<commit_before>use crate::{KeyError, ReadOnly, StringKey};
use std::convert::TryInto;
use std::ffi::{CStr, CString};

pub trait ReadableKey {
    type Value;
    type Duplicate;

    fn as_ref(&self) -> &elektra_sys::Key;
    fn get_value(&self) -> Self::Value;

    /// Return a duplicate of the key.
    fn duplicate(&self) -> Self::Duplicate
    where
        Self::Duplicate: Sized;

    /// Construct a new key from a raw key pointer
    fn from_ptr(ptr: *mut elektra_sys::Key) -> Self
    where
        Self: Sized;

    // TODO keyCopy?

    // keyname methods

    /// Return the name of the key as a borrowed slice.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyName(self.as_ref())) };
        c_str.to_str().unwrap()
    }

    /// Return the basename of the key as a borrowed slice.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    fn get_basename(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyBaseName(self.as_ref())) };
        c_str.to_str().unwrap()
    }

    /// Calculates number of bytes needed to store basename of key.
    fn get_basename_size(&self) -> isize {
        unsafe { elektra_sys::keyGetBaseNameSize(self.as_ref()) }
    }

    /// Bytes needed to store the key name including user domain and ending NULL.
    fn get_fullname_size(&self) -> usize {
        unsafe {
            elektra_sys::keyGetFullNameSize(self.as_ref())
                .try_into()
                .unwrap()
        }
    }

    /// Get key full name, including the user domain name.
    /// # Panics
    /// Panics if the underlying c_string contains interior nul bytes
    /// or cannot be converted to UTF-8
    fn get_fullname(&self) -> String {
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_fullname_size());

        let ret_val = unsafe {
            elektra_sys::keyGetFullName(
                self.as_ref(),
                vec.as_mut_ptr() as *mut std::os::raw::c_char,
                vec.capacity(),
            )
        };
        unsafe { vec.set_len(ret_val.try_into().unwrap()) };
        CStr::from_bytes_with_nul(&vec)
            .unwrap()
            .to_str()
            .unwrap()
            .to_owned()
    }

    fn get_namespace(&self) -> u32 {
        unsafe { elektra_sys::keyGetNamespace(self.as_ref()) as u32 }
    }

    /// Determines if the key is in the spec namespace
    fn is_spec(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_SPEC
    }

    /// Determines if the key is in the dir namespace
    fn is_dir(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_DIR
    }

    /// Determines if the key is in the proc namespace
    fn is_proc(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_PROC
    }

    /// Determines if the key is in the user namespace
    fn is_user(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_USER
    }

    /// Determines if the key is in the system namespace
    fn is_system(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_SYSTEM
    }

    /// Determines if the key is in the dir namespace
    fn is_cascading(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_CASCADING
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.as_ref()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val.try_into().unwrap()
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.as_ref()) == 1 }
    }

    /// Returns true if the key has a string value.
    fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.as_ref()) == 1 }
    }

    /// Returns true if other is below self
    /// # Examples
    /// ```
    /// use elektra::{StringKey,WriteableKey,ReadableKey};
    /// let key = StringKey::new("user/sw/app").unwrap();
    /// let key2 = StringKey::new("user/sw/app/folder/key").unwrap();
    /// assert!(key2.is_below(&key));
    /// ```
    fn is_below(&self, other: &Self) -> bool
    where
        Self: Sized,
    {
        unsafe { elektra_sys::keyIsBelow(other.as_ref(), self.as_ref()) == 1 }
    }

    /// Returns true if other is *directly* below self
    /// # Examples
    /// ```
    /// use elektra::{StringKey,WriteableKey,ReadableKey};
    /// let key = StringKey::new("user/sw/app").unwrap();
    /// let key2 = StringKey::new("user/sw/app/key").unwrap();
    /// assert!(key2.is_direct_below(&key));
    /// ```
    fn is_direct_below(&self, other: &Self) -> bool
    where
        Self: Sized,
    {
        unsafe { elektra_sys::keyIsDirectBelow(other.as_ref(), self.as_ref()) == 1 }
    }

    /// Returns true if the key is inactive.
    /// In Elektra terminology a hierarchy of keys is inactive if the
    /// rootkey's basename starts with '.'. So a key is also inactive
    /// if it is below an inactive key. For example, `user/key/.hidden`
    /// is inactive and so is `user/.hidden/below`.
    fn is_inactive(&self) -> bool {
        unsafe { elektra_sys::keyIsInactive(self.as_ref()) == 1 }
    }

    // TODO: If the key that held the metakey is dropped, the return value is still valid,
    // according to current semantics, but the pointer it holds is invalid.
    /// Returns the metadata with the given metaname
    fn get_meta(&self, metaname: &str) -> Result<ReadOnly<StringKey>, KeyError>
    where
        Self: Sized
    {
        let cstr = CString::new(metaname).unwrap();
        let key_ptr = unsafe { elektra_sys::keyGetMeta(self.as_ref(), cstr.as_ptr()) };
        if key_ptr.is_null() {
            Err(KeyError::NotFound)
        } else {
            let key: ReadOnly<StringKey> = ReadOnly::from_ptr(key_ptr as *mut elektra_sys::Key);
            Ok(key)
        }
    }
}
<commit_msg>Rust: Fix possible usage of invalid pointer<commit_after>use crate::{KeyError, ReadOnly, StrKey};
use std::convert::TryInto;
use std::ffi::{CStr, CString};

pub trait ReadableKey {
    type Value;
    type Duplicate;

    fn as_ref(&self) -> &elektra_sys::Key;
    fn get_value(&self) -> Self::Value;

    /// Return a duplicate of the key.
    fn duplicate(&self) -> Self::Duplicate
    where
        Self::Duplicate: Sized;

    /// Construct a new key from a raw key pointer
    fn from_ptr(ptr: *mut elektra_sys::Key) -> Self
    where
        Self: Sized;

    // TODO keyCopy?

    // keyname methods

    /// Return the name of the key as a borrowed slice.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    fn get_name(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyName(self.as_ref())) };
        c_str.to_str().unwrap()
    }

    /// Return the basename of the key as a borrowed slice.
    /// # Panics
    /// Panics if the underlying string cannot be converted to UTF-8.
    fn get_basename(&self) -> &str {
        let c_str = unsafe { CStr::from_ptr(elektra_sys::keyBaseName(self.as_ref())) };
        c_str.to_str().unwrap()
    }

    /// Calculates number of bytes needed to store basename of key.
    fn get_basename_size(&self) -> isize {
        unsafe { elektra_sys::keyGetBaseNameSize(self.as_ref()) }
    }

    /// Bytes needed to store the key name including user domain and ending NULL.
    fn get_fullname_size(&self) -> usize {
        unsafe {
            elektra_sys::keyGetFullNameSize(self.as_ref())
                .try_into()
                .unwrap()
        }
    }

    /// Get key full name, including the user domain name.
    /// # Panics
    /// Panics if the underlying c_string contains interior nul bytes
    /// or cannot be converted to UTF-8
    fn get_fullname(&self) -> String {
        let mut vec: Vec<u8> = Vec::with_capacity(self.get_fullname_size());

        let ret_val = unsafe {
            elektra_sys::keyGetFullName(
                self.as_ref(),
                vec.as_mut_ptr() as *mut std::os::raw::c_char,
                vec.capacity(),
            )
        };
        unsafe { vec.set_len(ret_val.try_into().unwrap()) };
        CStr::from_bytes_with_nul(&vec)
            .unwrap()
            .to_str()
            .unwrap()
            .to_owned()
    }

    fn get_namespace(&self) -> u32 {
        unsafe { elektra_sys::keyGetNamespace(self.as_ref()) as u32 }
    }

    /// Determines if the key is in the spec namespace
    fn is_spec(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_SPEC
    }

    /// Determines if the key is in the dir namespace
    fn is_dir(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_DIR
    }

    /// Determines if the key is in the proc namespace
    fn is_proc(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_PROC
    }

    /// Determines if the key is in the user namespace
    fn is_user(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_USER
    }

    /// Determines if the key is in the system namespace
    fn is_system(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_SYSTEM
    }

    /// Determines if the key is in the dir namespace
    fn is_cascading(&self) -> bool {
        self.get_namespace() == elektra_sys::KEY_NS_CASCADING
    }

    // keyvalue methds

    // Omitted keyValue() due to return value of void pointer, which cannot be used safely in Rust

    /// Returns the number of bytes needed to store the key value, including the
    /// NULL terminator.
    fn get_value_size(&self) -> usize {
        let ret_val = unsafe { elektra_sys::keyGetValueSize(self.as_ref()) };
        // keyGetValueSize returns -1 on null pointers, but we can be sure self.ptr is valid
        // so this conversion is safe
        ret_val.try_into().unwrap()
    }

    // keytest methods

    /// Returns true if the key has a binary value.
    fn is_binary(&self) -> bool {
        unsafe { elektra_sys::keyIsBinary(self.as_ref()) == 1 }
    }

    /// Returns true if the key has a string value.
    fn is_string(&self) -> bool {
        unsafe { elektra_sys::keyIsString(self.as_ref()) == 1 }
    }

    /// Returns true if other is below self
    /// # Examples
    /// ```
    /// use elektra::{StringKey,WriteableKey,ReadableKey};
    /// let key = StringKey::new("user/sw/app").unwrap();
    /// let key2 = StringKey::new("user/sw/app/folder/key").unwrap();
    /// assert!(key2.is_below(&key));
    /// ```
    fn is_below(&self, other: &Self) -> bool
    where
        Self: Sized,
    {
        unsafe { elektra_sys::keyIsBelow(other.as_ref(), self.as_ref()) == 1 }
    }

    /// Returns true if other is *directly* below self
    /// # Examples
    /// ```
    /// use elektra::{StringKey,WriteableKey,ReadableKey};
    /// let key = StringKey::new("user/sw/app").unwrap();
    /// let key2 = StringKey::new("user/sw/app/key").unwrap();
    /// assert!(key2.is_direct_below(&key));
    /// ```
    fn is_direct_below(&self, other: &Self) -> bool
    where
        Self: Sized,
    {
        unsafe { elektra_sys::keyIsDirectBelow(other.as_ref(), self.as_ref()) == 1 }
    }

    /// Returns true if the key is inactive.
    /// In Elektra terminology a hierarchy of keys is inactive if the
    /// rootkey's basename starts with '.'. So a key is also inactive
    /// if it is below an inactive key. For example, `user/key/.hidden`
    /// is inactive and so is `user/.hidden/below`.
    fn is_inactive(&self) -> bool {
        unsafe { elektra_sys::keyIsInactive(self.as_ref()) == 1 }
    }

    /// Returns the metadata with the given metaname
    fn get_meta(&self, metaname: &str) -> Result<StrKey<'_>, KeyError>
    where
        Self: Sized,
    {
        let cstr = CString::new(metaname).unwrap();
        let key_ptr = unsafe { elektra_sys::keyGetMeta(self.as_ref(), cstr.as_ptr()) };
        if key_ptr.is_null() {
            Err(KeyError::NotFound)
        } else {
            let key = StrKey::from_ptr(key_ptr as *mut elektra_sys::Key);
            Ok(key)
        }
    }
}
<|endoftext|>


