<commit_before>use collections::string::String;
use collections::btree_map::BTreeMap;
use collections::vec::Vec;
use alloc::boxed::Box;

use spin::RwLockWriteGuard;

use super::namespace::{ AmlValue, ObjectReference };
use super::AmlError;

use acpi::ACPI_TABLE;

pub type ParseResult = Result<AmlParseType, AmlError>;
pub type AmlParseType = AmlParseTypeGeneric<AmlValue>;

pub struct AmlParseTypeGeneric<T> {
    pub val: T,
    pub len: usize
}

pub enum ExecutionState {
    EXECUTING,
    CONTINUE,
    BREAK,
    RETURN(AmlValue)
}

pub struct AmlExecutionContext {
    pub scope: String,
    pub local_vars: [AmlValue; 8],
    pub arg_vars: [AmlValue; 8],
    pub state: ExecutionState,
    pub namespace_delta: Vec<String>,
    pub ctx_id: u64,
    pub sync_level: u8
}

impl AmlExecutionContext {
    pub fn new(scope: String) -> AmlExecutionContext {
        let mut idptr = ACPI_TABLE.next_ctx.write();
        let id: u64 = *idptr;

        *idptr += 1;

        AmlExecutionContext {
            scope: scope,
            local_vars: [AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized],
            arg_vars: [AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized],
            state: ExecutionState::EXECUTING,
            namespace_delta: vec!(),
            ctx_id: id,
            sync_level: 0
        }
    }

    pub fn wait_for_event(&mut self, event_ptr: AmlValue) -> Result<bool, AmlError> {
        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match event_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Event(count) => {
                if count > 0 {
                    namespace.insert(mutex_idx, AmlValue::Event(count - 1));
                    return Ok(true);
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(false)
    }

    pub fn signal_event(&mut self, event_ptr: AmlValue) -> Result<(), AmlError> {
        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match event_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Event(count) => {
                namespace.insert(mutex_idx, AmlValue::Event(count + 1));
                return Ok(());
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(())
    }

    pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> {
        let id = self.ctx_id;

        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match mutex_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Mutex((sync_level, owner)) => {
                if let Some(o) = owner {
                    if o == id {
                        if sync_level == self.sync_level {
                            namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None)));
                            return Ok(());
                        } else {
                            return Err(AmlError::AmlValueError);
                        }
                    } else {
                        return Err(AmlError::AmlHardFatal);
                    }
                }
            },
            AmlValue::OperationRegion(ref region) => {
                if let Some(o) = region.accessed_by {
                    if o == id {
                        let mut new_region = region.clone();
                        new_region.accessed_by = None;

                        namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
                        return Ok(());
                    } else {
                        return Err(AmlError::AmlHardFatal);
                    }
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(())
    }

    pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue) -> Result<bool, AmlError> {
        let id = self.ctx_id;

        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };
        let mutex_idx = match mutex_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Mutex((sync_level, owner)) => {
                if owner == None {
                    if sync_level < self.sync_level {
                        return Err(AmlError::AmlValueError);
                    }

                    namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id))));
                    self.sync_level = sync_level;

                    return Ok(true);
                }
            },
            AmlValue::OperationRegion(ref o) => {
                if o.accessed_by == None {
                    let mut new_region = o.clone();
                    new_region.accessed_by = Some(id);

                    namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
                    return Ok(true);
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(false)
    }

    pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
        let mut namespace = ACPI_TABLE.namespace.write();

        if let Some(ref mut namespace) = *namespace {
            if namespace.contains_key(&name) {
                return Err(AmlError::AmlValueError);
            }

            self.namespace_delta.push(name.clone());
            namespace.insert(name, value);

            Ok(())
        } else {
            Err(AmlError::AmlValueError)
        }
    }

    pub fn clean_namespace(&mut self) {
        let mut namespace = ACPI_TABLE.namespace.write();

        if let Some(ref mut namespace) = *namespace {
            for k in &self.namespace_delta {
                namespace.remove(k);
            }
        }
    }

    pub fn init_arg_vars(&mut self, parameters: Vec<AmlValue>) {
        if parameters.len() > 8 {
            return;
        }

        let mut cur = 0;
        while cur < parameters.len() {
            self.arg_vars[cur] = parameters[cur].clone();
            cur += 1;
        }
    }

    pub fn prelock(&mut self) -> RwLockWriteGuard<'static, Option<BTreeMap<String, AmlValue>>> {
        ACPI_TABLE.namespace.write()
    }

    fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> {
        self.local_vars[local] = value;
        Ok(())
    }

    fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
            namespace.insert(name, value);
            Ok(())
        } else {
            Err(AmlError::AmlHardFatal)
        }
    }

    fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError> {
        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
            let mut obj = if let Some(s) = namespace.get(&name) {
                s.clone()
            } else {
                return Err(AmlError::AmlValueError);
            };

            obj = self.modify_index_core(obj, value, indices)?;

            namespace.insert(name, obj);
            Ok(())
        } else {
            Err(AmlError::AmlValueError)
        }
    }

    fn modify_index_core(&mut self, obj: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError> {
        match obj {
            AmlValue::String(ref string) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut bytes = string.clone().into_bytes();
                bytes[indices[0] as usize] = value.get_as_integer()? as u8;

                let string = String::from_utf8(bytes).unwrap();

                Ok(AmlValue::String(string))
            },
            AmlValue::Buffer(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut b = b.clone();
                b[indices[0] as usize] = value.get_as_integer()? as u8;

                Ok(AmlValue::Buffer(b))
            },
            AmlValue::BufferField(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut idx = indices[0];
                idx += b.index.get_as_integer()?;

                self.modify(AmlValue::ObjectReference(ObjectReference::Index(b.source_buf.clone(), Box::new(AmlValue::Integer(idx.clone())))), value);

                Ok(AmlValue::BufferField(b.clone()))
            },
            AmlValue::Package(ref p) => {
                if indices.len() < 0 {
                    return Err(AmlError::AmlValueError);
                }

                let mut p = p.clone();

                if indices.len() == 1 {
                    p[indices[0] as usize] = value;
                } else {
                    p[indices[0] as usize] = self.modify_index_core(p[indices[0] as usize].clone(), value, indices[1..].to_vec())?;
                }

                Ok(AmlValue::Package(p))
            },
            _ => return Err(AmlError::AmlValueError)
        }
    }

    pub fn modify_index(&mut self, name: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError>{
        match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::Object(s) => self.modify_index_final(s, value, indices),
                ObjectReference::Index(c, v) => {
                    let mut indices = indices.clone();
                    indices.push(v.get_as_integer()?);

                    self.modify_index(*c, value, indices)
                },
                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
                ObjectReference::LocalObj(i) => {
                    let v = self.local_vars[i as usize].clone();
                    self.local_vars[i as usize] = self.modify_index_core(v, value, indices)?;

                    Ok(())
                }
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> {
        match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
                ObjectReference::LocalObj(i) => self.modify_local_obj(i as usize, value),
                ObjectReference::Object(s) => self.modify_object(s, value),
                ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?))
            },
            AmlValue::String(s) => self.modify_object(s, value),
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get(&self, name: AmlValue) -> Result<AmlValue, AmlError> {
        Ok(match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(),
                ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(),
                ObjectReference::Object(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
                    if let Some(o) = namespace.get(s) {
                        o.clone()
                    } else {
                        AmlValue::None
                    }
                } else { AmlValue::None },
                ObjectReference::Index(c, v) => if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
                    let idx = v.get_as_integer()? as usize;
                    match *c {
                        AmlValue::Package(p) => p[idx].clone(),
                        _ => AmlValue::None
                    }
                } else {
                    AmlValue::None
                }
            },
            AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
                if let Some(o) = namespace.get(s) {
                    o.clone()
                } else {
                    AmlValue::None
                }
            } else { AmlValue::None },
            _ => AmlValue::None
        })
    }
}
<commit_msg>Completed Get method<commit_after>use collections::string::String;
use collections::btree_map::BTreeMap;
use collections::vec::Vec;
use alloc::boxed::Box;

use spin::RwLockWriteGuard;

use super::namespace::{ AmlValue, ObjectReference };
use super::AmlError;

use acpi::ACPI_TABLE;

pub type ParseResult = Result<AmlParseType, AmlError>;
pub type AmlParseType = AmlParseTypeGeneric<AmlValue>;

pub struct AmlParseTypeGeneric<T> {
    pub val: T,
    pub len: usize
}

pub enum ExecutionState {
    EXECUTING,
    CONTINUE,
    BREAK,
    RETURN(AmlValue)
}

pub struct AmlExecutionContext {
    pub scope: String,
    pub local_vars: [AmlValue; 8],
    pub arg_vars: [AmlValue; 8],
    pub state: ExecutionState,
    pub namespace_delta: Vec<String>,
    pub ctx_id: u64,
    pub sync_level: u8
}

impl AmlExecutionContext {
    pub fn new(scope: String) -> AmlExecutionContext {
        let mut idptr = ACPI_TABLE.next_ctx.write();
        let id: u64 = *idptr;

        *idptr += 1;

        AmlExecutionContext {
            scope: scope,
            local_vars: [AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized,
                         AmlValue::Uninitialized],
            arg_vars: [AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized,
                       AmlValue::Uninitialized],
            state: ExecutionState::EXECUTING,
            namespace_delta: vec!(),
            ctx_id: id,
            sync_level: 0
        }
    }