<commit_before>//! Scan the file looking for pointer-sized values that fall within an
//! executable section. Then, step backwards and ensure that the target
//! looks like either:
//!
//!   1. the end of a function, or
//!   2. filler between functions
//!
//! This analysis pass should be particularly useful for finding callbacks,
//! such as the start address passed to `CreateThread`.
//!
//! TODO: but doesn't help find callbacks referenced relatively - need
//! disassembly for this.
//!
//! This analysis pass is also good at handling global vtables.
//! Its especially important when CFGuard metadata is not present.
//!
//! Assumes:
//!   - pointers are 32-bits on x32 and 64-bits on x64 (*not* 32-bits on x64)

use anyhow::Result;
use byteorder::ByteOrder;

use crate::{aspace::AddressSpace, loader::pe::PE, module::Permissions, VA};

pub fn find_pe_nonrelocated_executable_pointers(pe: &PE) -> Result<Vec<VA>> {
    let mut candidates: Vec<VA> = vec![];

    // look for hardcoded pointers into the executable section of the PE.
    // note: this often finds jump tables, too. more filtering is below.
    // note: also finds many exception handlers. see filtering below.
    for section in pe.module.sections.iter() {
        let vstart: VA = section.virtual_range.start;
        let vsize = (section.virtual_range.end - section.virtual_range.start) as usize;
        let sec_buf = pe.module.address_space.read_bytes(vstart, vsize)?;

        if let crate::module::Arch::X64 = pe.module.arch {
            candidates.extend(
                sec_buf
                    .windows(8)
                    .map(|b| byteorder::LittleEndian::read_u64(b) as VA)
                    .filter(|&va| pe.module.probe_va(va, Permissions::X)),
            )
        } else {
            candidates.extend(
                sec_buf
                    .windows(4)
                    .map(|b| byteorder::LittleEndian::read_u32(b) as VA)
                    .filter(|&va| pe.module.probe_va(va, Permissions::X)),
            )
        }
    }

    // CC debug filler, x86win_patterns.xml#L4
    const CC: u8 = 0xCC;
    // NOP filler, x86win_patterns.xml#L6
    const NOP: u8 = 0x90;
    // RET(N) of prior function, x86win_patterns.xml#L7
    const RET: u8 = 0xC3;

    // now, assert that the prior byte must be a either a RET or filler byte.
    // this should filter out almost all jump tables, etc.
    // should also filter out almost all exception handlers, too.
    Ok(candidates
        .into_iter()
        .filter(|&va| {
            if let Ok(b) = pe.module.address_space.read_u8(va - 1) {
                matches!(b, CC | NOP | RET)
            } else {
                false
            }
        })
        .collect())
}
<commit_msg>analysis: pointers: ignore candidates that are themselves valid pointers<commit_after>//! Scan the file looking for pointer-sized values that fall within an
//! executable section. Then, step backwards and ensure that the target
//! looks like either:
//!
//!   1. the end of a function, or
//!   2. filler between functions
//!
//! This analysis pass should be particularly useful for finding callbacks,
//! such as the start address passed to `CreateThread`.
//!
//! TODO: but doesn't help find callbacks referenced relatively - need
//! disassembly for this.
//!
//! This analysis pass is also good at handling global vtables.
//! Its especially important when CFGuard metadata is not present.
//!
//! Assumes:
//!   - pointers are 32-bits on x32 and 64-bits on x64 (*not* 32-bits on x64)

use anyhow::Result;
use byteorder::ByteOrder;

use crate::{aspace::AddressSpace, loader::pe::PE, module::Permissions, VA};

pub fn find_pe_nonrelocated_executable_pointers(pe: &PE) -> Result<Vec<VA>> {
    let mut candidates: Vec<VA> = vec![];

    // look for hardcoded pointers into the executable section of the PE.
    // note: this often finds jump tables, too. more filtering is below.
    // note: also finds many exception handlers. see filtering below.
    for section in pe.module.sections.iter() {
        let vstart: VA = section.virtual_range.start;
        let vsize = (section.virtual_range.end - section.virtual_range.start) as usize;
        let sec_buf = pe.module.address_space.read_bytes(vstart, vsize)?;

        if let crate::module::Arch::X64 = pe.module.arch {
            candidates.extend(
                sec_buf
                    .windows(8)
                    .map(|b| byteorder::LittleEndian::read_u64(b) as VA)
                    .filter(|&va| pe.module.probe_va(va, Permissions::X)),
            )
        } else {
            candidates.extend(
                sec_buf
                    .windows(4)
                    .map(|b| byteorder::LittleEndian::read_u32(b) as VA)
                    .filter(|&va| pe.module.probe_va(va, Permissions::X)),
            )
        }
    }

    // CC debug filler, x86win_patterns.xml#L4
    const CC: u8 = 0xCC;
    // NOP filler, x86win_patterns.xml#L6
    const NOP: u8 = 0x90;
    // RET(N) of prior function, x86win_patterns.xml#L7
    const RET: u8 = 0xC3;

    // TODO: ensure these are not pointers themselves

    // now, assert that the prior byte must be a either a RET or filler byte.
    // this should filter out almost all jump tables, etc.
    // should also filter out almost all exception handlers, too.
    Ok(candidates
        .into_iter()
        .filter(|&va| {
            if let Ok(b) = pe.module.address_space.read_u8(va - 1) {
                matches!(b, CC | NOP | RET)
            } else {
                false
            }
        })
        .filter(|&va| {
            if let Ok(ptr) = pe.module.read_va_at_va(va) {
                // the candidate is valid pointer, so its probably not an instruction.
                !pe.module.probe_va(ptr, Permissions::R)
            } else {
                true
            }
        })
        .collect())
}
<|endoftext|>


<commit_before>use std::fmt;

use super::lazy_buffer::LazyBuffer;

/// An iterator to iterate through all the `k`-length combinations in an iterator.
///
/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Combinations<I: Iterator> {
    k: usize,
    indices: Vec<usize>,
    pool: LazyBuffer<I>,
    first: bool,
}

impl<I> Clone for Combinations<I>
    where I: Clone + Iterator,
          I::Item: Clone,
{
    clone_fields!(k, indices, pool, first);
}

impl<I> fmt::Debug for Combinations<I>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(Combinations, k, indices, pool, first);
}

/// Create a new `Combinations` from a clonable iterator.
pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
    where I: Iterator
{
    let mut pool: LazyBuffer<I> = LazyBuffer::new(iter);

    for _ in 0..k {
        if !pool.get_next() {
            break;
        }
    }

    Combinations {
        k: k,
        indices: (0..k).collect(),
        pool: pool,
        first: true,
    }
}

impl<I> Iterator for Combinations<I>
    where I: Iterator,
          I::Item: Clone
{
    type Item = Vec<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        let mut pool_len = self.pool.len();

        if self.first {
            if self.pool.is_done() {
                return None;
            }
            self.first = false;
        } else if self.k == 0 {
            return None;
        } else {
            // Scan from the end, looking for an index to increment
            let mut i: usize = self.k - 1;

            // Check if we need to consume more from the iterator
            if self.indices[i] == pool_len - 1 && !self.pool.is_done() {
                if self.pool.get_next() {
                    pool_len += 1;
                }
            }

            while self.indices[i] == i + pool_len - self.k {
                if i > 0 {
                    i -= 1;
                } else {
                    // Reached the last combination
                    return None;
                }
            }

            // Increment index, and reset the ones to its right
            self.indices[i] += 1;
            let mut j = i + 1;
            while j < self.k {
                self.indices[j] = self.indices[j - 1] + 1;
                j += 1;
            }
        }

        // Create result vector based on the indices
        let mut result = Vec::with_capacity(self.k);
        for i in self.indices.iter() {
            result.push(self.pool[*i].clone());
        }
        Some(result)
    }
}
<commit_msg>Avoid redundant `Combinations::k`<commit_after>use std::fmt;

use super::lazy_buffer::LazyBuffer;

/// An iterator to iterate through all the `k`-length combinations in an iterator.
///
/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Combinations<I: Iterator> {
    indices: Vec<usize>,
    pool: LazyBuffer<I>,
    first: bool,
}

impl<I> Clone for Combinations<I>
    where I: Clone + Iterator,
          I::Item: Clone,
{
    clone_fields!(indices, pool, first);
}

impl<I> fmt::Debug for Combinations<I>
    where I: Iterator + fmt::Debug,
          I::Item: fmt::Debug,
{
    debug_fmt_fields!(Combinations, indices, pool, first);
}

/// Create a new `Combinations` from a clonable iterator.
pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
    where I: Iterator
{
    let mut pool: LazyBuffer<I> = LazyBuffer::new(iter);

    for _ in 0..k {
        if !pool.get_next() {
            break;
        }
    }

    Combinations {
        indices: (0..k).collect(),
        pool: pool,
        first: true,
    }
}

impl<I> Iterator for Combinations<I>
    where I: Iterator,
          I::Item: Clone
{
    type Item = Vec<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        let mut pool_len = self.pool.len();

        if self.first {
            if self.pool.is_done() {
                return None;
            }
            self.first = false;
        } else if self.indices.len() == 0 {
            return None;
        } else {
            // Scan from the end, looking for an index to increment
            let mut i: usize = self.indices.len() - 1;

            // Check if we need to consume more from the iterator
            if self.indices[i] == pool_len - 1 && !self.pool.is_done() {
                if self.pool.get_next() {
                    pool_len += 1;
                }
            }

            while self.indices[i] == i + pool_len - self.indices.len() {
                if i > 0 {
                    i -= 1;
                } else {
                    // Reached the last combination
                    return None;
                }
            }

            // Increment index, and reset the ones to its right
            self.indices[i] += 1;
            let mut j = i + 1;
            while j < self.indices.len() {
                self.indices[j] = self.indices[j - 1] + 1;
                j += 1;
            }
        }

        // Create result vector based on the indices
        let mut result = Vec::with_capacity(self.indices.len());
        for i in self.indices.iter() {
            result.push(self.pool[*i].clone());
        }
        Some(result)
    }
}
<|endoftext|>


<commit_before>pub use self::token::{Symbol, Token};
pub use self::lexer::Lexer;
pub use self::parser::Parser;

mod ast;
pub mod lexer;
mod parser;
mod token;
<commit_msg>Remove unnecessary pub specification<commit_after>pub use self::token::{Symbol, Token};
pub use self::lexer::Lexer;
pub use self::parser::Parser;

mod ast;
mod lexer;
mod parser;
mod token;
<|endoftext|>


<commit_before>//! Advertizes the capabilities of the LSP Server.

use crate::semantic_tokens;

use lsp_types::{
    CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability,
    CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions,
    FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions,
    RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability,
    SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions,
    ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
    TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
};

pub fn server_capabilities() -> ServerCapabilities {
    ServerCapabilities {
        text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
            open_close: Some(true),
            change: Some(TextDocumentSyncKind::Incremental),
            will_save: None,
            will_save_wait_until: None,
            save: Some(SaveOptions::default()),
        })),
        hover_provider: Some(true),
        completion_provider: Some(CompletionOptions {
            resolve_provider: None,
            trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        signature_help_provider: Some(SignatureHelpOptions {
            trigger_characters: Some(vec!["(".to_string(), ",".to_string()]),
            retrigger_characters: None,
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        declaration_provider: None,
        definition_provider: Some(true),
        type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
        implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
        references_provider: Some(true),
        document_highlight_provider: Some(true),
        document_symbol_provider: Some(true),
        workspace_symbol_provider: Some(true),
        code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
            // Advertise support for all built-in CodeActionKinds
            code_action_kinds: Some(vec![
                lsp_types::code_action_kind::EMPTY.to_string(),
                lsp_types::code_action_kind::QUICKFIX.to_string(),
                lsp_types::code_action_kind::REFACTOR.to_string(),
                lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
                lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
                lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
                lsp_types::code_action_kind::SOURCE.to_string(),
                lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
            ]),
            work_done_progress_options: Default::default(),
        })),
        code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
        document_formatting_provider: Some(true),
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
            first_trigger_character: "=".to_string(),
            more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
        }),
        selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
        semantic_highlighting: None,
        folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
        rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
            prepare_provider: Some(true),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        })),
        document_link_provider: None,
        color_provider: None,
        execute_command_provider: None,
        workspace: None,
        call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
        semantic_tokens_provider: Some(
            SemanticTokensOptions {
                legend: SemanticTokensLegend {
                    token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(),
                    token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(),
                },

                document_provider: Some(SemanticTokensDocumentProvider::Bool(true)),
                range_provider: Some(true),
                work_done_progress_options: Default::default(),
            }
            .into(),
        ),
        experimental: Default::default(),
    }
}
<commit_msg>Make incremental sync opt-in<commit_after>//! Advertizes the capabilities of the LSP Server.
use std::env;

use crate::semantic_tokens;

use lsp_types::{
    CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability,
    CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions,
    FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions,
    RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability,
    SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions,
    ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
    TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
};