    pub fn wait_for_event(&mut self, event_ptr: AmlValue) -> Result<bool, AmlError> {
        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match event_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Event(count) => {
                if count > 0 {
                    namespace.insert(mutex_idx, AmlValue::Event(count - 1));
                    return Ok(true);
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(false)
    }

    pub fn signal_event(&mut self, event_ptr: AmlValue) -> Result<(), AmlError> {
        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match event_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Event(count) => {
                namespace.insert(mutex_idx, AmlValue::Event(count + 1));
                return Ok(());
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(())
    }

    pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> {
        let id = self.ctx_id;

        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };

        let mutex_idx = match mutex_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Mutex((sync_level, owner)) => {
                if let Some(o) = owner {
                    if o == id {
                        if sync_level == self.sync_level {
                            namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None)));
                            return Ok(());
                        } else {
                            return Err(AmlError::AmlValueError);
                        }
                    } else {
                        return Err(AmlError::AmlHardFatal);
                    }
                }
            },
            AmlValue::OperationRegion(ref region) => {
                if let Some(o) = region.accessed_by {
                    if o == id {
                        let mut new_region = region.clone();
                        new_region.accessed_by = None;

                        namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
                        return Ok(());
                    } else {
                        return Err(AmlError::AmlHardFatal);
                    }
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(())
    }

    pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue) -> Result<bool, AmlError> {
        let id = self.ctx_id;

        let mut namespace_ptr = self.prelock();
        let mut namespace = match *namespace_ptr {
            Some(ref mut n) => n,
            None => return Err(AmlError::AmlHardFatal)
        };
        let mutex_idx = match mutex_ptr {
            AmlValue::String(ref s) => s.clone(),
            AmlValue::ObjectReference(ref o) => match *o {
                ObjectReference::Object(ref s) => s.clone(),
                _ => return Err(AmlError::AmlValueError)
            },
            _ => return Err(AmlError::AmlValueError)
        };

        let mutex = match namespace.get(&mutex_idx) {
            Some(s) => s.clone(),
            None => return Err(AmlError::AmlValueError)
        };

        match mutex {
            AmlValue::Mutex((sync_level, owner)) => {
                if owner == None {
                    if sync_level < self.sync_level {
                        return Err(AmlError::AmlValueError);
                    }

                    namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id))));
                    self.sync_level = sync_level;

                    return Ok(true);
                }
            },
            AmlValue::OperationRegion(ref o) => {
                if o.accessed_by == None {
                    let mut new_region = o.clone();
                    new_region.accessed_by = Some(id);

                    namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region));
                    return Ok(true);
                }
            },
            _ => return Err(AmlError::AmlValueError)
        }

        Ok(false)
    }

    pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
        let mut namespace = ACPI_TABLE.namespace.write();

        if let Some(ref mut namespace) = *namespace {
            if namespace.contains_key(&name) {
                return Err(AmlError::AmlValueError);
            }

            self.namespace_delta.push(name.clone());
            namespace.insert(name, value);

            Ok(())
        } else {
            Err(AmlError::AmlValueError)
        }
    }

    pub fn clean_namespace(&mut self) {
        let mut namespace = ACPI_TABLE.namespace.write();

        if let Some(ref mut namespace) = *namespace {
            for k in &self.namespace_delta {
                namespace.remove(k);
            }
        }
    }

    pub fn init_arg_vars(&mut self, parameters: Vec<AmlValue>) {
        if parameters.len() > 8 {
            return;
        }

        let mut cur = 0;
        while cur < parameters.len() {
            self.arg_vars[cur] = parameters[cur].clone();
            cur += 1;
        }
    }

    pub fn prelock(&mut self) -> RwLockWriteGuard<'static, Option<BTreeMap<String, AmlValue>>> {
        ACPI_TABLE.namespace.write()
    }

    fn modify_local_obj(&mut self, local: usize, value: AmlValue) -> Result<(), AmlError> {
        self.local_vars[local] = value;
        Ok(())
    }

    fn modify_object(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> {
        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
            namespace.insert(name, value);
            Ok(())
        } else {
            Err(AmlError::AmlHardFatal)
        }
    }

    fn modify_index_final(&mut self, name: String, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError> {
        if let Some(ref mut namespace) = *ACPI_TABLE.namespace.write() {
            let mut obj = if let Some(s) = namespace.get(&name) {
                s.clone()
            } else {
                return Err(AmlError::AmlValueError);
            };

            obj = self.modify_index_core(obj, value, indices)?;

            namespace.insert(name, obj);
            Ok(())
        } else {
            Err(AmlError::AmlValueError)
        }
    }

    fn modify_index_core(&mut self, obj: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError> {
        match obj {
            AmlValue::String(ref string) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut bytes = string.clone().into_bytes();
                bytes[indices[0] as usize] = value.get_as_integer()? as u8;

                let string = String::from_utf8(bytes).unwrap();

                Ok(AmlValue::String(string))
            },
            AmlValue::Buffer(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut b = b.clone();
                b[indices[0] as usize] = value.get_as_integer()? as u8;

                Ok(AmlValue::Buffer(b))
            },
            AmlValue::BufferField(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut idx = indices[0];
                idx += b.index.get_as_integer()?;

                self.modify(AmlValue::ObjectReference(ObjectReference::Index(b.source_buf.clone(), Box::new(AmlValue::Integer(idx.clone())))), value);

                Ok(AmlValue::BufferField(b.clone()))
            },
            AmlValue::Package(ref p) => {
                if indices.len() < 0 {
                    return Err(AmlError::AmlValueError);
                }

                let mut p = p.clone();

                if indices.len() == 1 {
                    p[indices[0] as usize] = value;
                } else {
                    p[indices[0] as usize] = self.modify_index_core(p[indices[0] as usize].clone(), value, indices[1..].to_vec())?;
                }

                Ok(AmlValue::Package(p))
            },
            _ => return Err(AmlError::AmlValueError)
        }
    }

    pub fn modify_index(&mut self, name: AmlValue, value: AmlValue, indices: Vec<u64>) -> Result<(), AmlError>{
        match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::Object(s) => self.modify_index_final(s, value, indices),
                ObjectReference::Index(c, v) => {
                    let mut indices = indices.clone();
                    indices.push(v.get_as_integer()?);

                    self.modify_index(*c, value, indices)
                },
                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
                ObjectReference::LocalObj(i) => {
                    let v = self.local_vars[i as usize].clone();
                    self.local_vars[i as usize] = self.modify_index_core(v, value, indices)?;

                    Ok(())
                }
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn modify(&mut self, name: AmlValue, value: AmlValue) -> Result<(), AmlError> {
        match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
                ObjectReference::LocalObj(i) => self.modify_local_obj(i as usize, value),
                ObjectReference::Object(s) => self.modify_object(s, value),
                ObjectReference::Index(c, v) => self.modify_index(*c, value, vec!(v.get_as_integer()?))
            },
            AmlValue::String(s) => self.modify_object(s, value),
            _ => Err(AmlError::AmlValueError)
        }
    }

    fn get_index_final(&self, name: String, indices: Vec<u64>) -> Result<AmlValue, AmlError> {
        if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
            let obj = if let Some(s) = namespace.get(&name) {
                s.clone()
            } else {
                return Err(AmlError::AmlValueError);
            };

            self.get_index_core(obj, indices)
        } else {
            Err(AmlError::AmlValueError)
        }
    }

    fn get_index_core(&self, obj: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError> {
        match obj {
            AmlValue::String(ref string) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut bytes = string.clone().into_bytes();
                Ok(AmlValue::Integer(bytes[indices[0] as usize] as u64))
            },
            AmlValue::Buffer(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                Ok(AmlValue::Integer(b[indices[0] as usize] as u64))
            },
            AmlValue::BufferField(ref b) => {
                if indices.len() != 1 {
                    return Err(AmlError::AmlValueError);
                }

                let mut idx = indices[0];
                idx += b.index.get_as_integer()?;

                Ok(AmlValue::Integer(b.source_buf.get_as_buffer()?[idx as usize] as u64))
            },
            AmlValue::Package(ref p) => {
                if indices.len() < 0 {
                    return Err(AmlError::AmlValueError);
                }

                if indices.len() == 1 {
                    Ok(p[indices[0] as usize].clone())
                } else {
                    self.get_index_core(p[indices[0] as usize].clone(), indices[1..].to_vec())
                }
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get_index(&self, name: AmlValue, indices: Vec<u64>) -> Result<AmlValue, AmlError>{
        match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::Object(s) => self.get_index_final(s, indices),
                ObjectReference::Index(c, v) => {
                    let mut indices = indices.clone();
                    indices.push(v.get_as_integer()?);

                    self.get_index(*c, indices)
                },
                ObjectReference::ArgObj(_) => Err(AmlError::AmlValueError),
                ObjectReference::LocalObj(i) => {
                    let v = self.local_vars[i as usize].clone();
                    self.get_index_core(v, indices)
                }
            },
            _ => Err(AmlError::AmlValueError)
        }
    }

    pub fn get(&self, name: AmlValue) -> Result<AmlValue, AmlError> {
        Ok(match name {
            AmlValue::ObjectReference(r) => match r {
                ObjectReference::ArgObj(i) => self.arg_vars[i as usize].clone(),
                ObjectReference::LocalObj(i) => self.local_vars[i as usize].clone(),
                ObjectReference::Object(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
                    if let Some(o) = namespace.get(s) {
                        o.clone()
                    } else {
                        AmlValue::None
                    }
                } else { AmlValue::None },
                ObjectReference::Index(c, v) => self.get_index(*c, vec!(v.get_as_integer()?))?,
            },
            AmlValue::String(ref s) => if let Some(ref namespace) = *ACPI_TABLE.namespace.read() {
                if let Some(o) = namespace.get(s) {
                    o.clone()
                } else {
                    AmlValue::None
                }
            } else { AmlValue::None },
            _ => AmlValue::None
        })
    }
}
<|endoftext|>