pub fn server_capabilities() -> ServerCapabilities {
    ServerCapabilities {
        text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
            open_close: Some(true),
            change: Some(if env::var("RA_PROFILE").is_ok() {
                TextDocumentSyncKind::Incremental
            } else {
                TextDocumentSyncKind::Full
            }),
            will_save: None,
            will_save_wait_until: None,
            save: Some(SaveOptions::default()),
        })),
        hover_provider: Some(true),
        completion_provider: Some(CompletionOptions {
            resolve_provider: None,
            trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        signature_help_provider: Some(SignatureHelpOptions {
            trigger_characters: Some(vec!["(".to_string(), ",".to_string()]),
            retrigger_characters: None,
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        declaration_provider: None,
        definition_provider: Some(true),
        type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
        implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
        references_provider: Some(true),
        document_highlight_provider: Some(true),
        document_symbol_provider: Some(true),
        workspace_symbol_provider: Some(true),
        code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
            // Advertise support for all built-in CodeActionKinds
            code_action_kinds: Some(vec![
                lsp_types::code_action_kind::EMPTY.to_string(),
                lsp_types::code_action_kind::QUICKFIX.to_string(),
                lsp_types::code_action_kind::REFACTOR.to_string(),
                lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
                lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
                lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
                lsp_types::code_action_kind::SOURCE.to_string(),
                lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
            ]),
            work_done_progress_options: Default::default(),
        })),
        code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
        document_formatting_provider: Some(true),
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
            first_trigger_character: "=".to_string(),
            more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
        }),
        selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
        semantic_highlighting: None,
        folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
        rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
            prepare_provider: Some(true),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        })),
        document_link_provider: None,
        color_provider: None,
        execute_command_provider: None,
        workspace: None,
        call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
        semantic_tokens_provider: Some(
            SemanticTokensOptions {
                legend: SemanticTokensLegend {
                    token_types: semantic_tokens::SUPPORTED_TYPES.to_vec(),
                    token_modifiers: semantic_tokens::SUPPORTED_MODIFIERS.to_vec(),
                },

                document_provider: Some(SemanticTokensDocumentProvider::Bool(true)),
                range_provider: Some(true),
                work_done_progress_options: Default::default(),
            }
            .into(),
        ),
        experimental: Default::default(),
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
extern crate itertools;
use self::itertools::Itertools;
extern crate crossbeam;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = fetch_tag!(self.tiff, Tag::Make, "ARW: Couldn't find Make").get_str();
    let model = fetch_tag!(self.tiff, Tag::Model, "ARW: Couldn't find Model").get_str();
    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.identify());
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth, "ARW: Couldn't find width").get_u16(0) as u32;
    let height = fetch_tag!(raw, Tag::ImageLength, "ARW: Couldn't find height").get_u16(0) as u32;
    let offset = fetch_tag!(raw, Tag::StripOffsets, "ARW: Couldn't find offset").get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts, "ARW: Couldn't find byte count").get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression, "ARW: Couldn't find Compression").get_u16(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample, "ARW: Couldn't find bps").get_u16(0) as u32
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => decode_16le(src, width as usize, height as usize),
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          ArwDecoder::decode_arw1(src, width, height)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width, height, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn decode_arw1(buf: &[u8], width: u32, height: u32) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];

    buffer[0] = buf[0] as u16; // Shut up the warnings for now

    buffer
  }

  fn decode_arw2(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    // Simple dual threaded implementation of the arw decode that could be
    // generalized into more threads easily. In practice doing much more than
    // two threads is probably suboptimal on most hardware. Could be worth a
    // shot though.
    let height1 = height/2;
    let height2 = height - height1;
    let split = (height1+1)*width;
    let src1 = &buf[0..(split as usize)];
    let src2 = &buf[(split as usize)..buf.len()];

    crossbeam::scope(|scope| {
      let handle1 = scope.spawn(move || {
        ArwDecoder::decode_arw2_slice(src1, width, height1, &curve)
      });
      let handle2 = scope.spawn(move || {
        ArwDecoder::decode_arw2_slice(src2, width, height2, &curve)
      });

      let mut out1 = handle1.join();
      let mut out2 = handle2.join();
      out1.append(&mut out2);
      out1
    })
  }

  fn decode_arw2_slice(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];
    let mut pump = BitPump::new(buf);

    for row in 0..height {
      // Process 16 pixels at a time in interleaved fashion
      let mut col = 0;
      let mut random = pump.peek_bits(24);
      while col < (width-30) {
        let max = pump.get_bits(11);
        let min = pump.get_bits(11);
        let imax = pump.get_bits(4);
        let imin = pump.get_bits(4);
        let mut sh = 0;
        while sh<4 && (0x80 << sh) <= (max - min) {sh = sh + 1;}
        for i in 0..16 {
          let val = if i == imax {
            max
          } else if i == imin {
            min
          } else {
            cmp::min(0x7ff,(pump.get_bits(7) << sh) + min)
          };
          buffer[(row*width+col+i*2) as usize] = curve.dither(val as u16, &mut random);
        }
        col += if (col & 1) != 0 {31} else {1};  // Skip to next 16 pixels
      }
    }

    buffer
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea, "ARW: Couldn't find private offset").get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN);
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset, "ARW: Couldn't find sony offset").get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength, "ARW: Couldn't find sony length").get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey, "ARW: Couldn't find sony key").get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN);
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u16(1) as f32, levels.get_u16(0) as f32, levels.get_u16(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u16(0) as f32, levels.get_u16(1) as f32, levels.get_u16(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve, "ARW: Couldn't find sony curve");
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u16(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Make sure we always have space for the final bytes even if the buffer
    // isn't a multiple of 4
    let mut out = vec![0;length+4];
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    for i in (0..length).step(4) {
      let p = i/4 + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i) ^ pad[p & 127];
      let bytes: [u8; 4] = unsafe { transmute(output.to_le()) };
      out[i]   = bytes[0];
      out[i+1] = bytes[1];
      out[i+2] = bytes[2];
      out[i+3] = bytes[3];
    }
    out
  }
}
<commit_msg>ARW: generalized N threads decoding for ARW2<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
extern crate itertools;
use self::itertools::Itertools;
extern crate crossbeam;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn identify(&self) -> Result<&Camera, String> {
    let make = fetch_tag!(self.tiff, Tag::Make, "ARW: Couldn't find Make").get_str();
    let model = fetch_tag!(self.tiff, Tag::Model, "ARW: Couldn't find Model").get_str();
    self.rawloader.check_supported(make, model)
  }

  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.identify());
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth, "ARW: Couldn't find width").get_u16(0) as u32;
    let height = fetch_tag!(raw, Tag::ImageLength, "ARW: Couldn't find height").get_u16(0) as u32;
    let offset = fetch_tag!(raw, Tag::StripOffsets, "ARW: Couldn't find offset").get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts, "ARW: Couldn't find byte count").get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression, "ARW: Couldn't find Compression").get_u16(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample, "ARW: Couldn't find bps").get_u16(0) as u32
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => decode_16le(src, width as usize, height as usize),
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          ArwDecoder::decode_arw1(src, width, height)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width, height, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn decode_arw1(buf: &[u8], width: u32, height: u32) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];

    buffer[0] = buf[0] as u16; // Shut up the warnings for now

    buffer
  }

  fn decode_arw2(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    // Speedup doesn't currently seem worthwhile above 2 threads, probably because
    // of too much copying
    let threads = 2;
    if threads < 2 || height < threads {
      return ArwDecoder::decode_arw2_slice(buf, width, height, &curve);
    }

    let mut heights = Vec::new();
    let split = height/threads;
    let mut height_split = 0;
    for i in 0..threads {
      let start = height_split;
      height_split += split;
      let end = if i == threads-1 {
        height
      } else {
        height_split -1
      };
      heights.push((start, end));
    }

    crossbeam::scope(|scope| {
      let mut handles = Vec::new();
      for (start, end) in heights {
        let src = &buf[((start*width) as usize)..buf.len()];
        let handle = scope.spawn(move || {
          ArwDecoder::decode_arw2_slice(src, width, end-start+1, &curve)
        });
        handles.push(handle);
      }

      let mut out = Vec::new();
      for h in handles {
        let mut other = h.join();
        out.append(&mut other);
      }
      out
    })
  }

  fn decode_arw2_slice(buf: &[u8], width: u32, height: u32, curve: &LookupTable) -> Vec<u16> {
    let mut buffer: Vec<u16> = vec![0; (width*height) as usize];
    let mut pump = BitPump::new(buf);

    for row in 0..height {
      // Process 16 pixels at a time in interleaved fashion
      let mut col = 0;
      let mut random = pump.peek_bits(24);
      while col < (width-30) {
        let max = pump.get_bits(11);
        let min = pump.get_bits(11);
        let imax = pump.get_bits(4);
        let imin = pump.get_bits(4);
        let mut sh = 0;
        while sh<4 && (0x80 << sh) <= (max - min) {sh = sh + 1;}
        for i in 0..16 {
          let val = if i == imax {
            max
          } else if i == imin {
            min
          } else {
            cmp::min(0x7ff,(pump.get_bits(7) << sh) + min)
          };
          buffer[(row*width+col+i*2) as usize] = curve.dither(val as u16, &mut random);
        }
        col += if (col & 1) != 0 {31} else {1};  // Skip to next 16 pixels
      }
    }

    buffer
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea, "ARW: Couldn't find private offset").get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN);
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset, "ARW: Couldn't find sony offset").get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength, "ARW: Couldn't find sony length").get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey, "ARW: Couldn't find sony key").get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN);
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u16(1) as f32, levels.get_u16(0) as f32, levels.get_u16(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u16(0) as f32, levels.get_u16(1) as f32, levels.get_u16(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve, "ARW: Couldn't find sony curve");
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u16(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Make sure we always have space for the final bytes even if the buffer
    // isn't a multiple of 4
    let mut out = vec![0;length+4];
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    for i in (0..length).step(4) {
      let p = i/4 + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i) ^ pad[p & 127];
      let bytes: [u8; 4] = unsafe { transmute(output.to_le()) };
      out[i]   = bytes[0];
      out[i+1] = bytes[1];
      out[i+2] = bytes[2];
      out[i+3] = bytes[3];
    }
    out
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::env;
use std::process::{Stdio, exit};

use tokio::io::AsyncWriteExt;
use tokio::process::{Command, ChildStdin};

/// The environment variable that is set to indicate that the current process is a server process
pub const RENDERER_PROCESS_ENV_VAR: &str = "RUN_TURTLE_CANVAS";

#[derive(Debug)]
pub struct RendererServerProcess {
    /// A handle to the stdin of the child process
    child_stdin: ChildStdin,
}

impl RendererServerProcess {
    /// Spawn a new process for the renderer
    pub async fn spawn() -> Self {
        let current_exe = env::current_exe()
            .expect("Could not read path of the currently running executable");

        // The new process is the same executable as this process but with a special environment
        // variable passed in
        let mut child = Command::new(current_exe)
            .env(RENDERER_PROCESS_ENV_VAR, "true")
            // Pipe input so we can communicate with the spawned process
            //
            // stdout/stderr will be inherited from the current process
            .stdin(Stdio::piped())
            .spawn()
            .expect("failed to start separate process for renderer");

        let child_stdin = child.stdin.take()
            .expect("renderer process was not spawned with a handle to stdin");

        // Ensure the child process is spawned in the runtime so it can
        // make progress on its own while we send it input.
        tokio::spawn(async {
            // We want to await in a separate task because otherwise the current task would not
            // make any progress until the child process is complete
            let status = child.await
                .expect("child process encountered an error");

            if status.success() {
                // The window/renderer process was closed normally
                exit(0);
            } else {
                // Something went wrong, likely the other thread panicked
                exit(1);
            }
        });

        Self {child_stdin}
    }

    /// Writes the given bytes followed by a newline b'\n' to the stdin of the process
    ///
    /// Unlike `std::io::Write::write`, this returns an error in the case all of the bytes could
    /// not be written for some reason.
    pub async fn writeln<S: AsRef<[u8]>>(&mut self, data: S) -> io::Result<()> {
        let data = data.as_ref();
        let bytes_written = self.child_stdin.write(data).await?;
        self.child_stdin.write_u8(b'\n').await?;

        if bytes_written == data.len() {
            Ok(())

        } else {
            // From the docs: "This typically means that an operation could only succeed if it
            // wrote a particular number of bytes but only a smaller number of bytes could be
            // written."
            let err_msg = format!("expected to write `{}` bytes, but actually wrote `{}`", data.len(), bytes_written);
            Err(io::Error::new(io::ErrorKind::WriteZero, err_msg))
        }
    }
}
<commit_msg>Waiting for renderer process to finish in Drop for RendererServerProcess<commit_after>use std::io;
use std::env;
use std::process::{Stdio, exit};

use tokio::{
    runtime,
    io::AsyncWriteExt,
    task::JoinHandle,
    process::{Command, ChildStdin},
};

/// The environment variable that is set to indicate that the current process is a server process
pub const RENDERER_PROCESS_ENV_VAR: &str = "RUN_TURTLE_CANVAS";

#[derive(Debug)]
pub struct RendererServerProcess {
    task_handle: Option<JoinHandle<()>>,
    /// A handle to the stdin of the child process
    child_stdin: ChildStdin,
}

impl RendererServerProcess {
    /// Spawn a new process for the renderer
    pub async fn spawn() -> Self {
        let current_exe = env::current_exe()
            .expect("Could not read path of the currently running executable");

        // The new process is the same executable as this process but with a special environment
        // variable passed in
        let mut child = Command::new(current_exe)
            .env(RENDERER_PROCESS_ENV_VAR, "true")
            // Pipe input so we can communicate with the spawned process
            //
            // stdout/stderr will be inherited from the current process
            .stdin(Stdio::piped())
            .spawn()
            .expect("failed to start separate process for renderer");

        let child_stdin = child.stdin.take()
            .expect("renderer process was not spawned with a handle to stdin");

        // Ensure the child process is spawned in the runtime so it can
        // make progress on its own while we send it input.
        let task_handle = Some(tokio::spawn(async {
            // We want to await in a separate task because otherwise the current task would not
            // make any progress until the child process is complete
            let status = child.await
                .expect("child process encountered an error");

            if status.success() {
                // The window/renderer process was closed normally
                exit(0);
            } else {
                // Something went wrong, likely the other thread panicked
                exit(1);
            }
        }));

        Self {task_handle, child_stdin}
    }

    /// Writes the given bytes followed by a newline b'\n' to the stdin of the process
    ///
    /// Unlike `std::io::Write::write`, this returns an error in the case all of the bytes could
    /// not be written for some reason.
    pub async fn writeln<S: AsRef<[u8]>>(&mut self, data: S) -> io::Result<()> {
        let data = data.as_ref();
        let bytes_written = self.child_stdin.write(data).await?;
        self.child_stdin.write_u8(b'\n').await?;

        if bytes_written == data.len() {
            Ok(())

        } else {
            // From the docs: "This typically means that an operation could only succeed if it
            // wrote a particular number of bytes but only a smaller number of bytes could be
            // written."
            let err_msg = format!("expected to write `{}` bytes, but actually wrote `{}`", data.len(), bytes_written);
            Err(io::Error::new(io::ErrorKind::WriteZero, err_msg))
        }
    }
}

impl Drop for RendererServerProcess {
    fn drop(&mut self) {
        use std::thread;

        // If the current thread is panicking, we want to abort right away
        // because otherwise there is code in the rendering thread that will call
        // process::exit(0) and then the exit code will be 0 instead of 1
        if thread::panicking() {
            exit(1);
        }

        // If this is just a normal ending of the main thread, we want to leave the renderer
        // running so that the user can see their drawing as long as they keep the window open
        let runtime = runtime::Handle::current();
        // This unwrap is safe because no struct gets dropped twice
        let task_handle = self.task_handle.take().unwrap();
        runtime.block_on(task_handle).unwrap_or_else(|_| {
            // If this returns an error, the other thread panicked
            exit(1);
        });
    }
}
<|endoftext|>


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

#![feature(rand, core)]

use std::fs::File;
use std::io::prelude::*;
use std::iter::repeat;
use std::path::Path;
use std::process::Command;
use std::__rand::{thread_rng, Rng};
use std::{char, env};

// creates a file with `fn main() { <random ident> }` and checks the
// compiler emits a span of the appropriate length (for the
// "unresolved name" message); currently just using the number of code
// points, but should be the number of graphemes (FIXME #7043)

fn random_char() -> char {
    let mut rng = thread_rng();
    // a subset of the XID_start Unicode table (ensuring that the
    // compiler doesn't fail with an "unrecognised token" error)
    let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
        1 => (0x41, 0x5a),
        2 => (0xf8, 0x1ba),
        3 => (0x1401, 0x166c),
        _ => (0x10400, 0x1044f)
    };

    char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let rustc = &args[1];
    let tmpdir = Path::new(&args[2]);
    let main_file = tmpdir.join("span_main.rs");

    for _ in 0..100 {
        let n = thread_rng().gen_range(3, 20);

        {
            let _ = write!(&mut File::create(&main_file).unwrap(),
                           "#![feature(non_ascii_idents)] fn main() {{ {} }}",
                           // random string of length n
                           (0..n).map(|_| random_char()).collect::<String>());
        }

        // rustc is passed to us with --out-dir and -L etc., so we
        // can't exec it directly
        let result = Command::new("sh")
                             .arg("-c")
                             .arg(&format!("{} {}",
                                           rustc,
                                           main_file.to_str()
                                                    .unwrap()))
                             .output().unwrap();

        let err = String::from_utf8_lossy(&result.stderr);

        // the span should end the line (e.g no extra ~'s)
        let expected_span = format!("^{}\n", repeat("~").take(n - 1)
                                                        .collect::<String>());
        assert!(err.contains(&expected_span));
    }

    // Test multi-column characters and tabs
    {
        let _ = write!(&mut File::create(&main_file).unwrap(),
                       r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
    }

    // Extra characters. Every line is preceded by `filename:lineno <actual code>`
    let offset = main_file.to_str().unwrap().len() + 3;

    let result = Command::new("sh")
                         .arg("-c")
                         .arg(format!("{} {}",
                                      rustc,
                                      main_file.display()))
                         .output().unwrap();

    let err = String::from_utf8_lossy(&result.stderr);

    // Test both the length of the snake and the leading spaces up to it

    // First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset)
    let expected_span = format!("\n{}^{}\n",
                                repeat(" ").take(offset + 7).collect::<String>(),
                                repeat("~").take(8).collect::<String>());
    assert!(err.contains(&expected_span));
    // Second snake is only 7 ~s long, with 36 preceding spaces,
    // because rustc counts chars() now rather than width(). This
    // is because width() functions are to be removed from
    // librustc_unicode
    let expected_span = format!("\n{}^{}\n",
                                repeat(" ").take(offset + 36).collect::<String>(),
                                repeat("~").take(7).collect::<String>());
    assert!(err.contains(&expected_span));
}
<commit_msg>rewrite span-length to include strings<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rand, core)]

use std::fs::File;
use std::io::prelude::*;
use std::iter::repeat;
use std::path::Path;
use std::process::Command;
use std::__rand::{thread_rng, Rng};
use std::{char, env};

// creates a file with `fn main() { <random ident> }` and checks the
// compiler emits a span of the appropriate length (for the
// "unresolved name" message); currently just using the number of code
// points, but should be the number of graphemes (FIXME #7043)

fn random_char() -> char {
    let mut rng = thread_rng();
    // a subset of the XID_start Unicode table (ensuring that the
    // compiler doesn't fail with an "unrecognised token" error)
    let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
        1 => (0x41, 0x5a),
        2 => (0xf8, 0x1ba),
        3 => (0x1401, 0x166c),
        _ => (0x10400, 0x1044f)
    };

    char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let rustc = &args[1];
    let tmpdir = Path::new(&args[2]);
    let main_file = tmpdir.join("span_main.rs");

    for _ in 0..100 {
        let n = thread_rng().gen_range(3, 20);

        {
            let _ = write!(&mut File::create(&main_file).unwrap(),
                           "#![feature(non_ascii_idents)] fn main() {{ {} }}",
                           // random string of length n
                           (0..n).map(|_| random_char()).collect::<String>());
        }

        // rustc is passed to us with --out-dir and -L etc., so we
        // can't exec it directly
        let result = Command::new("sh")
                             .arg("-c")
                             .arg(&format!("{} {}",
                                           rustc,
                                           main_file.to_str()
                                                    .unwrap()))
                             .output().unwrap();

        let err = String::from_utf8_lossy(&result.stderr);

        // the span should end the line (e.g no extra ^'s)
        let expected_span = format!("^{}\n", repeat("^").take(n - 1)
                                                        .collect::<String>());
        assert!(err.contains(&expected_span));
    }

    // Test multi-column characters and tabs
    {
        let _ = write!(&mut File::create(&main_file).unwrap(),
                       r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
    }

    // Extra characters. Every line is preceded by `filename:lineno <actual code>`
    let offset = main_file.to_str().unwrap().len() + 3;

    let result = Command::new("sh")
                         .arg("-c")
                         .arg(format!("{} {}",
                                      rustc,
                                      main_file.display()))
                         .output().unwrap();

    let err = String::from_utf8_lossy(&result.stderr);

    // Test both the length of the snake and the leading spaces up to it

    // First snake is 9 ^s long.
    let expected_1 = r#"
1 |> extern "路濫狼á́́" fn foo() {} extern "路濫狼á́" fn bar() {}
  |>        ^^^^^^^^^
"#;
    assert!(err.contains(&expected_1));

    // Second snake is only 8 ^s long, because rustc counts chars()
    // now rather than width(). This is because width() functions are
    // to be removed from librustc_unicode
    let expected_2 = r#"
1 |> extern "路濫狼á́́" fn foo() {} extern "路濫狼á́" fn bar() {}
  |>                                     ^^^^^^^^
"#;
    assert!(err.contains(&expected_2));
}
<|endoftext|>


<commit_before>/// A simple static assertion macro.
#[macro_export]
#[cfg_attr(stage0, allow_internal_unstable(type_ascription, underscore_const_names))]
#[cfg_attr(not(stage0), allow_internal_unstable(type_ascription))]
macro_rules! static_assert {
    ($test:expr) => {
        // Use the bool to access an array such that if the bool is false, the access
        // is out-of-bounds.
        #[allow(dead_code)]
        const _: () = [()][!($test: bool) as usize];
    }
}

/// Type size assertion. The first argument is a type and the second argument is its expected size.
#[macro_export]
#[cfg_attr(stage0, allow_internal_unstable(underscore_const_names))]
macro_rules! static_assert_size {
    ($ty:ty, $size:expr) => {
        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    }
}
<commit_msg>Stabilize underscore_const_names: stage0 -> bootstrap.<commit_after>/// A simple static assertion macro.
#[macro_export]
#[cfg_attr(bootstrap, allow_internal_unstable(type_ascription, underscore_const_names))]
#[cfg_attr(not(bootstrap), allow_internal_unstable(type_ascription))]
macro_rules! static_assert {
    ($test:expr) => {
        // Use the bool to access an array such that if the bool is false, the access
        // is out-of-bounds.
        #[allow(dead_code)]
        const _: () = [()][!($test: bool) as usize];
    }
}