<commit_before>use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::division_ring::DivisionRing;
use traits::rlmul::{RMul, LMul};
use traits::cross::Cross;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use traits::homogeneous::ToHomogeneous;
use traits::indexable::Indexable;
use traits::norm::Norm;
use vec::Vec1;
use mat::{Mat2, Mat3};
use vec::Vec3;

#[deriving(Eq, ToStr, Clone)]
pub struct Rotmat<M>
{ priv submat: M }

impl<M: Clone> Rotmat<M>
{
  pub fn submat(&self) -> M
  { self.submat.clone() }
}

impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>>
{
  pub fn from_angle(angle: N) -> Rotmat<Mat2<N>>
  {
    let (sia, coa) = angle.sin_cos();

    Rotmat { submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) }
  }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
  pub fn from_axis_angle(axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
  {
    if axisangle.sqnorm().is_zero()
    { One::one() }
    else
    {
      let mut axis   = axisangle;
      let angle      = axis.normalize();
      let _1         = One::one::<N>();
      let ux         = axis.x.clone();
      let uy         = axis.y.clone();
      let uz         = axis.z.clone();
      let sqx        = ux * ux;
      let sqy        = uy * uy;
      let sqz        = uz * uz;
      let (sin, cos) = angle.sin_cos();
      let one_m_cos  = _1 - cos;

      Rotmat {
        submat: Mat3::new(
                  (sqx + (_1 - sqx) * cos),
                  (ux * uy * one_m_cos - uz * sin),
                  (ux * uz * one_m_cos + uy * sin),

                  (ux * uy * one_m_cos + uz * sin),
                  (sqy + (_1 - sqy) * cos),
                  (uy * uz * one_m_cos - ux * sin),

                  (ux * uz * one_m_cos - uy * sin),
                  (uy * uz * one_m_cos + ux * sin),
                  (sqz + (_1 - sqz) * cos))
      }
    }
  }
}

impl<N: Clone + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
  pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>)
  {
    let zaxis = at.normalized();
    let xaxis = up.cross(&zaxis).normalized();
    let yaxis = zaxis.cross(&xaxis);

    self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
                            xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
                            xaxis.z        , yaxis.z        , zaxis.z)
  }
}

impl<N: Trigonometric + DivisionRing + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{
  #[inline]
  fn rotation(&self) -> Vec1<N>
  { Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0)))) }

  #[inline]
  fn inv_rotation(&self) -> Vec1<N>
  { -self.rotation() }

  #[inline]
  fn rotate_by(&mut self, rot: &Vec1<N>)
  { *self = self.rotated(rot) }
}