/// Type size assertion. The first argument is a type and the second argument is its expected size.
#[macro_export]
#[cfg_attr(bootstrap, allow_internal_unstable(underscore_const_names))]
macro_rules! static_assert_size {
    ($ty:ty, $size:expr) => {
        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    }
}
<|endoftext|>


<commit_before>use eval::fixity::Fixity;
use eval::context_item::ContextItem;
use eval::built_in_function::BuiltInFunction;
use eval::eval_context::{EvalContext, EvalResult, EvalError};

pub fn setup_defaults(context: &mut EvalContext) {
    setup_fixity_constants(context);

    context.define_built_in_method_defaults(
        "operator",
        4,
        BuiltInFunction::new(operator),
    );

    context.define_built_in_method_defaults(
        "defineUnit",
        1,
        BuiltInFunction::new(define_unit),
    );

    context.define_built_in_method_defaults(
        "convert",
        2,
        BuiltInFunction::new(convert),
    );

    context.define_built_in_method_defaults(
        "unitFor",
        1,
        BuiltInFunction::new(unit_for),
    );

    context.define_built_in_method_defaults(
        "valueOf",
        1,
        BuiltInFunction::new(value_of),
    );

    context.define_built_in_method_defaults(
        "conversion",
        3,
        BuiltInFunction::new(conversion),
    );
}

fn setup_fixity_constants(context: &mut EvalContext) {
    context.set_constant("PREFIX", Fixity::Prefix.to_string());
    context.set_constant("INFIX", Fixity::Infix.to_string());
    context.set_constant("POSTFIX", Fixity::Postfix.to_string());
}

fn operator(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 4));

    try!(expect_param_is(params[0].is_constant(),
        "Fixity must be one of the constants PREFIX, INFIX, or POSTFIX"));
    try!(expect_param_is(params[1].is_number(),
        "Precedence must be a numeric value"));
    try!(expect_param_is(params[2].is_constant(),
        "Name of the operator must be a string literal"));
    try!(expect_param_is(params[3].is_function(),
        "Function definition must be either an existing function or an anonymous function"));

    let fixity = {
        let fx = Fixity::from_str(&params.remove(0).unwrap_constant());
        try!(expect_param_is(fx.is_some(),
            "Fixity must be one of the constants PREFIX, INFIX, or POSTFIX"));
        fx.unwrap()
    };

    let precedence = {
        let p = params.remove(0).unwrap_number();
        try!(expect_param_is(p.is_dimensionless(),
            "Precedence cannot have a unit"));
        p.value as u8
    };

    let name = &params.remove(0).unwrap_constant();
    let function = params.remove(0);

    debug_assert!(params.is_empty(), "Not all parameters used");

    match function {
        ContextItem::Definition { function, .. } => {
            context.define(name, fixity, precedence, function);
        },
        ContextItem::BuiltInMethod { function, params, .. } => {
            context.define_built_in_method(name, fixity, precedence, params, function)
        },
        _ => unreachable!(),
    };

    Ok(ContextItem::Nothing)
}

fn define_unit(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    try!(expect_param_is(params[0].is_constant(),
        "Name of the unit must be a string literal"));

    let unit_name = &params.remove(0).unwrap_constant();
    debug_assert!(params.is_empty(), "Not all parameters used");

    let unit = context.create_unit(unit_name);

    const UNIT_PRECEDENCE: u8 = 9;

    context.define_built_in_method(
        unit_name,
        Fixity::Postfix,
        UNIT_PRECEDENCE,
        1,
        BuiltInFunction::new(move |context, mut params| {
            try!(expect_params(&params, 1));
            try!(expect_param_is(params[0].is_number(),
                "Value to convert must be numeric"));

            let value = params.remove(0).unwrap_number();
            debug_assert!(params.is_empty(), "Not parameters used");

            context.convert(value, Some(unit))
        }),
    );

    Ok(ContextItem::Nothing)
}

fn convert(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 2));

    try!(expect_param_is(params[0].is_number(),
        "Value to convert must be numeric"));
    try!(expect_param_is(params[1].is_constant(),
        "Unit to convert to must be a string literal"));

    let value = params.remove(0).unwrap_number();
    let target_unit_name = params.remove(0).unwrap_constant();
    debug_assert!(params.is_empty(), "Not all parameters used");

    let unit = context.lookup_unit_name(&target_unit_name).unwrap();

    context.convert(value, Some(unit))
}

fn unit_for(context: &mut EvalContext, params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    unimplemented!();
}

fn value_of(context: &mut EvalContext, params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    unimplemented!();
}

fn conversion(context: &mut EvalContext, params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 3));

    unimplemented!();
}

fn expect_params(params: &Vec<ContextItem>, nparams: usize) -> Result<(), EvalError> {
    if params.len() != nparams {
        Err(EvalError::ExpectedParams(nparams))
    }
    else {
        Ok(())
    }
}

fn expect_param_is(cond: bool, message: &str) -> Result<(), EvalError> {
    if cond {
        Ok(())
    }
    else {
        Err(EvalError::InvalidParam(message.to_owned()))
    }
}

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

    use ast::*;

    use math::rich_number::RichNumber;

    use eval::fixity::Fixity;
    use eval::context_item::ContextItem;
    use eval::eval_context::EvalContext;

    #[test]
    fn fixity_constants() {
        let mut context = EvalContext::new();
        setup_defaults(&mut context);

        let lookup_fixity = |name| Fixity::from_str(&context.get(name).unwrap().unwrap_constant()).unwrap();

        assert_eq!(lookup_fixity("PREFIX"), Fixity::Prefix);
        assert_eq!(lookup_fixity("INFIX"), Fixity::Infix);
        assert_eq!(lookup_fixity("POSTFIX"), Fixity::Postfix);
    }

    #[test]
    fn can_define_operators_with_different_fixities() {
        let mut context = EvalContext::new();
        setup_defaults(&mut context);

        let fixity = Fixity::Prefix;
        let precedence: u8 = 0;
        let name = "foo".to_owned();

        let params = vec!["x".to_owned()];
        let function_body: Expr = vec![
            ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
        ];

        assert_eq!(context.call("operator", vec![
            ContextItem::Constant(fixity.to_string()),
            ContextItem::Number(RichNumber::from(precedence as f64)),
            ContextItem::Constant(name.clone()),
            ContextItem::new_definition(
                // must be different from the other values for these
                Fixity::Postfix,
                precedence + 1,
                Function {
                    params: params.clone(),
                    body: function_body.clone(),
                },
            ),
        ]).unwrap().unwrap(), ContextItem::Nothing);

        let defined = context.get(&name).unwrap();

        match defined {
            ContextItem::Definition {
                precedence: dprecedence,
                fixity: dfixity,
                function,
            } => {
                assert_eq!(dprecedence, precedence);
                assert_eq!(dfixity, fixity);
                assert_eq!(function.params, params);
                assert_eq!(function.body, function_body);
            },
            _ => panic!("operator did not define a function"),
        }
    }
}

<commit_msg>Implementing the  unit and as a consequence implementing valueOf<commit_after>use eval::fixity::Fixity;
use eval::context_item::ContextItem;
use eval::built_in_function::BuiltInFunction;
use eval::eval_context::{EvalContext, EvalResult, EvalError};

const UNIT_PRECEDENCE: u8 = 9;

pub fn setup_defaults(context: &mut EvalContext) {
    setup_fixity_constants(context);

    context.define_built_in_method_defaults(
        "operator",
        4,
        BuiltInFunction::new(operator),
    );

    context.define_built_in_method(
        "units",
        Fixity::Postfix,
        UNIT_PRECEDENCE,
        1,
        BuiltInFunction::new(remove_unit),
    );

    context.define_built_in_method_defaults(
        "defineUnit",
        1,
        BuiltInFunction::new(define_unit),
    );

    context.define_built_in_method_defaults(
        "convert",
        2,
        BuiltInFunction::new(convert),
    );

    context.define_built_in_method_defaults(
        "unitFor",
        1,
        BuiltInFunction::new(unit_for),
    );

    context.define_built_in_method_defaults(
        "valueOf",
        1,
        BuiltInFunction::new(remove_unit),
    );

    context.define_built_in_method_defaults(
        "conversion",
        3,
        BuiltInFunction::new(conversion),
    );
}

fn setup_fixity_constants(context: &mut EvalContext) {
    context.set_constant("PREFIX", Fixity::Prefix.to_string());
    context.set_constant("INFIX", Fixity::Infix.to_string());
    context.set_constant("POSTFIX", Fixity::Postfix.to_string());
}

fn operator(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 4));

    try!(expect_param_is(params[0].is_constant(),
        "Fixity must be one of the constants PREFIX, INFIX, or POSTFIX"));
    try!(expect_param_is(params[1].is_number(),
        "Precedence must be a numeric value"));
    try!(expect_param_is(params[2].is_constant(),
        "Name of the operator must be a string literal"));
    try!(expect_param_is(params[3].is_function(),
        "Function definition must be either an existing function or an anonymous function"));

    let fixity = {
        let fx = Fixity::from_str(&params.remove(0).unwrap_constant());
        try!(expect_param_is(fx.is_some(),
            "Fixity must be one of the constants PREFIX, INFIX, or POSTFIX"));
        fx.unwrap()
    };

    let precedence = {
        let p = params.remove(0).unwrap_number();
        try!(expect_param_is(p.is_dimensionless(),
            "Precedence cannot have a unit"));
        p.value as u8
    };

    let name = &params.remove(0).unwrap_constant();
    let function = params.remove(0);

    debug_assert!(params.is_empty(), "Not all parameters used");

    match function {
        ContextItem::Definition { function, .. } => {
            context.define(name, fixity, precedence, function);
        },
        ContextItem::BuiltInMethod { function, params, .. } => {
            context.define_built_in_method(name, fixity, precedence, params, function)
        },
        _ => unreachable!(),
    };

    Ok(ContextItem::Nothing)
}

fn remove_unit(_: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    try!(expect_param_is(params[0].is_number(),
        "Value to convert must be numeric"));

    let value = params.remove(0).unwrap_number();
    debug_assert!(params.is_empty(), "Not all parameters used");

    Ok(ContextItem::Number(value.without_units()))
}

fn define_unit(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    try!(expect_param_is(params[0].is_constant(),
        "Name of the unit must be a string literal"));

    let unit_name = &params.remove(0).unwrap_constant();
    debug_assert!(params.is_empty(), "Not all parameters used");

    let unit = context.create_unit(unit_name);

    context.define_built_in_method(
        unit_name,
        Fixity::Postfix,
        UNIT_PRECEDENCE,
        1,
        BuiltInFunction::new(move |context, mut params| {
            try!(expect_params(&params, 1));
            try!(expect_param_is(params[0].is_number(),
                "Value to convert must be numeric"));

            let value = params.remove(0).unwrap_number();
            debug_assert!(params.is_empty(), "Not parameters used");

            context.convert(value, Some(unit))
        }),
    );

    Ok(ContextItem::Nothing)
}

fn convert(context: &mut EvalContext, mut params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 2));

    try!(expect_param_is(params[0].is_number(),
        "Value to convert must be numeric"));
    try!(expect_param_is(params[1].is_constant(),
        "Unit to convert to must be a string literal"));

    let value = params.remove(0).unwrap_number();
    let target_unit_name = params.remove(0).unwrap_constant();
    debug_assert!(params.is_empty(), "Not all parameters used");

    let unit = context.lookup_unit_name(&target_unit_name).unwrap();

    context.convert(value, Some(unit))
}

fn unit_for(context: &mut EvalContext, params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 1));

    unimplemented!();
}

fn conversion(context: &mut EvalContext, params: Vec<ContextItem>) -> EvalResult {
    try!(expect_params(&params, 3));

    unimplemented!();
}

fn expect_params(params: &Vec<ContextItem>, nparams: usize) -> Result<(), EvalError> {
    if params.len() != nparams {
        Err(EvalError::ExpectedParams(nparams))
    }
    else {
        Ok(())
    }
}

fn expect_param_is(cond: bool, message: &str) -> Result<(), EvalError> {
    if cond {
        Ok(())
    }
    else {
        Err(EvalError::InvalidParam(message.to_owned()))
    }
}

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

    use ast::*;

    use math::rich_number::RichNumber;

    use eval::fixity::Fixity;
    use eval::context_item::ContextItem;
    use eval::eval_context::EvalContext;

    #[test]
    fn fixity_constants() {
        let mut context = EvalContext::new();
        setup_defaults(&mut context);

        let lookup_fixity = |name| Fixity::from_str(&context.get(name).unwrap().unwrap_constant()).unwrap();

        assert_eq!(lookup_fixity("PREFIX"), Fixity::Prefix);
        assert_eq!(lookup_fixity("INFIX"), Fixity::Infix);
        assert_eq!(lookup_fixity("POSTFIX"), Fixity::Postfix);
    }

    #[test]
    fn can_define_operators_with_different_fixities() {
        let mut context = EvalContext::new();
        setup_defaults(&mut context);

        let fixity = Fixity::Prefix;
        let precedence: u8 = 0;
        let name = "foo".to_owned();

        let params = vec!["x".to_owned()];
        let function_body: Expr = vec![
            ExprItem::SingleTerm(Term::Symbol("x".to_owned())),
        ];

        assert_eq!(context.call("operator", vec![
            ContextItem::Constant(fixity.to_string()),
            ContextItem::Number(RichNumber::from(precedence as f64)),
            ContextItem::Constant(name.clone()),
            ContextItem::new_definition(
                // must be different from the other values for these
                Fixity::Postfix,
                precedence + 1,
                Function {
                    params: params.clone(),
                    body: function_body.clone(),
                },
            ),
        ]).unwrap().unwrap(), ContextItem::Nothing);

        let defined = context.get(&name).unwrap();

        match defined {
            ContextItem::Definition {
                precedence: dprecedence,
                fixity: dfixity,
                function,
            } => {
                assert_eq!(dprecedence, precedence);
                assert_eq!(dfixity, fixity);
                assert_eq!(function.params, params);
                assert_eq!(function.body, function_body);
            },
            _ => panic!("operator did not define a function"),
        }
    }
}

<|endoftext|>


<commit_before>#[repr(packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    pub fn size(&self) -> usize {
        self.sh_size as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<commit_msg>Expose flags for Elf Sections.<commit_after>#[repr(packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    pub fn size(&self) -> usize {
        self.sh_size as usize
    }

    pub fn flags(&self) -> usize {
        self.sh_flags as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<|endoftext|>


<commit_before>// automatically generated by rust-bindgen
pub use super::ext::boolean::*;
pub use libc::FILE;

#[link(name = "R")]
extern {
    pub static mut R_Interactive: Rboolean;
    pub static mut R_Slave: Rboolean;
    pub static mut R_DirtyImage: ::libc::c_int;
    pub static mut R_GUIType: *mut ::libc::c_char;
    pub static mut R_HistoryFile: *mut ::libc::c_char;
    pub static mut R_HistorySize: ::libc::c_int;
    pub static mut R_RestoreHistory: ::libc::c_int;
    pub static mut R_Home: *mut ::libc::c_char;
    pub static mut R_GlobalContext: *mut ::libc::c_void;
    pub static mut R_Consolefile: *mut FILE;
    pub static mut R_Outputfile: *mut FILE;
    pub static mut R_timeout_val: ::libc::c_long;
    pub static mut R_SignalHandlers: ::libc::c_int;
    pub static mut R_CStackLimit: ::libc::uintptr_t;
    pub static mut R_CStackStart: ::libc::uintptr_t;
}
#[link(name = "R")]
extern {
    pub fn R_RestoreGlobalEnv() -> ();
    pub fn R_RestoreGlobalEnvFromFile(arg1: *const ::libc::c_char, arg2: Rboolean) -> ();
    pub fn R_SaveGlobalEnv() -> ();
    pub fn R_SaveGlobalEnvToFile(arg1: *const ::libc::c_char) -> ();
    pub fn R_FlushConsole() -> ();
    pub fn R_ClearerrConsole() -> ();
    pub fn R_Suicide(arg1: *const ::libc::c_char) -> ();
    pub fn R_HomeDir() -> *mut ::libc::c_char;
    pub fn R_setupHistory() -> ();
    pub fn Rf_jump_to_toplevel() -> ();
    pub fn Rf_mainloop() -> ();
    pub fn Rf_onintr() -> ();
    pub fn process_site_Renviron() -> ();
    pub fn process_system_Renviron() -> ();
    pub fn process_user_Renviron() -> ();
    pub fn R_setStartTime() -> ();
    pub fn fpu_setup(arg1: Rboolean) -> ();
}

pub unsafe fn jump_to_toplevel() {
    Rf_jump_to_toplevel()
}
pub unsafe fn mainloop() {
    Rf_mainloop()
}
pub unsafe fn onintr() {
    Rf_onintr()
}
<commit_msg>Add a extern static variable for mainloop<commit_after>// automatically generated by rust-bindgen
pub use super::ext::boolean::*;
pub use libc::FILE;

#[link(name = "R")]
extern {
    pub static mut R_Interactive: Rboolean;
    pub static mut R_Slave: Rboolean;
    pub static mut R_DirtyImage: ::libc::c_int;
    pub static mut R_GUIType: *mut ::libc::c_char;
    pub static mut R_HistoryFile: *mut ::libc::c_char;
    pub static mut R_HistorySize: ::libc::c_int;
    pub static mut R_RestoreHistory: ::libc::c_int;
    pub static mut R_Home: *mut ::libc::c_char;
    pub static mut R_GlobalContext: *mut ::libc::c_void;
    pub static mut R_Consolefile: *mut FILE;
    pub static mut R_Outputfile: *mut FILE;
    pub static mut R_timeout_val: ::libc::c_long;
    pub static mut R_SignalHandlers: ::libc::c_int;
    pub static mut R_CStackLimit: ::libc::uintptr_t;
    pub static mut R_CStackStart: ::libc::uintptr_t;
    pub static mut R_running_as_main_program: ::libc::c_int;
}
#[link(name = "R")]
extern {
    pub fn R_RestoreGlobalEnv() -> ();
    pub fn R_RestoreGlobalEnvFromFile(arg1: *const ::libc::c_char, arg2: Rboolean) -> ();
    pub fn R_SaveGlobalEnv() -> ();
    pub fn R_SaveGlobalEnvToFile(arg1: *const ::libc::c_char) -> ();
    pub fn R_FlushConsole() -> ();
    pub fn R_ClearerrConsole() -> ();
    pub fn R_Suicide(arg1: *const ::libc::c_char) -> ();
    pub fn R_HomeDir() -> *mut ::libc::c_char;
    pub fn R_setupHistory() -> ();
    pub fn Rf_jump_to_toplevel() -> ();
    pub fn Rf_mainloop() -> ();
    pub fn Rf_onintr() -> ();
    pub fn process_site_Renviron() -> ();
    pub fn process_system_Renviron() -> ();
    pub fn process_user_Renviron() -> ();
    pub fn R_setStartTime() -> ();
    pub fn fpu_setup(arg1: Rboolean) -> ();
}

pub unsafe fn jump_to_toplevel() {
    Rf_jump_to_toplevel()
}
pub unsafe fn mainloop() {
    Rf_mainloop()
}
pub unsafe fn onintr() {
    Rf_onintr()
}
<|endoftext|>


<commit_before>mod coordinate;

pub use self::coordinate::Coordinate;

use std::cell::Cell;

use aura::{Aura, AbilityBuff, AuraTag};
use crusader::*;
use dps::*;

#[derive(Debug, Clone)]
pub struct Formation<'a> {
    positions: Box<[FormationPosition<'a>]>,
    used_slots: Slot,
    dps: Cell<Option<Dps>>,
}

impl<'a> Formation<'a> {
    pub fn empty<I: IntoIterator<Item=Coordinate>>(positions: I) -> Self {
        let positions = positions.into_iter().map(FormationPosition::empty)
            .collect::<Vec<_>>()
            .into_boxed_slice();
        Formation {
            positions,
            used_slots: Slot::empty(),
            dps: Cell::new(None),
        }
    }

    pub fn place_crusader(&mut self, position: usize, crusader: &'a Crusader) -> &mut Self {
        self.positions[position].crusader = Some(crusader);
        self.used_slots |= crusader.slot();
        self.dps.set(None);
        self
    }

    pub fn remove_crusader(&mut self, position: usize) -> &mut Self {
        self.positions[position].crusader = None;
        let used_slots = self.crusaders().fold(Slot::empty(), |s, c| s | c.slot());
        self.used_slots = used_slots;
        self.dps.set(None);
        self
    }

    pub fn total_dps(&self) -> Dps {
        self.dps.get().unwrap_or_else(|| {
            let dps = self.positions.iter()
                .map(|p| p.total_dps(&self, self.crusaders().flat_map(Crusader::dps_auras)))
                .sum();
            self.dps.set(Some(dps));
            dps
        })
    }

    pub fn empty_positions<'b>(&'b self) -> impl Iterator<Item=usize> + 'b {
        self.positions.iter()
            .enumerate()
            .filter(|&(_, p)| p.crusader.is_none())
            .map(|(i, _)| i)
    }

    pub fn used_slots(&self) -> Slot {
        self.used_slots
    }

    pub fn position_of(&self, crusader: CrusaderName) -> Option<&Coordinate> {
        self.positions.iter()
            .find(|p| p.crusader.as_ref().map(|c| c.name) == Some(crusader))
            .map(|p| &p.coordinate)
    }

    pub fn front_column(&self) -> Option<u8> {
        self.positions.iter()
            .map(|p| p.coordinate.x)
            .max()
    }

    pub fn ability_buffs<'b>(&'b self, tag: AuraTag)
        -> impl Iterator<Item=&'a AbilityBuff> + 'b
    {
        self.crusaders().flat_map(Crusader::ability_buffs)
            .filter(move |b| b.applies_to(tag, self))
    }

    pub fn print(&self) {
        println!("Total DPS: {}", self.total_dps());
        for pos in self.positions.iter() {
            let coord = pos.coordinate;
            let crusader = pos.crusader;
            let dps = pos.total_dps(&self, self.crusaders().flat_map(Crusader::dps_auras));
            println!("({}, {}): {:?} {}", coord.x, coord.y, crusader.map(|c| c.name), dps);
        }
    }

    pub fn crusaders<'b>(&'b self) -> impl Iterator<Item=&'a Crusader> + 'b {
        self.positions.iter().filter_map(|p| p.crusader)
    }
}