impl<N: Trigonometric + DivisionRing + Clone>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{
  #[inline]
  fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
  { Rotmat::from_angle(rot.x.clone()) * *self }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotation<Vec3<N>> for Rotmat<Mat3<N>>
{
  #[inline]
  fn rotation(&self) -> Vec3<N>
  { fail!("Not yet implemented.") }
  #[inline]

  fn inv_rotation(&self) -> Vec3<N>
  { fail!("Not yet implemented.") }

  #[inline]
  fn rotate_by(&mut self, rot: &Vec3<N>)
  { *self = self.rotated(rot) }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
{
  #[inline]
  fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
  { Rotmat::from_axis_angle(axisangle.clone()) * *self }
}

impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{
  #[inline]
  fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
  { Rotmat::from_angle(rng.gen()) }
}

impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M>
{
  #[inline]
  fn rotate(&self, v: &V) -> V
  { self.rmul(v) }

  #[inline]
  fn inv_rotate(&self, v: &V) -> V
  { self.lmul(v) }
}

impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
{
  #[inline]
  fn transform_vec(&self, v: &V) -> V
  { self.rotate(v) }

  #[inline]
  fn inv_transform(&self, v: &V) -> V
  { self.inv_rotate(v) }
}

impl<N: Clone + Rand + Trigonometric + DivisionRing + Algebraic>
Rand for Rotmat<Mat3<N>>
{
  #[inline]
  fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>>
  { Rotmat::from_axis_angle(rng.gen()) }
}

impl<M: Dim> Dim for Rotmat<M>
{
  #[inline]
  fn dim() -> uint
  { Dim::dim::<M>() }
}

impl<M: One + Zero> One for Rotmat<M>
{
  #[inline]
  fn one() -> Rotmat<M>
  { Rotmat { submat: One::one() } }
}

impl<M: Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M>
{
  #[inline]
  fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
  { Rotmat { submat: self.submat.mul(&other.submat) } }
}

impl<V, M: RMul<V>> RMul<V> for Rotmat<M>
{
  #[inline]
  fn rmul(&self, other: &V) -> V
  { self.submat.rmul(other) }
}

impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
{
  #[inline]
  fn lmul(&self, other: &V) -> V
  { self.submat.lmul(other) }
}

impl<M: Transpose> Inv for Rotmat<M>
{
  #[inline]
  fn inplace_inverse(&mut self) -> bool
  {
    self.transpose();

    true
  }

  #[inline]
  fn inverse(&self) -> Option<Rotmat<M>>
  { Some(self.transposed()) }
}

impl<M: Transpose>
Transpose for Rotmat<M>
{
  #[inline]
  fn transposed(&self) -> Rotmat<M>
  { Rotmat { submat: self.submat.transposed() } }

  #[inline]
  fn transpose(&mut self)
  { self.submat.transpose() }
}

// we loose the info that we are a rotation matrix
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M>
{
  fn to_homogeneous(&self) -> M2
  { self.submat.to_homogeneous() }
}

impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M>
{
  #[inline]
  fn approx_epsilon() -> N
  { ApproxEq::approx_epsilon::<N, N>() }

  #[inline]
  fn approx_eq(&self, other: &Rotmat<M>) -> bool
  { self.submat.approx_eq(&other.submat) }

  #[inline]
  fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool
  { self.submat.approx_eq_eps(&other.submat, epsilon) }
}
<commit_msg>Changed the semantic of the look_at method.<commit_after>use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::division_ring::DivisionRing;
use traits::rlmul::{RMul, LMul};
use traits::cross::Cross;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use traits::homogeneous::ToHomogeneous;
use traits::indexable::Indexable;
use traits::norm::Norm;
use vec::Vec1;
use mat::{Mat2, Mat3};
use vec::Vec3;

#[deriving(Eq, ToStr, Clone)]
pub struct Rotmat<M>
{ priv submat: M }

impl<M: Clone> Rotmat<M>
{
  pub fn submat(&self) -> M
  { self.submat.clone() }
}

impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>>
{
  pub fn from_angle(angle: N) -> Rotmat<Mat2<N>>
  {
    let (sia, coa) = angle.sin_cos();

    Rotmat { submat: Mat2::new(coa.clone(), -sia, sia.clone(), coa) }
  }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
  pub fn from_axis_angle(axisangle: Vec3<N>) -> Rotmat<Mat3<N>>
  {
    if axisangle.sqnorm().is_zero()
    { One::one() }
    else
    {
      let mut axis   = axisangle;
      let angle      = axis.normalize();
      let _1         = One::one::<N>();
      let ux         = axis.x.clone();
      let uy         = axis.y.clone();
      let uz         = axis.z.clone();
      let sqx        = ux * ux;
      let sqy        = uy * uy;
      let sqz        = uz * uz;
      let (sin, cos) = angle.sin_cos();
      let one_m_cos  = _1 - cos;

      Rotmat {
        submat: Mat3::new(
                  (sqx + (_1 - sqx) * cos),
                  (ux * uy * one_m_cos - uz * sin),
                  (ux * uz * one_m_cos + uy * sin),

                  (ux * uy * one_m_cos + uz * sin),
                  (sqy + (_1 - sqy) * cos),
                  (uy * uz * one_m_cos - ux * sin),

                  (ux * uz * one_m_cos - uy * sin),
                  (uy * uz * one_m_cos + ux * sin),
                  (sqz + (_1 - sqz) * cos))
      }
    }
  }
}

impl<N: Clone + DivisionRing + Algebraic> Rotmat<Mat3<N>>
{
  pub fn look_at(&mut self, at: &Vec3<N>, up: &Vec3<N>)
  {
    let xaxis = at.normalized();
    let zaxis = up.cross(&xaxis).normalized();
    let yaxis = zaxis.cross(&xaxis);

    self.submat = Mat3::new(xaxis.x.clone(), yaxis.x.clone(), zaxis.x.clone(),
                            xaxis.y.clone(), yaxis.y.clone(), zaxis.y.clone(),
                            xaxis.z        , yaxis.z        , zaxis.z)
  }
}

impl<N: Trigonometric + DivisionRing + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>>
{
  #[inline]
  fn rotation(&self) -> Vec1<N>
  { Vec1::new((-self.submat.at((0, 1))).atan2(&self.submat.at((0, 0)))) }

  #[inline]
  fn inv_rotation(&self) -> Vec1<N>
  { -self.rotation() }

  #[inline]
  fn rotate_by(&mut self, rot: &Vec1<N>)
  { *self = self.rotated(rot) }
}

impl<N: Trigonometric + DivisionRing + Clone>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>>
{
  #[inline]
  fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>>
  { Rotmat::from_angle(rot.x.clone()) * *self }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotation<Vec3<N>> for Rotmat<Mat3<N>>
{
  #[inline]
  fn rotation(&self) -> Vec3<N>
  { fail!("Not yet implemented.") }
  #[inline]

  fn inv_rotation(&self) -> Vec3<N>
  { fail!("Not yet implemented.") }

  #[inline]
  fn rotate_by(&mut self, rot: &Vec3<N>)
  { *self = self.rotated(rot) }
}

impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>>
{
  #[inline]
  fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>>
  { Rotmat::from_axis_angle(axisangle.clone()) * *self }
}

impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>>
{
  #[inline]
  fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat2<N>>
  { Rotmat::from_angle(rng.gen()) }
}

impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M>
{
  #[inline]
  fn rotate(&self, v: &V) -> V
  { self.rmul(v) }

  #[inline]
  fn inv_rotate(&self, v: &V) -> V
  { self.lmul(v) }
}

impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M>
{
  #[inline]
  fn transform_vec(&self, v: &V) -> V
  { self.rotate(v) }

  #[inline]
  fn inv_transform(&self, v: &V) -> V
  { self.inv_rotate(v) }
}

impl<N: Clone + Rand + Trigonometric + DivisionRing + Algebraic>
Rand for Rotmat<Mat3<N>>
{
  #[inline]
  fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>>
  { Rotmat::from_axis_angle(rng.gen()) }
}

impl<M: Dim> Dim for Rotmat<M>
{
  #[inline]
  fn dim() -> uint
  { Dim::dim::<M>() }
}

impl<M: One + Zero> One for Rotmat<M>
{
  #[inline]
  fn one() -> Rotmat<M>
  { Rotmat { submat: One::one() } }
}

impl<M: Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M>
{
  #[inline]
  fn mul(&self, other: &Rotmat<M>) -> Rotmat<M>
  { Rotmat { submat: self.submat.mul(&other.submat) } }
}

impl<V, M: RMul<V>> RMul<V> for Rotmat<M>
{
  #[inline]
  fn rmul(&self, other: &V) -> V
  { self.submat.rmul(other) }
}

impl<V, M: LMul<V>> LMul<V> for Rotmat<M>
{
  #[inline]
  fn lmul(&self, other: &V) -> V
  { self.submat.lmul(other) }
}

impl<M: Transpose> Inv for Rotmat<M>
{
  #[inline]
  fn inplace_inverse(&mut self) -> bool
  {
    self.transpose();

    true
  }

  #[inline]
  fn inverse(&self) -> Option<Rotmat<M>>
  { Some(self.transposed()) }
}

impl<M: Transpose>
Transpose for Rotmat<M>
{
  #[inline]
  fn transposed(&self) -> Rotmat<M>
  { Rotmat { submat: self.submat.transposed() } }

  #[inline]
  fn transpose(&mut self)
  { self.submat.transpose() }
}

// we loose the info that we are a rotation matrix
impl<M: ToHomogeneous<M2>, M2> ToHomogeneous<M2> for Rotmat<M>
{
  fn to_homogeneous(&self) -> M2
  { self.submat.to_homogeneous() }
}

impl<N: ApproxEq<N>, M: ApproxEq<N>> ApproxEq<N> for Rotmat<M>
{
  #[inline]
  fn approx_epsilon() -> N
  { ApproxEq::approx_epsilon::<N, N>() }

  #[inline]
  fn approx_eq(&self, other: &Rotmat<M>) -> bool
  { self.submat.approx_eq(&other.submat) }

  #[inline]
  fn approx_eq_eps(&self, other: &Rotmat<M>, epsilon: &N) -> bool
  { self.submat.approx_eq_eps(&other.submat, epsilon) }
}
<|endoftext|>


<commit_before>use crate::{
    analysis::{
        function_parameters::{async_param_to_remove, CParameter},
        functions::{find_function, find_index_to_ignore, finish_function_name},
        imports::Imports,
        out_parameters::use_function_return_for_result,
        rust_type::{bounds_rust_type, rust_type, rust_type_with_scope},
    },
    consts::TYPE_PARAMETERS_START,
    env::Env,
    library::{
        Class, Concurrency, Function, Fundamental, Nullable, ParameterDirection, Type, TypeId,
    },
    traits::IntoString,
};
use std::{collections::vec_deque::VecDeque, slice::Iter};

#[derive(Clone, Eq, Debug, PartialEq)]
pub enum BoundType {
    NoWrapper,
    // lifetime
    IsA(Option<char>),
    // lifetime <- shouldn't be used but just in case...
    AsRef(Option<char>),
}

impl BoundType {
    pub fn need_isa(&self) -> bool {
        match *self {
            BoundType::IsA(_) => true,
            _ => false,
        }
    }
}

#[derive(Clone, Eq, Debug, PartialEq)]
pub struct Bound {
    pub bound_type: BoundType,
    pub parameter_name: String,
    pub alias: char,
    pub type_str: String,
    pub info_for_next_type: bool,
    pub callback_modified: bool,
}

#[derive(Clone, Debug)]
pub struct Bounds {
    unused: VecDeque<char>,
    used: Vec<Bound>,
    unused_lifetimes: VecDeque<char>,
    lifetimes: Vec<char>,
}

impl Default for Bounds {
    fn default() -> Bounds {
        Bounds {
            unused: (TYPE_PARAMETERS_START as u8..)
                .take_while(|x| *x <= b'Z')
                .map(|x| x as char)
                .collect(),
            used: Vec::new(),
            unused_lifetimes: "abcdefg".chars().collect(),
            lifetimes: Vec::new(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct CallbackInfo {
    pub callback_type: String,
    pub success_parameters: String,
    pub error_parameters: String,
    pub bound_name: char,
}

impl Bounds {
    pub fn add_for_parameter(
        &mut self,
        env: &Env,
        func: &Function,
        par: &CParameter,
        r#async: bool,
        concurrency: Concurrency,
    ) -> (Option<String>, Option<CallbackInfo>) {
        let type_name = bounds_rust_type(env, par.typ);
        if (r#async && async_param_to_remove(&par.name)) || type_name.is_err() {
            return (None, None);
        }
        let mut type_string = type_name.into_string();
        let mut callback_info = None;
        let mut ret = None;
        let mut need_is_into_check = false;
        if !par.instance_parameter && par.direction != ParameterDirection::Out {
            if let Some(bound_type) = Bounds::type_for(env, par.typ, par.nullable) {
                ret = Some(Bounds::get_to_glib_extra(&bound_type));
                if r#async && par.name == "callback" {
                    let func_name = func.c_identifier.as_ref().unwrap();
                    let finish_func_name = finish_function_name(func_name);
                    if let Some(function) = find_function(env, &finish_func_name) {
                        let mut out_parameters = find_out_parameters(env, function);
                        if use_function_return_for_result(env, function.ret.typ) {
                            out_parameters
                                .insert(0, rust_type(env, function.ret.typ).into_string());
                        }
                        let parameters = format_out_parameters(&out_parameters);
                        let error_type = find_error_type(env, function);
                        type_string = format!(
                            "FnOnce(Result<{}, {}>) + Send + 'static",
                            parameters, error_type
                        );
                        let bound_name = *self.unused.front().unwrap();
                        callback_info = Some(CallbackInfo {
                            callback_type: type_string.clone(),
                            success_parameters: parameters,
                            error_parameters: error_type,
                            bound_name,
                        });
                    }
                } else if par.c_type == "GDestroyNotify" || env.library.type_(par.typ).is_function()
                {
                    need_is_into_check = par.c_type != "GDestroyNotify";
                    if let Type::Function(_) = env.library.type_(par.typ) {
                        type_string = rust_type_with_scope(env, par.typ, par.scope, concurrency)
                            .into_string();
                        let bound_name = *self.unused.front().unwrap();
                        callback_info = Some(CallbackInfo {
                            callback_type: type_string.clone(),
                            success_parameters: String::new(),
                            error_parameters: String::new(),
                            bound_name,
                        });
                    }
                }
                if (!need_is_into_check || !*par.nullable)
                    && par.c_type != "GDestroyNotify"
                    && !self.add_parameter(&par.name, &type_string, bound_type, r#async)
                {
                    panic!(
                        "Too many type constraints for {}",
                        func.c_identifier.as_ref().unwrap()
                    )
                }
            }
        } else if par.instance_parameter {
            if let Some(bound_type) = Bounds::type_for(env, par.typ, par.nullable) {
                ret = Some(Bounds::get_to_glib_extra(&bound_type));
            }
        }

        (ret, callback_info)
    }

    pub fn type_for(env: &Env, type_id: TypeId, nullable: Nullable) -> Option<BoundType> {
        use self::BoundType::*;
        match *env.library.type_(type_id) {
            Type::Fundamental(Fundamental::Filename) => Some(AsRef(None)),
            Type::Fundamental(Fundamental::OsString) => Some(AsRef(None)),
            Type::Fundamental(Fundamental::Utf8) if *nullable => None,
            Type::Class(Class { final_type, .. }) => {
                if final_type {
                    None
                } else {
                    Some(IsA(None))
                }
            }
            Type::Interface(..) => Some(IsA(None)),
            Type::List(_) | Type::SList(_) | Type::CArray(_) => None,
            Type::Fundamental(_) if *nullable => None,
            Type::Function(_) => Some(NoWrapper),
            _ => None,
        }
    }
    fn get_to_glib_extra(bound_type: &BoundType) -> String {
        use self::BoundType::*;
        match *bound_type {
            AsRef(_) => ".as_ref()".to_owned(),
            IsA(_) => ".as_ref()".to_owned(),
            _ => String::new(),
        }
    }
    pub fn add_parameter(
        &mut self,
        name: &str,
        type_str: &str,
        bound_type: BoundType,
        r#async: bool,
    ) -> bool {
        if r#async && name == "callback" {
            if let Some(alias) = self.unused.pop_front() {
                self.used.push(Bound {
                    bound_type: BoundType::NoWrapper,
                    parameter_name: name.to_owned(),
                    alias,
                    type_str: type_str.to_string(),
                    info_for_next_type: false,
                    callback_modified: false,
                });
                return true;
            }
            return false;
        }
        if self.used.iter().any(|n| n.parameter_name == name) {
            return false;
        }
        let type_str = type_str.to_owned();
        if let Some(alias) = self.unused.pop_front() {
            self.used.push(Bound {
                bound_type,
                parameter_name: name.to_owned(),
                alias,
                type_str: type_str.to_owned(),
                info_for_next_type: false,
                callback_modified: false,
            });
            true
        } else {
            false
        }
    }
    pub fn get_parameter_alias_info(&self, name: &str) -> Option<(char, BoundType)> {
        self.used
            .iter()
            .find(move |n| {
                if n.parameter_name == name {
                    !n.info_for_next_type
                } else {
                    false
                }
            })
            .map(|t| (t.alias, t.bound_type.clone()))
    }
    pub fn get_base_alias(&self, alias: char) -> Option<char> {
        if alias == TYPE_PARAMETERS_START {
            return None;
        }
        let prev_alias = ((alias as u8) - 1) as char;
        self.used
            .iter()
            .find(move |n| n.alias == prev_alias)
            .and_then(|b| {
                if b.info_for_next_type {
                    Some(b.alias)
                } else {
                    None
                }
            })
    }
    pub fn update_imports(&self, imports: &mut Imports) {
        //TODO: import with versions
        use self::BoundType::*;
        for used in &self.used {
            match used.bound_type {
                NoWrapper => (),
                IsA(_) => imports.add("glib::object::IsA", None),
                AsRef(_) => imports.add_used_type(&used.type_str, None),
            }
        }
    }
    pub fn is_empty(&self) -> bool {
        self.used.is_empty()
    }
    pub fn iter(&self) -> Iter<'_, Bound> {
        self.used.iter()
    }
    pub fn iter_lifetimes(&self) -> Iter<'_, char> {
        self.lifetimes.iter()
    }
}

fn find_out_parameters(env: &Env, function: &Function) -> Vec<String> {
    let index_to_ignore = find_index_to_ignore(&function.parameters);
    function
        .parameters
        .iter()
        .enumerate()
        .filter(|&(index, param)| {
            Some(index) != index_to_ignore
                && param.direction == ParameterDirection::Out
                && param.name != "error"
        })
        .map(|(_, param)| rust_type(env, param.typ).into_string())
        .collect()
}

fn format_out_parameters(parameters: &[String]) -> String {
    if parameters.len() == 1 {
        parameters[0].to_string()
    } else {
        format!("({})", parameters.join(", "))
    }
}

fn find_error_type(env: &Env, function: &Function) -> String {
    let error_param = function
        .parameters
        .iter()
        .find(|param| param.direction == ParameterDirection::Out && param.name == "error")
        .expect("error type");
    if let Type::Record(ref record) = *env.type_(error_param.typ) {
        return record.name.clone();
    }
    panic!("cannot find error type")
}

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

    #[test]
    fn get_new_all() {
        let mut bounds: Bounds = Default::default();
        let typ = BoundType::IsA(None);
        assert_eq!(bounds.add_parameter("a", "", typ.clone(), false), true);
        // Don't add second time
        assert_eq!(bounds.add_parameter("a", "", typ.clone(), false), false);
        assert_eq!(bounds.add_parameter("b", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("c", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("d", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("e", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("f", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("g", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("h", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("h", "", typ.clone(), false), false);
        assert_eq!(bounds.add_parameter("i", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("j", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("k", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("l", "", typ, false), false);
    }

    #[test]
    fn get_parameter_alias_info() {
        let mut bounds: Bounds = Default::default();
        let typ = BoundType::IsA(None);
        bounds.add_parameter("a", "", typ.clone(), false);
        bounds.add_parameter("b", "", typ.clone(), false);
        assert_eq!(
            bounds.get_parameter_alias_info("a"),
            Some(('P', typ.clone()))
        );
        assert_eq!(bounds.get_parameter_alias_info("b"), Some(('Q', typ)));
        assert_eq!(bounds.get_parameter_alias_info("c"), None);
    }
}
<commit_msg>Fix missing callback parameter handling<commit_after>use crate::{
    analysis::{
        function_parameters::{async_param_to_remove, CParameter},
        functions::{find_function, find_index_to_ignore, finish_function_name},
        imports::Imports,
        out_parameters::use_function_return_for_result,
        rust_type::{bounds_rust_type, rust_type, rust_type_with_scope},
    },
    consts::TYPE_PARAMETERS_START,
    env::Env,
    library::{
        Class, Concurrency, Function, Fundamental, Nullable, ParameterDirection, Type, TypeId,
    },
    traits::IntoString,
};
use std::{collections::vec_deque::VecDeque, slice::Iter};

#[derive(Clone, Eq, Debug, PartialEq)]
pub enum BoundType {
    NoWrapper,
    // lifetime
    IsA(Option<char>),
    // lifetime <- shouldn't be used but just in case...
    AsRef(Option<char>),
}

impl BoundType {
    pub fn need_isa(&self) -> bool {
        match *self {
            BoundType::IsA(_) => true,
            _ => false,
        }
    }
}

#[derive(Clone, Eq, Debug, PartialEq)]
pub struct Bound {
    pub bound_type: BoundType,
    pub parameter_name: String,
    pub alias: char,
    pub type_str: String,
    pub info_for_next_type: bool,
    pub callback_modified: bool,
}

#[derive(Clone, Debug)]
pub struct Bounds {
    unused: VecDeque<char>,
    used: Vec<Bound>,
    unused_lifetimes: VecDeque<char>,
    lifetimes: Vec<char>,
}

impl Default for Bounds {
    fn default() -> Bounds {
        Bounds {
            unused: (TYPE_PARAMETERS_START as u8..)
                .take_while(|x| *x <= b'Z')
                .map(|x| x as char)
                .collect(),
            used: Vec::new(),
            unused_lifetimes: "abcdefg".chars().collect(),
            lifetimes: Vec::new(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct CallbackInfo {
    pub callback_type: String,
    pub success_parameters: String,
    pub error_parameters: String,
    pub bound_name: char,
}

impl Bounds {
    pub fn add_for_parameter(
        &mut self,
        env: &Env,
        func: &Function,
        par: &CParameter,
        r#async: bool,
        concurrency: Concurrency,
    ) -> (Option<String>, Option<CallbackInfo>) {
        let type_name = bounds_rust_type(env, par.typ);
        if (r#async && async_param_to_remove(&par.name)) || type_name.is_err() {
            return (None, None);
        }
        let mut type_string = type_name.into_string();
        let mut callback_info = None;
        let mut ret = None;
        let mut need_is_into_check = false;
        if !par.instance_parameter && par.direction != ParameterDirection::Out {
            if let Some(bound_type) = Bounds::type_for(env, par.typ, par.nullable) {
                ret = Some(Bounds::get_to_glib_extra(&bound_type));
                if r#async && (par.name == "callback" || par.name.ends_with("_callback")) {
                    let func_name = func.c_identifier.as_ref().unwrap();
                    let finish_func_name = finish_function_name(func_name);
                    if let Some(function) = find_function(env, &finish_func_name) {
                        let mut out_parameters = find_out_parameters(env, function);
                        if use_function_return_for_result(env, function.ret.typ) {
                            out_parameters
                                .insert(0, rust_type(env, function.ret.typ).into_string());
                        }
                        let parameters = format_out_parameters(&out_parameters);
                        let error_type = find_error_type(env, function);
                        type_string = format!(
                            "FnOnce(Result<{}, {}>) + Send + 'static",
                            parameters, error_type
                        );
                        let bound_name = *self.unused.front().unwrap();
                        callback_info = Some(CallbackInfo {
                            callback_type: type_string.clone(),
                            success_parameters: parameters,
                            error_parameters: error_type,
                            bound_name,
                        });
                    }
                } else if par.c_type == "GDestroyNotify" || env.library.type_(par.typ).is_function()
                {
                    need_is_into_check = par.c_type != "GDestroyNotify";
                    if let Type::Function(_) = env.library.type_(par.typ) {
                        type_string = rust_type_with_scope(env, par.typ, par.scope, concurrency)
                            .into_string();
                        let bound_name = *self.unused.front().unwrap();
                        callback_info = Some(CallbackInfo {
                            callback_type: type_string.clone(),
                            success_parameters: String::new(),
                            error_parameters: String::new(),
                            bound_name,
                        });
                    }
                }
                if (!need_is_into_check || !*par.nullable)
                    && par.c_type != "GDestroyNotify"
                    && !self.add_parameter(&par.name, &type_string, bound_type, r#async)
                {
                    panic!(
                        "Too many type constraints for {}",
                        func.c_identifier.as_ref().unwrap()
                    )
                }
            }
        } else if par.instance_parameter {
            if let Some(bound_type) = Bounds::type_for(env, par.typ, par.nullable) {
                ret = Some(Bounds::get_to_glib_extra(&bound_type));
            }
        }

        (ret, callback_info)
    }

    pub fn type_for(env: &Env, type_id: TypeId, nullable: Nullable) -> Option<BoundType> {
        use self::BoundType::*;
        match *env.library.type_(type_id) {
            Type::Fundamental(Fundamental::Filename) => Some(AsRef(None)),
            Type::Fundamental(Fundamental::OsString) => Some(AsRef(None)),
            Type::Fundamental(Fundamental::Utf8) if *nullable => None,
            Type::Class(Class { final_type, .. }) => {
                if final_type {
                    None
                } else {
                    Some(IsA(None))
                }
            }
            Type::Interface(..) => Some(IsA(None)),
            Type::List(_) | Type::SList(_) | Type::CArray(_) => None,
            Type::Fundamental(_) if *nullable => None,
            Type::Function(_) => Some(NoWrapper),
            _ => None,
        }
    }
    fn get_to_glib_extra(bound_type: &BoundType) -> String {
        use self::BoundType::*;
        match *bound_type {
            AsRef(_) => ".as_ref()".to_owned(),
            IsA(_) => ".as_ref()".to_owned(),
            _ => String::new(),
        }
    }
    pub fn add_parameter(
        &mut self,
        name: &str,
        type_str: &str,
        bound_type: BoundType,
        r#async: bool,
    ) -> bool {
        if r#async && name == "callback" {
            if let Some(alias) = self.unused.pop_front() {
                self.used.push(Bound {
                    bound_type: BoundType::NoWrapper,
                    parameter_name: name.to_owned(),
                    alias,
                    type_str: type_str.to_string(),
                    info_for_next_type: false,
                    callback_modified: false,
                });
                return true;
            }
            return false;
        }
        if self.used.iter().any(|n| n.parameter_name == name) {
            return false;
        }
        let type_str = type_str.to_owned();
        if let Some(alias) = self.unused.pop_front() {
            self.used.push(Bound {
                bound_type,
                parameter_name: name.to_owned(),
                alias,
                type_str: type_str.to_owned(),
                info_for_next_type: false,
                callback_modified: false,
            });
            true
        } else {
            false
        }
    }
    pub fn get_parameter_alias_info(&self, name: &str) -> Option<(char, BoundType)> {
        self.used
            .iter()
            .find(move |n| {
                if n.parameter_name == name {
                    !n.info_for_next_type
                } else {
                    false
                }
            })
            .map(|t| (t.alias, t.bound_type.clone()))
    }
    pub fn get_base_alias(&self, alias: char) -> Option<char> {
        if alias == TYPE_PARAMETERS_START {
            return None;
        }
        let prev_alias = ((alias as u8) - 1) as char;
        self.used
            .iter()
            .find(move |n| n.alias == prev_alias)
            .and_then(|b| {
                if b.info_for_next_type {
                    Some(b.alias)
                } else {
                    None
                }
            })
    }
    pub fn update_imports(&self, imports: &mut Imports) {
        //TODO: import with versions
        use self::BoundType::*;
        for used in &self.used {
            match used.bound_type {
                NoWrapper => (),
                IsA(_) => imports.add("glib::object::IsA", None),
                AsRef(_) => imports.add_used_type(&used.type_str, None),
            }
        }
    }
    pub fn is_empty(&self) -> bool {
        self.used.is_empty()
    }
    pub fn iter(&self) -> Iter<'_, Bound> {
        self.used.iter()
    }
    pub fn iter_lifetimes(&self) -> Iter<'_, char> {
        self.lifetimes.iter()
    }
}

fn find_out_parameters(env: &Env, function: &Function) -> Vec<String> {
    let index_to_ignore = find_index_to_ignore(&function.parameters);
    function
        .parameters
        .iter()
        .enumerate()
        .filter(|&(index, param)| {
            Some(index) != index_to_ignore
                && param.direction == ParameterDirection::Out
                && param.name != "error"
        })
        .map(|(_, param)| rust_type(env, param.typ).into_string())
        .collect()
}

fn format_out_parameters(parameters: &[String]) -> String {
    if parameters.len() == 1 {
        parameters[0].to_string()
    } else {
        format!("({})", parameters.join(", "))
    }
}

fn find_error_type(env: &Env, function: &Function) -> String {
    let error_param = function
        .parameters
        .iter()
        .find(|param| param.direction == ParameterDirection::Out && param.name == "error")
        .expect("error type");
    if let Type::Record(ref record) = *env.type_(error_param.typ) {
        return record.name.clone();
    }
    panic!("cannot find error type")
}

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

    #[test]
    fn get_new_all() {
        let mut bounds: Bounds = Default::default();
        let typ = BoundType::IsA(None);
        assert_eq!(bounds.add_parameter("a", "", typ.clone(), false), true);
        // Don't add second time
        assert_eq!(bounds.add_parameter("a", "", typ.clone(), false), false);
        assert_eq!(bounds.add_parameter("b", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("c", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("d", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("e", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("f", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("g", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("h", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("h", "", typ.clone(), false), false);
        assert_eq!(bounds.add_parameter("i", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("j", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("k", "", typ.clone(), false), true);
        assert_eq!(bounds.add_parameter("l", "", typ, false), false);
    }

    #[test]
    fn get_parameter_alias_info() {
        let mut bounds: Bounds = Default::default();
        let typ = BoundType::IsA(None);
        bounds.add_parameter("a", "", typ.clone(), false);
        bounds.add_parameter("b", "", typ.clone(), false);
        assert_eq!(
            bounds.get_parameter_alias_info("a"),
            Some(('P', typ.clone()))
        );
        assert_eq!(bounds.get_parameter_alias_info("b"), Some(('Q', typ)));
        assert_eq!(bounds.get_parameter_alias_info("c"), None);
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "android")]

extern crate android_glue;

use libc;

use CreationError::{self, OsError};

use winit;

use Api;
use ContextError;
use GlAttributes;
use PixelFormat;
use PixelFormatRequirements;

use api::egl;
use api::egl::Context as EglContext;

mod ffi;

pub struct Context {
    egl_context: EglContext,
}

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

impl Context {
    pub fn new(
        _window: &winit::Window,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
    ) -> Result<Self, CreationError>
    {
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.egl_context);
        let native_window = unsafe { android_glue::get_native_window() };
        if native_window.is_null() {
            return Err(OsError(format!("Android's native window is null")));
        }
        let egl = egl::ffi::egl::Egl;
        let native_display = egl::NativeDisplay::Android;
        let context = try!(EglContext::new(egl, pf_reqs, &gl_attr, native_display)
            .and_then(|p| p.finish(native_window as *const _)));
        Ok(Context { egl_context: context })
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.egl_context.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.egl_context.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.egl_context.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        self.egl_context.swap_buffers()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.egl_context.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.egl_context.get_pixel_format()
    }
}

pub struct HeadlessContext(EglContext);

unsafe impl Send for HeadlessContext {}
unsafe impl Sync for HeadlessContext {}

impl HeadlessContext {
    /// See the docs in the crate root file.
    pub fn new(
        dimensions: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&HeadlessContext>,
        _: &PlatformSpecificHeadlessBuilderAttributes,
    ) -> Result<Self, CreationError>
    {
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0);
        let context = try!(EglContext::new(egl::ffi::egl::Egl,
                                           pf_reqs,
                                           &gl_attr,
                                           egl::NativeDisplay::Android));
        let context = try!(context.finish_pbuffer(dimensions));     // TODO:
        Ok(HeadlessContext(context))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.0.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.0.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.0.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        self.0.swap_buffers()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.0.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.0.get_pixel_format()
    }
}
<commit_msg>Update android platform to switch from Window to WindowBuilder<commit_after>#![cfg(target_os = "android")]

extern crate android_glue;

use libc;

use CreationError::{self, OsError};

use winit;

use Api;
use ContextError;
use GlAttributes;
use PixelFormat;
use PixelFormatRequirements;

use api::egl;
use api::egl::Context as EglContext;

mod ffi;

pub struct Context {
    egl_context: EglContext,
}

#[derive(Clone, Default)]
pub struct PlatformSpecificHeadlessBuilderAttributes;

impl Context {
    pub fn new(
        window_builder: winit::WindowBuilder,
        events_loop: &winit::EventsLoop,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
    ) -> Result<(winit::Window, Self), CreationError>
    {
        let window = try!(window_builder.build(events_loop));
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.egl_context);
        let native_window = unsafe { android_glue::get_native_window() };
        if native_window.is_null() {
            return Err(OsError(format!("Android's native window is null")));
        }
        let egl = egl::ffi::egl::Egl;
        let native_display = egl::NativeDisplay::Android;
        let context = try!(EglContext::new(egl, pf_reqs, &gl_attr, native_display)
            .and_then(|p| p.finish(native_window as *const _)));
        let context = Context { egl_context: context };
        Ok((window, context))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.egl_context.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.egl_context.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.egl_context.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        self.egl_context.swap_buffers()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.egl_context.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.egl_context.get_pixel_format()
    }
}

pub struct HeadlessContext(EglContext);

unsafe impl Send for HeadlessContext {}
unsafe impl Sync for HeadlessContext {}

impl HeadlessContext {
    /// See the docs in the crate root file.
    pub fn new(
        dimensions: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&HeadlessContext>,
        _: &PlatformSpecificHeadlessBuilderAttributes,
    ) -> Result<Self, CreationError>
    {
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0);
        let context = try!(EglContext::new(egl::ffi::egl::Egl,
                                           pf_reqs,
                                           &gl_attr,
                                           egl::NativeDisplay::Android));
        let context = try!(context.finish_pbuffer(dimensions));     // TODO:
        Ok(HeadlessContext(context))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.0.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.0.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.0.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        self.0.swap_buffers()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.0.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.0.get_pixel_format()
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::ops::Deref;

#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;

use base::allocator::Allocator;
use base::default_allocator::DefaultAllocator;
use base::dimension::{Dim, DimName, Dynamic, U1};
use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut};
use base::{Scalar, Vector};
use base::constraint::{SameNumberOfRows, ShapeConstraint};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

/*
 *
 * Storage.
 *
 */
/// A Vec-based matrix data storage. It may be dynamically-sized.
#[repr(C)]
#[derive(Eq, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct MatrixVec<N, R: Dim, C: Dim> {
    data: Vec<N>,
    nrows: R,
    ncols: C,
}

impl<N, R: Dim, C: Dim> MatrixVec<N, R, C> {
    /// Creates a new dynamic matrix data storage from the given vector and shape.
    #[inline]
    pub fn new(nrows: R, ncols: C, data: Vec<N>) -> MatrixVec<N, R, C> {
        assert!(
            nrows.value() * ncols.value() == data.len(),
            "Data storage buffer dimension mismatch."
        );
        MatrixVec {
            data: data,
            nrows: nrows,
            ncols: ncols,
        }
    }

    /// The underlying data storage.
    #[inline]
    pub fn data(&self) -> &Vec<N> {
        &self.data
    }

    /// The underlying mutable data storage.
    ///
    /// This is unsafe because this may cause UB if the vector is modified by the user.
    #[inline]
    pub unsafe fn data_mut(&mut self) -> &mut Vec<N> {
        &mut self.data
    }

    /// Resizes the underlying mutable data storage and unwraps it.
    ///
    /// If `sz` is larger than the current size, additional elements are uninitialized.
    /// If `sz` is smaller than the current size, additional elements are truncated.
    #[inline]
    pub unsafe fn resize(mut self, sz: usize) -> Vec<N> {
        let len = self.len();

        if sz < len {
            self.data.set_len(sz);
            self.data.shrink_to_fit();
        } else {
            self.data.reserve_exact(sz - len);
            self.data.set_len(sz);
        }

        self.data
    }
}

impl<N, R: Dim, C: Dim> Deref for MatrixVec<N, R, C> {
    type Target = Vec<N>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

/*
 *
 * Dynamic − Static
 * Dynamic − Dynamic
 *
 */
unsafe impl<N: Scalar, C: Dim> Storage<N, Dynamic, C> for MatrixVec<N, Dynamic, C>
where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{
    type RStride = U1;
    type CStride = Dynamic;

    #[inline]
    fn ptr(&self) -> *const N {
        self.data.as_ptr()
    }

    #[inline]
    fn shape(&self) -> (Dynamic, C) {
        (self.nrows, self.ncols)
    }

    #[inline]
    fn strides(&self) -> (Self::RStride, Self::CStride) {
        (Self::RStride::name(), self.nrows)
    }

    #[inline]
    fn is_contiguous(&self) -> bool {
        true
    }

    #[inline]
    fn into_owned(self) -> Owned<N, Dynamic, C>
    where DefaultAllocator: Allocator<N, Dynamic, C> {
        self
    }

    #[inline]
    fn clone_owned(&self) -> Owned<N, Dynamic, C>
    where DefaultAllocator: Allocator<N, Dynamic, C> {
        self.clone()
    }

    #[inline]
    fn as_slice(&self) -> &[N] {
        &self[..]
    }
}

unsafe impl<N: Scalar, R: DimName> Storage<N, R, Dynamic> for MatrixVec<N, R, Dynamic>
where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{
    type RStride = U1;
    type CStride = R;

    #[inline]
    fn ptr(&self) -> *const N {
        self.data.as_ptr()
    }

    #[inline]
    fn shape(&self) -> (R, Dynamic) {
        (self.nrows, self.ncols)
    }

    #[inline]
    fn strides(&self) -> (Self::RStride, Self::CStride) {
        (Self::RStride::name(), self.nrows)
    }

    #[inline]
    fn is_contiguous(&self) -> bool {
        true
    }

    #[inline]
    fn into_owned(self) -> Owned<N, R, Dynamic>
    where DefaultAllocator: Allocator<N, R, Dynamic> {
        self
    }

    #[inline]
    fn clone_owned(&self) -> Owned<N, R, Dynamic>
    where DefaultAllocator: Allocator<N, R, Dynamic> {
        self.clone()
    }

    #[inline]
    fn as_slice(&self) -> &[N] {
        &self[..]
    }
}

/*
 *
 * StorageMut, ContiguousStorage.
 *
 */
unsafe impl<N: Scalar, C: Dim> StorageMut<N, Dynamic, C> for MatrixVec<N, Dynamic, C>
where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{
    #[inline]
    fn ptr_mut(&mut self) -> *mut N {
        self.data.as_mut_ptr()
    }

    #[inline]
    fn as_mut_slice(&mut self) -> &mut [N] {
        &mut self.data[..]
    }
}

unsafe impl<N: Scalar, C: Dim> ContiguousStorage<N, Dynamic, C> for MatrixVec<N, Dynamic, C> where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{}

unsafe impl<N: Scalar, C: Dim> ContiguousStorageMut<N, Dynamic, C> for MatrixVec<N, Dynamic, C> where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{}

unsafe impl<N: Scalar, R: DimName> StorageMut<N, R, Dynamic> for MatrixVec<N, R, Dynamic>
where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{
    #[inline]
    fn ptr_mut(&mut self) -> *mut N {
        self.data.as_mut_ptr()
    }

    #[inline]
    fn as_mut_slice(&mut self) -> &mut [N] {
        &mut self.data[..]
    }
}

#[cfg(feature = "abomonation-serialize")]
impl<N: Abomonation, R: Dim, C: Dim> Abomonation for MatrixVec<N, R, C> {
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.data.entomb(writer)
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.data.exhume(bytes)
    }

    fn extent(&self) -> usize {
        self.data.extent()
    }
}

unsafe impl<N: Scalar, R: DimName> ContiguousStorage<N, R, Dynamic> for MatrixVec<N, R, Dynamic> where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{}

unsafe impl<N: Scalar, R: DimName> ContiguousStorageMut<N, R, Dynamic> for MatrixVec<N, R, Dynamic> where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{}

impl<N, R: Dim> Extend<N> for MatrixVec<N, R, Dynamic>
{
    /// Extends the number of columns of the `MatrixVec` with elements
    /// from the given iterator.
    ///
    /// # Panics
    /// This function panics if the number of elements yielded by the
    /// given iterator is not a multiple of the number of rows of the
    /// `MatrixVec`.
    fn extend<I: IntoIterator<Item=N>>(&mut self, iter: I)
    {
        self.data.extend(iter);
        self.ncols = Dynamic::new(self.data.len() / self.nrows.value());
        assert!(self.data.len() % self.nrows.value() == 0,
          "The number of elements produced by the given iterator was not a multiple of the number of rows.");
    }
}

impl<N, R, RV, SV> Extend<Vector<N, RV, SV>> for MatrixVec<N, R, Dynamic>
where
    N: Scalar,
    R: Dim,
    RV: Dim,
    SV: Storage<N, RV>,
    ShapeConstraint: SameNumberOfRows<R, RV>,
{
    /// Extends the number of columns of the `MatrixVec` with vectors
    /// from the given iterator.
    ///
    /// # Panics
    /// This function panics if the number of rows of each `Vector`
    /// yielded by the iterator is not equal to the number of rows
    /// of this `MatrixVec`.
    fn extend<I: IntoIterator<Item=Vector<N, RV, SV>>>(&mut self, iter: I)
    {
        let nrows = self.nrows.value();
        let iter = iter.into_iter();
        let (lower, _upper) = iter.size_hint();
        self.data.reserve(nrows * lower);
        for vector in iter {
            assert_eq!(nrows, vector.shape().0);
            self.data.extend(vector.iter());
        }
        self.ncols = Dynamic::new(self.data.len() / nrows);
    }
}

impl<N> Extend<N> for MatrixVec<N, Dynamic, U1>
{
    /// Extends the number of rows of the `MatrixVec` with elements
    /// from the given iterator.
    fn extend<I: IntoIterator<Item=N>>(&mut self, iter: I)
    {
        self.data.extend(iter);
        self.nrows = Dynamic::new(self.data.len());
    }
}
<commit_msg>Implement `Into<Vec<N>>` for `MatrixVec<N, R, C>`<commit_after>#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::ops::Deref;

#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;

use base::allocator::Allocator;
use base::default_allocator::DefaultAllocator;
use base::dimension::{Dim, DimName, Dynamic, U1};
use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut};
use base::{Scalar, Vector};
use base::constraint::{SameNumberOfRows, ShapeConstraint};

#[cfg(feature = "abomonation-serialize")]
use abomonation::Abomonation;

/*
 *
 * Storage.
 *
 */
/// A Vec-based matrix data storage. It may be dynamically-sized.
#[repr(C)]
#[derive(Eq, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct MatrixVec<N, R: Dim, C: Dim> {
    data: Vec<N>,
    nrows: R,
    ncols: C,
}

impl<N, R: Dim, C: Dim> MatrixVec<N, R, C> {
    /// Creates a new dynamic matrix data storage from the given vector and shape.
    #[inline]
    pub fn new(nrows: R, ncols: C, data: Vec<N>) -> MatrixVec<N, R, C> {
        assert!(
            nrows.value() * ncols.value() == data.len(),
            "Data storage buffer dimension mismatch."
        );
        MatrixVec {
            data: data,
            nrows: nrows,
            ncols: ncols,
        }
    }

    /// The underlying data storage.
    #[inline]
    pub fn data(&self) -> &Vec<N> {
        &self.data
    }

    /// The underlying mutable data storage.
    ///
    /// This is unsafe because this may cause UB if the vector is modified by the user.
    #[inline]
    pub unsafe fn data_mut(&mut self) -> &mut Vec<N> {
        &mut self.data
    }

    /// Resizes the underlying mutable data storage and unwraps it.
    ///
    /// If `sz` is larger than the current size, additional elements are uninitialized.
    /// If `sz` is smaller than the current size, additional elements are truncated.
    #[inline]
    pub unsafe fn resize(mut self, sz: usize) -> Vec<N> {
        let len = self.len();

        if sz < len {
            self.data.set_len(sz);
            self.data.shrink_to_fit();
        } else {
            self.data.reserve_exact(sz - len);
            self.data.set_len(sz);
        }

        self.data
    }
}

impl<N, R: Dim, C: Dim> Deref for MatrixVec<N, R, C> {
    type Target = Vec<N>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl<N, R: Dim, C: Dim> Into<Vec<N>> for MatrixVec<N, R, C>
{
    fn into(self) -> Vec<N> {
        self.data
    }
}

/*
 *
 * Dynamic − Static
 * Dynamic − Dynamic
 *
 */
unsafe impl<N: Scalar, C: Dim> Storage<N, Dynamic, C> for MatrixVec<N, Dynamic, C>
where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{
    type RStride = U1;
    type CStride = Dynamic;

    #[inline]
    fn ptr(&self) -> *const N {
        self.data.as_ptr()
    }

    #[inline]
    fn shape(&self) -> (Dynamic, C) {
        (self.nrows, self.ncols)
    }

    #[inline]
    fn strides(&self) -> (Self::RStride, Self::CStride) {
        (Self::RStride::name(), self.nrows)
    }

    #[inline]
    fn is_contiguous(&self) -> bool {
        true
    }

    #[inline]
    fn into_owned(self) -> Owned<N, Dynamic, C>
    where DefaultAllocator: Allocator<N, Dynamic, C> {
        self
    }

    #[inline]
    fn clone_owned(&self) -> Owned<N, Dynamic, C>
    where DefaultAllocator: Allocator<N, Dynamic, C> {
        self.clone()
    }

    #[inline]
    fn as_slice(&self) -> &[N] {
        &self[..]
    }
}

unsafe impl<N: Scalar, R: DimName> Storage<N, R, Dynamic> for MatrixVec<N, R, Dynamic>
where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{
    type RStride = U1;
    type CStride = R;

    #[inline]
    fn ptr(&self) -> *const N {
        self.data.as_ptr()
    }

    #[inline]
    fn shape(&self) -> (R, Dynamic) {
        (self.nrows, self.ncols)
    }

    #[inline]
    fn strides(&self) -> (Self::RStride, Self::CStride) {
        (Self::RStride::name(), self.nrows)
    }

    #[inline]
    fn is_contiguous(&self) -> bool {
        true
    }

    #[inline]
    fn into_owned(self) -> Owned<N, R, Dynamic>
    where DefaultAllocator: Allocator<N, R, Dynamic> {
        self
    }

    #[inline]
    fn clone_owned(&self) -> Owned<N, R, Dynamic>
    where DefaultAllocator: Allocator<N, R, Dynamic> {
        self.clone()
    }

    #[inline]
    fn as_slice(&self) -> &[N] {
        &self[..]
    }
}

/*
 *
 * StorageMut, ContiguousStorage.
 *
 */
unsafe impl<N: Scalar, C: Dim> StorageMut<N, Dynamic, C> for MatrixVec<N, Dynamic, C>
where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{
    #[inline]
    fn ptr_mut(&mut self) -> *mut N {
        self.data.as_mut_ptr()
    }

    #[inline]
    fn as_mut_slice(&mut self) -> &mut [N] {
        &mut self.data[..]
    }
}

unsafe impl<N: Scalar, C: Dim> ContiguousStorage<N, Dynamic, C> for MatrixVec<N, Dynamic, C> where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{}

unsafe impl<N: Scalar, C: Dim> ContiguousStorageMut<N, Dynamic, C> for MatrixVec<N, Dynamic, C> where DefaultAllocator: Allocator<N, Dynamic, C, Buffer = Self>
{}

unsafe impl<N: Scalar, R: DimName> StorageMut<N, R, Dynamic> for MatrixVec<N, R, Dynamic>
where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{
    #[inline]
    fn ptr_mut(&mut self) -> *mut N {
        self.data.as_mut_ptr()
    }

    #[inline]
    fn as_mut_slice(&mut self) -> &mut [N] {
        &mut self.data[..]
    }
}

#[cfg(feature = "abomonation-serialize")]
impl<N: Abomonation, R: Dim, C: Dim> Abomonation for MatrixVec<N, R, C> {
    unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
        self.data.entomb(writer)
    }

    unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
        self.data.exhume(bytes)
    }

    fn extent(&self) -> usize {
        self.data.extent()
    }
}

unsafe impl<N: Scalar, R: DimName> ContiguousStorage<N, R, Dynamic> for MatrixVec<N, R, Dynamic> where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{}

unsafe impl<N: Scalar, R: DimName> ContiguousStorageMut<N, R, Dynamic> for MatrixVec<N, R, Dynamic> where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self>
{}

impl<N, R: Dim> Extend<N> for MatrixVec<N, R, Dynamic>
{
    /// Extends the number of columns of the `MatrixVec` with elements
    /// from the given iterator.
    ///
    /// # Panics
    /// This function panics if the number of elements yielded by the
    /// given iterator is not a multiple of the number of rows of the
    /// `MatrixVec`.
    fn extend<I: IntoIterator<Item=N>>(&mut self, iter: I)
    {
        self.data.extend(iter);
        self.ncols = Dynamic::new(self.data.len() / self.nrows.value());
        assert!(self.data.len() % self.nrows.value() == 0,
          "The number of elements produced by the given iterator was not a multiple of the number of rows.");
    }
}

impl<N, R, RV, SV> Extend<Vector<N, RV, SV>> for MatrixVec<N, R, Dynamic>
where
    N: Scalar,
    R: Dim,
    RV: Dim,
    SV: Storage<N, RV>,
    ShapeConstraint: SameNumberOfRows<R, RV>,
{
    /// Extends the number of columns of the `MatrixVec` with vectors
    /// from the given iterator.
    ///
    /// # Panics
    /// This function panics if the number of rows of each `Vector`
    /// yielded by the iterator is not equal to the number of rows
    /// of this `MatrixVec`.
    fn extend<I: IntoIterator<Item=Vector<N, RV, SV>>>(&mut self, iter: I)
    {
        let nrows = self.nrows.value();
        let iter = iter.into_iter();
        let (lower, _upper) = iter.size_hint();
        self.data.reserve(nrows * lower);
        for vector in iter {
            assert_eq!(nrows, vector.shape().0);
            self.data.extend(vector.iter());
        }
        self.ncols = Dynamic::new(self.data.len() / nrows);
    }
}

impl<N> Extend<N> for MatrixVec<N, Dynamic, U1>
{
    /// Extends the number of rows of the `MatrixVec` with elements
    /// from the given iterator.
    fn extend<I: IntoIterator<Item=N>>(&mut self, iter: I)
    {
        self.data.extend(iter);
        self.nrows = Dynamic::new(self.data.len());
    }
}
<|endoftext|>