#[derive(Debug, Clone)]
struct FormationPosition<'a> {
    coordinate: Coordinate,
    crusader: Option<&'a Crusader>,
}

impl<'a> FormationPosition<'a> {
    fn empty(coordinate: Coordinate) -> Self {
        FormationPosition {
            coordinate,
            crusader: None,
        }
    }

    fn total_dps<I>(&self, formation: &Formation<'a>, auras: I) -> Dps where
        I: IntoIterator<Item=&'a Aura>,
    {
        let crusader = match self.crusader {
            Some(crusader) => crusader,
            None => return Dps(0.0),
        };
        auras.into_iter()
            .fold(crusader.base_dps(), |dps, aura| {
                dps.percent_increase(aura.amount_for_crusader(
                    crusader.name,
                    formation,
                ))
            })
    }
}
<commit_msg>Improve formation printing to be easier for humans to parse<commit_after>mod coordinate;

pub use self::coordinate::Coordinate;

use std::cell::Cell;

use aura::{Aura, AbilityBuff, AuraTag};
use crusader::*;
use dps::*;

#[derive(Debug, Clone)]
pub struct Formation<'a> {
    positions: Box<[FormationPosition<'a>]>,
    used_slots: Slot,
    dps: Cell<Option<Dps>>,
}

impl<'a> Formation<'a> {
    pub fn empty<I: IntoIterator<Item=Coordinate>>(positions: I) -> Self {
        let positions = positions.into_iter().map(FormationPosition::empty)
            .collect::<Vec<_>>()
            .into_boxed_slice();
        Formation {
            positions,
            used_slots: Slot::empty(),
            dps: Cell::new(None),
        }
    }

    pub fn place_crusader(&mut self, position: usize, crusader: &'a Crusader) -> &mut Self {
        self.positions[position].crusader = Some(crusader);
        self.used_slots |= crusader.slot();
        self.dps.set(None);
        self
    }

    pub fn remove_crusader(&mut self, position: usize) -> &mut Self {
        self.positions[position].crusader = None;
        let used_slots = self.crusaders().fold(Slot::empty(), |s, c| s | c.slot());
        self.used_slots = used_slots;
        self.dps.set(None);
        self
    }

    pub fn total_dps(&self) -> Dps {
        self.dps.get().unwrap_or_else(|| {
            let dps = self.positions.iter()
                .map(|p| p.total_dps(&self, self.crusaders().flat_map(Crusader::dps_auras)))
                .sum();
            self.dps.set(Some(dps));
            dps
        })
    }

    pub fn empty_positions<'b>(&'b self) -> impl Iterator<Item=usize> + 'b {
        self.positions.iter()
            .enumerate()
            .filter(|&(_, p)| p.crusader.is_none())
            .map(|(i, _)| i)
    }

    pub fn used_slots(&self) -> Slot {
        self.used_slots
    }

    pub fn position_of(&self, crusader: CrusaderName) -> Option<&Coordinate> {
        self.positions.iter()
            .find(|p| p.crusader.as_ref().map(|c| c.name) == Some(crusader))
            .map(|p| &p.coordinate)
    }

    pub fn front_column(&self) -> Option<u8> {
        self.positions.iter()
            .map(|p| p.coordinate.x)
            .max()
    }

    pub fn ability_buffs<'b>(&'b self, tag: AuraTag)
        -> impl Iterator<Item=&'a AbilityBuff> + 'b
    {
        self.crusaders().flat_map(Crusader::ability_buffs)
            .filter(move |b| b.applies_to(tag, self))
    }

    pub fn print(&self) {
        let longest_crusader_name = self.crusaders()
            .map(|c| format!("{:?}", c.name).len())
            .max();
        let longest_crusader_name = match longest_crusader_name {
            Some(x) => x,
            None => return,
        };
        let front_column = self.front_column().unwrap();
        let num_rows = self.positions.iter()
            .map(|p| p.coordinate.y)
            .max().unwrap();
        println!("Total DPS: {}", self.total_dps());
        for y in 0..(num_rows * 2 + 2) {
            for x in 0..(front_column + 1) {
                let crusader_name = self.positions.iter()
                    .find(|p| {
                        let c = p.coordinate;
                        c.x == x && c.y * 2 + x % 2 == y
                    }).map(|p| {
                        p.crusader.map(|c| format!("{:?}", c))
                            .unwrap_or_else(|| String::from("o"))
                    });
                let dps = self.positions.iter()
                    .filter(|p| p.crusader.is_some())
                    .find(|p| {
                        let c = p.coordinate;
                        c.x == x && c.y * 2 + x % 2 == y - 1
                    }).map(|p| {
                        p.total_dps(&self, self.crusaders().flat_map(Crusader::dps_auras))
                            .to_string()
                    });
                print!("{1:^0$}", longest_crusader_name, crusader_name.or(dps).unwrap_or(String::new()));
            }
            print!("\n");
        }
    }

    pub fn crusaders<'b>(&'b self) -> impl Iterator<Item=&'a Crusader> + 'b {
        self.positions.iter().filter_map(|p| p.crusader)
    }
}

#[derive(Debug, Clone)]
struct FormationPosition<'a> {
    coordinate: Coordinate,
    crusader: Option<&'a Crusader>,
}

impl<'a> FormationPosition<'a> {
    fn empty(coordinate: Coordinate) -> Self {
        FormationPosition {
            coordinate,
            crusader: None,
        }
    }

    fn total_dps<I>(&self, formation: &Formation<'a>, auras: I) -> Dps where
        I: IntoIterator<Item=&'a Aura>,
    {
        let crusader = match self.crusader {
            Some(crusader) => crusader,
            None => return Dps(0.0),
        };
        auras.into_iter()
            .fold(crusader.base_dps(), |dps, aura| {
                dps.percent_increase(aura.amount_for_crusader(
                    crusader.name,
                    formation,
                ))
            })
    }
}
<|endoftext|>