<commit_before>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn commit_interactive(config: &Value) -> bool {
    warn!("Interactive committing not yet supported, using dummy commit message");
    false
}

pub fn commit_message(config: &Value, action: StoreAction) -> String {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        String::from("Dummy commit")
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<commit_msg>The helper commit_message() really should return an Result<String><commit_after>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

pub fn commit_interactive(config: &Value) -> bool {
    warn!("Interactive committing not yet supported, using dummy commit message");
    false
}

pub fn commit_message(config: &Value, action: StoreAction) -> Result<String> {
    if commit_interactive(config) {
        unimplemented!()
    } else {
        Ok(String::from("Dummy commit"))
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<|endoftext|>


<commit_before>pub mod modint;

const P: i64 = 1_000_000_007;

/// Calculates `x^n`. O(log n) time.
/// By Fermat's little theorem, `x^(-1) = pow(x, P - 2)`.
pub fn pow(x: i64, n: i64) -> i64 {
    let (mut x, mut y, mut n) = (x % P, 1_i64, n);
    while n > 0 {
        if n % 2 != 0 {
            y = (y * x) % P;
            n -= 1;
        }

        x = (x * x) % P;
        n /= 2;
    }
    y
}

/// Calculates `1/a` for each `a` in `1..n`.
/// Use `P = floor(P / k) * k + P % k` for proof.
pub fn inv_dp(n: usize) -> Vec<i64> {
    let mut dp = vec![0; n];
    if n >= 2 {
        dp[1] = 1;
        for i in 2..n {
            let mut z = P - dp[(P % i as i64) as usize];
            z %= P;
            z *= P / i as i64;
            z %= P;
            dp[i] = z;
        }
    }
    dp
}

#[cfg(test)]
mod tests {
    use super::{inv_dp, pow, P};
    use std;

    #[test]
    fn test_pow_edges() {
        assert_eq!(pow(0, 0), 1);
        assert_eq!(pow(2, 0), 1);
        assert_eq!(pow(3, 1), 3);
        assert_eq!(pow(5, 6), (5 * 5 * 5) * (5 * 5 * 5));
        assert_eq!(pow(std::i64::MAX % P, std::i64::MAX), 856225998);
    }

    #[test]
    fn test_pow_small() {
        for x in 0..100_i64 {
            for n in 0..100_i64 {
                let actual = pow(x, n);
                let expected = (0..n).fold(1_i64, |acc, _| (acc * x) % P);
                assert_eq!(actual, expected, "{}^{}", x, n);
            }
        }
    }

    #[test]
    fn test_inv_dp() {
        let n = 10000;
        let dp = inv_dp(n);
        for i in 1..n {
            let mut z = dp[i] * i as i64;
            z %= P;
            z += P;
            z %= P;
            assert_eq!(z, 1);
        }
    }
}
<commit_msg>feat: choose を追加<commit_after>pub mod modint;

const P: i64 = 1_000_000_007;

/// Calculates `x^n`. O(log n) time.
/// By Fermat's little theorem, `x^(-1) = pow(x, P - 2)`.
pub fn pow(x: i64, n: i64) -> i64 {
    let (mut x, mut y, mut n) = (x % P, 1_i64, n);
    while n > 0 {
        if n % 2 != 0 {
            y = (y * x) % P;
            n -= 1;
        }

        x = (x * x) % P;
        n /= 2;
    }
    y
}

/// Calculates `1/a` for each `a` in `1..n`.
/// Use `P = floor(P / k) * k + P % k` for proof.
pub fn inv_dp(n: usize) -> Vec<i64> {
    let mut dp = vec![0; n];
    if n >= 2 {
        dp[1] = 1;
        for i in 2..n {
            let mut z = P - dp[(P % i as i64) as usize];
            z %= P;
            z *= P / i as i64;
            z %= P;
            dp[i] = z;
        }
    }
    dp
}

pub struct ChooseFn {
    fact: Vec<i64>,
    fact_inv: Vec<i64>,
}

impl ChooseFn {
    pub fn new(m: usize) -> Self {
        let mut fact = vec![0; m];
        fact[0] = 1;
        fact[1] = 1;
        for i in 2..m {
            fact[i] = (i as i64) * fact[i - 1] % P;
        }

        let mut fact_inv = vec![0; m];
        fact_inv[m - 1] = pow(fact[m - 1], P - 2);
        for i in (1..m).rev() {
            fact_inv[i - 1] = (i as i64) * fact_inv[i] % P;
        }

        ChooseFn {
            fact: fact,
            fact_inv: fact_inv,
        }
    }

    pub fn call(&self, n: usize, r: usize) -> i64 {
        if n < r {
            return 0;
        }

        let mut t = self.fact[n];
        t *= self.fact_inv[n - r];
        t %= P;
        t *= self.fact_inv[r];
        t % P
    }
}

#[cfg(test)]
mod tests {
    use super::{inv_dp, pow, ChooseFn, P};
    use std;

    #[test]
    fn test_pow_edges() {
        assert_eq!(pow(0, 0), 1);
        assert_eq!(pow(2, 0), 1);
        assert_eq!(pow(3, 1), 3);
        assert_eq!(pow(5, 6), (5 * 5 * 5) * (5 * 5 * 5));
        assert_eq!(pow(std::i64::MAX % P, std::i64::MAX), 856225998);
    }

    #[test]
    fn test_pow_small() {
        for x in 0..100_i64 {
            for n in 0..100_i64 {
                let actual = pow(x, n);
                let expected = (0..n).fold(1_i64, |acc, _| (acc * x) % P);
                assert_eq!(actual, expected, "{}^{}", x, n);
            }
        }
    }

    #[test]
    fn test_inv_dp() {
        let n = 10000;
        let dp = inv_dp(n);
        for i in 1..n {
            let mut z = dp[i] * i as i64;
            z %= P;
            z += P;
            z %= P;
            assert_eq!(z, 1);
        }
    }

    #[test]
    fn test_choose() {
        let table = vec![
            vec![1],
            vec![1, 1],
            vec![1, 2, 1],
            vec![1, 3, 3, 1],
            vec![1, 4, 6, 4, 1],
            vec![1, 5, 10, 10, 5, 1],
        ];

        let m = table.len();
        let choose_fn = ChooseFn::new(m + 1);
        for n in 0..m {
            for r in 0..n + 1 {
                assert_eq!(choose_fn.call(n, r), table[n][r]);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate std;

use resources::ResourcesLoader;
use serialize::json;
use std::ascii::StrAsciiExt;
use std::collections::{ HashSet, HashMap };
use super::EntitiesState;
use super::EntityID;
use super::ComponentID;

pub fn load(loader: &ResourcesLoader, resourceName: &str, output: &mut EntitiesState)
	-> Result<Vec<EntityID>, String>
{
	let mut docs = HashSet::new();
	load_impl(loader, resourceName, output, &mut docs)
}

fn load_impl(loader: &ResourcesLoader, resourceName: &str, output: &mut EntitiesState, loadedDocs: &mut HashSet<String>)
	-> Result<Vec<EntityID>, String>
{
	// checking that the doc has not already been loaded
	if loadedDocs.contains_equiv(&resourceName) {
		return Ok(vec!());
	}
	loadedDocs.insert(resourceName.to_string());

	// if not, loading the resource
	let mut resource = match loader.load(resourceName) {
		Ok(r) => std::io::BufferedReader::new(r),
		Err(err) => return Err(format!("{}", err))
	};

	// building the JSON object
	let data = match json::Builder::new(resource.chars().map(|c| c.unwrap())).build() {
		Ok(d) => d,
		Err(err) => return Err(format!("{}", err))
	};

	// loading the doc into the entities state
	load_all(output, resourceName, &data, loader, loadedDocs)
}

fn load_all(output: &mut EntitiesState, resourceName: &str, doc: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<Vec<EntityID>, String>
{
	match doc {
		&json::List(ref entities) => {
			let mut result = Vec::new();

			for elem in entities.iter() {
				match load_entity(output, resourceName, elem, loader, loadedDocs) {
					Ok(e) => result.push(e),
					Err(err) => {
						for e in result.iter() { output.destroy_entity(e); }
						return Err(err);
					}
				}
			}

			Ok(result)
		},
		_ => return Err(format!("Wrong format for entities document, expected list of entities but got: {}", doc))
	}
}

fn load_entity(output: &mut EntitiesState, resourceName: &str, entity: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<EntityID, String>
{
	match entity {
		&json::Object(ref entityData) => {
			let name = entityData
				.find(&"name".to_string())
				.and_then(|e| e.as_string())
				.map(|e| e.to_string())
				.map(|name| Path::new(resourceName).join(name).as_str().expect("non-utf8 entity name!").to_string());

			let visible = entityData.find(&"visible".to_string()).and_then(|e| e.as_boolean()).unwrap_or(true);
			let entityID = output.create_entity(name, visible);

			match entityData.find(&"components".to_string()) {
				Some(cmp) => {
					match load_components_list(output, &entityID, cmp, loader, loadedDocs) {
						Ok(_) => (),
						Err(err) => {
							output.destroy_entity(&entityID);
							return Err(err);
						}
					}
				},
				_ => ()
			};

			Ok(entityID)
		},
		_ => return Err(format!("Wrong format for entity, expected object but got: {}", entity))
	}
}

fn load_components_list(output: &mut EntitiesState, entity: &EntityID, componentsList: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<Vec<ComponentID>, String>
{
	match componentsList {
		&json::List(ref components) => {
			let mut result = Vec::new();

			for elem in components.iter() {
				match load_component(output, entity, elem, loader, loadedDocs) {
					Ok(e) => result.push(e),
					Err(err) => {
						for e in result.iter() { output.destroy_component(e); }
						return Err(err);
					}
				}
			}

			Ok(result)
		},
		_ => return Err(format!("Wrong format for components list, expected list but got: {}", componentsList))
	}
}

fn load_component(output: &mut EntitiesState, entity: &EntityID, component: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<ComponentID, String>
{
	match component {
		&json::Object(ref componentInfos) => {
			let cmptype = match componentInfos.find(&"type".to_string()) {
				Some(t) => t,
				None => return Err(format!("Component does not have a \"type\" field: {}", component))
			};

			let data = match componentInfos.find(&"data".to_string()) {
				Some(cmp) => { try!(load_component_data(output, cmp, loader, loadedDocs)) },
				_ => HashMap::new()
			};

			match cmptype {
				&json::String(ref t) => output.create_native_component(entity, t.as_slice(), data).map_err(|err| format!("{}", err)),
				&json::Object(_) => {
					match load_data_entry(output, cmptype, loader, loadedDocs) {
						Ok(super::Entity(id)) => output.create_component_from_entity(entity, &id, data).map_err(|err| format!("{}", err)),
						Ok(_) => return Err(format!("Wrong type for component \"type\" field object, expected entity")),
						Err(err) => return Err(err)
					}
				},
				_ => Err(format!("Wrong format for component \"type\" field, expected string or object"))
			}
		},
		_ => return Err(format!("Wrong format for component, expected object but got {}", component))
	}
}

fn load_component_data(output: &mut EntitiesState, componentData: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<HashMap<String, super::Data>, String>
{
	match componentData {
		&json::Object(ref data) => {
			let mut result = HashMap::new();

			for (key, val) in data.iter() {
				result.insert(key.clone(), try!(load_data_entry(output, val, loader, loadedDocs)));
			}

			Ok(result)
		},
		_ => return Err(format!("Wrong format for component data, expected object but got {}", componentData))
	}
}

fn load_data_entry(output: &mut EntitiesState, element: &json::Json, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<super::Data, String>
{
	Ok(match element {
		&json::String(ref data) => {
			super::String(data.clone())
		},
		&json::Number(ref data) => {
			super::Number(data.clone())
		},
		&json::Boolean(ref data) => {
			super::Boolean(data.clone())
		},
		&json::List(ref elems) => {
			let mut result = Vec::new();
			for elem in elems.iter() {
				let val = try!(load_data_entry(output, elem, loader, loadedDocs));
				result.push(val);
			}
			super::List(result)
		},
		&json::Object(ref data) => {
			let (key, val) = match data.iter().next() {
				None => return Err(format!("Empty object found for component data element")),
				Some(a) => a
			};

			if key.as_slice().eq_ignore_ascii_case("prototype") {
				let entityID = output.create_entity(None, false);

				match load_components_list(output, &entityID, val, loader, loadedDocs) {
					Ok(_) => (),
					Err(err) => {
						output.destroy_entity(&entityID);
						return Err(err);
					}
				}

				super::Entity(entityID)

			} else if key.as_slice().eq_ignore_ascii_case("entity") {
				let requestedName = match val.as_string() { Some(a) => a, None => return Err(format!("Component data element object of type Entity expects a string")) };
				super::Entity(try!(load_entity_from_name(output, requestedName, loader, loadedDocs)))

			} else if key.as_slice().eq_ignore_ascii_case("property") {
				let requestedProp = match val.as_string() { Some(a) => a, None => return Err(format!("Component data element object of type Property expects a string")) };
				super::FromProperty(requestedProp.to_string())

			} else {
				return Err(format!("Got invalid key for component data element object: {}", key));
			}
		},
		_ => return Err(format!("Wrong format for component data element, got {}", element))
	})
}

fn load_entity_from_name(output: &mut EntitiesState, entityName: &str, loader: &ResourcesLoader, loadedDocs: &mut HashSet<String>)
	-> Result<EntityID, String>
{
	let entityNameRefined = {
		let path = Path::new(entityName);
		path.join(path.filename().unwrap()).as_str().expect("non-utf8 entity name!").to_string()
	};

	// first, we check if there is an existing entity with this name
	{
		let entities = output.get_entities_by_name(entityName);
		if entities.len() >= 2 {
			return Err(format!("Found multiple entities with the same name: {}", entityName))
		}
		if entities.len() == 1 {
			return Ok(entities.get(0).clone())
		}
	}

	// first, we check if there is an existing entity with this name
	{
		let entities = output.get_entities_by_name(entityNameRefined.as_slice());
		if entities.len() >= 2 {
			return Err(format!("Found multiple entities with the same name: {}", entityNameRefined))
		}
		if entities.len() == 1 {
			return Ok(entities.get(0).clone())
		}
	}

	// trying to load the file with the same name as the entity
	{
		let mut nameAsPath = ::std::path::posix::Path::new(entityName);
		loop {
			match nameAsPath.as_str() {
				 Some(path) =>
					match load_impl(loader, path, output, loadedDocs) {
						Ok(l) => break,
						Err(e) => ()		// TODO: check for error type! If anything else than "resource doesn't exist", return
					},
				 None => ()
			};

			let newPath = nameAsPath.dir_path();
			if match newPath.as_str() { Some(s) => s == ".", None => false } || newPath == nameAsPath { break };
			nameAsPath = newPath;
		}
	}

	// first, we check if there is an existing entity with this name
	{
		let entities = output.get_entities_by_name(entityName);
		if entities.len() >= 2 {
			return Err(format!("Found multiple entities with the same name: {}", entityName))
		}
		if entities.len() == 1 {
			return Ok(entities.get(0).clone())
		}
	}

	// first, we check if there is an existing entity with this name
	{
		let entities = output.get_entities_by_name(entityNameRefined.as_slice());
		if entities.len() >= 2 {
			return Err(format!("Found multiple entities with the same name: {}", entityNameRefined))
		}
		if entities.len() == 1 {
			return Ok(entities.get(0).clone())
		}
	}

	Err(format!("Unable to load entity named \"{}\"", entityName))
}
<commit_msg>Cleanup loader<commit_after>use resources::ResourcesLoader;
use serialize::json;
use std::ascii::StrAsciiExt;
use std::collections::{ HashSet, HashMap };
use super::EntitiesState;
use super::EntityID;
use super::ComponentID;

/// Loads entities into an EntitiesState
pub fn load(loader: &ResourcesLoader, resourceName: &str, output: &mut EntitiesState)
    -> Result<Vec<EntityID>, LoaderError>
{
    let mut context = LoadContext {
        loader: loader,
        output: output,
        loadedDocs: HashSet::new(),
    };

    load_impl(&mut context, resourceName)
}

struct LoadContext<'a> {
    loader: &'a ResourcesLoader,
    output: &'a mut EntitiesState,
    loadedDocs: HashSet<String>,
}

enum LoaderError {
    IoError(::std::io::IoError),
    SyntaxError(::serialize::json::ParserError),
    StateError(super::StateError),
    WrongDataStructure(String),
}

impl ::std::fmt::Show for LoaderError {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::FormatError> {
        match self {
            &IoError(ref err) => err.fmt(formatter),
            &SyntaxError(ref err) => err.fmt(formatter),
            &StateError(ref err) => err.fmt(formatter),
            &WrongDataStructure(ref err) => format!("WrongDataStructure({})", err).fmt(formatter),
        }
    }
}

fn load_impl(context: &mut LoadContext, resourceName: &str)
    -> Result<Vec<EntityID>, LoaderError>
{
    // checking that the doc has not already been loaded
    if context.loadedDocs.contains_equiv(&resourceName) {
        return Ok(vec!());
    }
    context.loadedDocs.insert(resourceName.to_string());

    // if not, loading the resource
    let mut resource = match context.loader.load(resourceName) {
        Ok(r) => ::std::io::BufferedReader::new(r),
        Err(err) => return Err(IoError(err))
    };

    // building the JSON object
    let data = match json::Builder::new(resource.chars().map(|c| c.unwrap())).build() {
        Ok(d) => d,
        Err(err) => return Err(SyntaxError(err))
    };

    // loading the doc into the entities state
    load_all(context, resourceName, &data)
}

fn load_all(context: &mut LoadContext, resourceName: &str, doc: &json::Json)
    -> Result<Vec<EntityID>, LoaderError>
{
    match doc {
        &json::List(ref entities) => {
            let mut result = Vec::new();

            for elem in entities.iter() {
                match load_entity(context, resourceName, elem) {
                    Ok(e) => result.push(e),
                    Err(err) => {
                        for e in result.iter() { context.output.destroy_entity(e); }
                        return Err(err);
                    }
                }
            }

            Ok(result)
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for entities document, expected list of entities but got: {}", doc)))
    }
}

fn load_entity(context: &mut LoadContext, resourceName: &str, entity: &json::Json)
    -> Result<EntityID, LoaderError>
{
    match entity {
        &json::Object(ref entityData) => {
            let name = entityData
                .find(&"name".to_string())
                .and_then(|e| e.as_string())
                .map(|e| e.to_string())
                .map(|name| Path::new(resourceName).join(name).as_str().expect("non-utf8 entity name!").to_string());

            let visible = entityData.find(&"visible".to_string()).and_then(|e| e.as_boolean()).unwrap_or(true);
            let entityID = context.output.create_entity(name, visible);

            match entityData.find(&"components".to_string()) {
                Some(cmp) => {
                    match load_components_list(context, &entityID, cmp) {
                        Ok(_) => (),
                        Err(err) => {
                            context.output.destroy_entity(&entityID);
                            return Err(err);
                        }
                    }
                },
                _ => ()
            };

            Ok(entityID)
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for entity, expected object but got: {}", entity)))
    }
}

fn load_components_list(context: &mut LoadContext, entity: &EntityID, componentsList: &json::Json)
    -> Result<Vec<ComponentID>, LoaderError>
{
    match componentsList {
        &json::List(ref components) => {
            let mut result = Vec::new();

            for elem in components.iter() {
                match load_component(context, entity, elem) {
                    Ok(e) => result.push(e),
                    Err(err) => {
                        for e in result.iter() { context.output.destroy_component(e); }
                        return Err(err);
                    }
                }
            }

            Ok(result)
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for components list, expected list but got: {}", componentsList)))
    }
}

fn load_component(context: &mut LoadContext, entity: &EntityID, component: &json::Json)
    -> Result<ComponentID, LoaderError>
{
    match component {
        &json::Object(ref componentInfos) => {
            let cmptype = match componentInfos.find(&"type".to_string()) {
                Some(t) => t,
                None => return Err(WrongDataStructure(format!("Component does not have a \"type\" field: {}", component)))
            };

            let data = match componentInfos.find(&"data".to_string()) {
                Some(cmp) => { try!(load_component_data(context, cmp)) },
                _ => HashMap::new()
            };

            match cmptype {
                &json::String(ref t) => context.output.create_native_component(entity, t.as_slice(), data).map_err(|err| StateError(err)),
                &json::Object(_) => {
                    match load_data_entry(context, cmptype) {
                        Ok(super::Entity(id)) => context.output.create_component_from_entity(entity, &id, data).map_err(|err| StateError(err)),
                        Ok(_) => return Err(WrongDataStructure(format!("Wrong type for component \"type\" field object, expected entity"))),
                        Err(err) => return Err(err)
                    }
                },
                _ => Err(WrongDataStructure(format!("Wrong format for component \"type\" field, expected string or object")))
            }
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for component, expected object but got {}", component)))
    }
}

fn load_component_data(context: &mut LoadContext, componentData: &json::Json)
    -> Result<HashMap<String, super::Data>, LoaderError>
{
    match componentData {
        &json::Object(ref data) => {
            let mut result = HashMap::new();

            for (key, val) in data.iter() {
                result.insert(key.clone(), try!(load_data_entry(context, val)));
            }

            Ok(result)
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for component data, expected object but got {}", componentData)))
    }
}

fn load_data_entry(context: &mut LoadContext, element: &json::Json)
    -> Result<super::Data, LoaderError>
{
    Ok(match element {
        &json::String(ref data) => {
            super::String(data.clone())
        },
        &json::Number(ref data) => {
            super::Number(data.clone())
        },
        &json::Boolean(ref data) => {
            super::Boolean(data.clone())
        },
        &json::List(ref elems) => {
            let mut result = Vec::new();
            for elem in elems.iter() {
                let val = try!(load_data_entry(context, elem));
                result.push(val);
            }
            super::List(result)
        },
        &json::Object(ref data) => {
            let (key, val) = match data.iter().next() {
                None => return Err(WrongDataStructure(format!("Empty object found for component data element"))),
                Some(a) => a
            };

            if key.as_slice().eq_ignore_ascii_case("prototype") {
                let entityID = context.output.create_entity(None, false);

                match load_components_list(context, &entityID, val) {
                    Ok(_) => (),
                    Err(err) => {
                        context.output.destroy_entity(&entityID);
                        return Err(err);
                    }
                }

                super::Entity(entityID)

            } else if key.as_slice().eq_ignore_ascii_case("entity") {
                let requestedName = match val.as_string() { Some(a) => a, None => return Err(WrongDataStructure(format!("Component data element object of type Entity expects a string"))) };
                super::Entity(try!(load_entity_from_name(context, requestedName)))

            } else if key.as_slice().eq_ignore_ascii_case("property") {
                let requestedProp = match val.as_string() { Some(a) => a, None => return Err(WrongDataStructure(format!("Component data element object of type Property expects a string"))) };
                super::FromProperty(requestedProp.to_string())

            } else {
                return Err(WrongDataStructure(format!("Got invalid key for component data element object: {}", key)));
            }
        },
        _ => return Err(WrongDataStructure(format!("Wrong format for component data element, got {}", element)))
    })
}

fn load_entity_from_name(context: &mut LoadContext, entityName: &str)
    -> Result<EntityID, LoaderError>
{
    let entityNameRefined = {
        let path = Path::new(entityName);
        path.join(path.filename().unwrap()).as_str().expect("non-utf8 entity name!").to_string()
    };

    // first, we check if there is an existing entity with this name
    {
        let entities = context.output.get_entities_by_name(entityName);
        if entities.len() >= 2 {
            return Err(WrongDataStructure(format!("Found multiple entities with the same name: {}", entityName)))
        }
        if entities.len() == 1 {
            return Ok(entities.get(0).clone())
        }
    }

    // first, we check if there is an existing entity with this name
    {
        let entities = context.output.get_entities_by_name(entityNameRefined.as_slice());
        if entities.len() >= 2 {
            return Err(WrongDataStructure(format!("Found multiple entities with the same name: {}", entityNameRefined)))
        }
        if entities.len() == 1 {
            return Ok(entities.get(0).clone())
        }
    }

    // trying to load the file with the same name as the entity
    {
        let mut nameAsPath = ::std::path::posix::Path::new(entityName);
        loop {
            match nameAsPath.as_str() {
                 Some(path) =>
                    match load_impl(context, path) {
                        Ok(l) => break,
                        Err(IoError(_)) => (),
                        Err(err) => return Err(err)
                    },
                 None => ()
            };

            let newPath = nameAsPath.dir_path();
            if match newPath.as_str() { Some(s) => s == ".", None => false } || newPath == nameAsPath { break };
            nameAsPath = newPath;
        }
    }

    // first, we check if there is an existing entity with this name
    {
        let entities = context.output.get_entities_by_name(entityName);
        if entities.len() >= 2 {
            return Err(WrongDataStructure(format!("Found multiple entities with the same name: {}", entityName)))
        }
        if entities.len() == 1 {
            return Ok(entities.get(0).clone())
        }
    }

    // first, we check if there is an existing entity with this name
    {
        let entities = context.output.get_entities_by_name(entityNameRefined.as_slice());
        if entities.len() >= 2 {
            return Err(WrongDataStructure(format!("Found multiple entities with the same name: {}", entityNameRefined)))
        }
        if entities.len() == 1 {
            return Ok(entities.get(0).clone())
        }
    }

    Err(WrongDataStructure(format!("Unable to load entity named \"{}\"", entityName)))
}
<|endoftext|>


<commit_before>use super::{LuaValue, Result, eval_expr, boolean_coercion, num_coercion};
use nom_lua53::op::UnOp;
use nom_lua53::Exp;

use LuaError::*;

pub fn eval_unary_expr(operand: &Box<Exp>, operator: &UnOp) -> Result<LuaValue> {
    let operand = eval_expr(&operand)?;
    match *operator {
        UnOp::BoolNot => Ok(LuaValue::Boolean(!boolean_coercion(&operand))),
        UnOp::Minus => {
            match num_coercion(operand) {
                LuaValue::Integer(i) => Ok(LuaValue::Integer(-i)),
                LuaValue::Float(f) => Ok(LuaValue::Float(-f)),
                _ => Err(TypeError("Trying to do arithmetic on a non-numerical value.".to_owned()))
            }
        }
        _ => Ok(LuaValue::Nil)
    }
}

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

    use nom_lua53::Exp;
    use nom_lua53::string::StringLit;
    use nom_lua53::num::Numeral;
    use nom_lua53::op::UnOp;

    use std::borrow::Cow;

    #[test]
    fn test_math_negation() {
        // 1. + -1. == 0.
        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Float(-1.));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(0))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Integer(0));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(-4))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Integer(4));

        let res = eval_unary_expr(&Box::new(Exp::Str(StringLit(Cow::from(&b"5.5"[..])))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Float(-5.5));

        let res = eval_unary_expr(&Box::new(Exp::Bool(true)), &UnOp::Minus).unwrap_err();
        assert!(match res { TypeError(_) => true, _ => false });
    }

    #[test]
    fn test_bool_negation() {
        // 1. + -1. == 0.
        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(0))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Str(StringLit(Cow::from(&b""[..])))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Nil), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(true));
    }
}

<commit_msg>Implement the length operator for the string types<commit_after>use super::{LuaValue, Result, eval_expr, boolean_coercion, num_coercion};
use nom_lua53::op::UnOp;
use nom_lua53::Exp;

use LuaError::*;

pub fn eval_unary_expr(operand: &Box<Exp>, operator: &UnOp) -> Result<LuaValue> {
    let operand = eval_expr(&operand)?;
    match *operator {
        UnOp::BoolNot => Ok(LuaValue::Boolean(!boolean_coercion(&operand))),
        UnOp::Minus => {
            match num_coercion(operand) {
                LuaValue::Integer(i) => Ok(LuaValue::Integer(-i)),
                LuaValue::Float(f) => Ok(LuaValue::Float(-f)),
                _ => Err(TypeError("Trying to do arithmetic on a non-numerical value.".to_owned()))
            }
        },
        UnOp::Length => {
            match operand {
                LuaValue::Str(s) => Ok(LuaValue::Integer(s.len() as isize)),
                _ => Err(TypeError("Trying to do get size on an unsupported type.".to_owned()))
            }
        }
        _ => Ok(LuaValue::Nil)
    }
}

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

    use nom_lua53::Exp;
    use nom_lua53::string::StringLit;
    use nom_lua53::num::Numeral;
    use nom_lua53::op::UnOp;

    use std::borrow::Cow;

    #[test]
    fn test_math_negation() {
        // 1. + -1. == 0.
        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Float(-1.));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(0))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Integer(0));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(-4))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Integer(4));

        let res = eval_unary_expr(&Box::new(Exp::Str(StringLit(Cow::from(&b"5.5"[..])))), &UnOp::Minus).unwrap();
        assert_eq!(res, LuaValue::Float(-5.5));

        let res = eval_unary_expr(&Box::new(Exp::Bool(true)), &UnOp::Minus).unwrap_err();
        assert!(match res { TypeError(_) => true, _ => false });
    }

    #[test]
    fn test_bool_negation() {
        // 1. + -1. == 0.
        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Float(1.0))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Num(Numeral::Int(0))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Str(StringLit(Cow::from(&b""[..])))), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(false));

        let res = eval_unary_expr(&Box::new(Exp::Nil), &UnOp::BoolNot).unwrap();
        assert_eq!(res, LuaValue::Boolean(true));
    }

    #[test]
    fn test_bool_length() {
        let res = eval_unary_expr(&Box::new(Exp::Str(StringLit(Cow::from(&b"1234"[..])))), &UnOp::Length).unwrap();
        assert_eq!(res, LuaValue::Integer(4));

        let res = eval_unary_expr(&Box::new(Exp::Bool(true)), &UnOp::Length).unwrap_err();
        assert!(match res { TypeError(_) => true, _ => false });
    }
}

<|endoftext|>


<commit_before>//! Describes items defined or visible (ie, imported) in a certain scope.
//! This is shared between modules and blocks.

use hir_expand::name::Name;
use once_cell::sync::Lazy;
use ra_db::CrateId;
use rustc_hash::{FxHashMap, FxHashSet};
use test_utils::mark;

use crate::{
    db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
    LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
};
use std::collections::hash_map::Entry;

#[derive(Copy, Clone)]
pub(crate) enum ImportType {
    Glob,
    Named,
}

#[derive(Debug, Default)]
pub struct PerNsGlobImports {
    types: FxHashSet<(LocalModuleId, Name)>,
    values: FxHashSet<(LocalModuleId, Name)>,
    macros: FxHashSet<(LocalModuleId, Name)>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ItemScope {
    types: FxHashMap<Name, (ModuleDefId, Visibility)>,
    values: FxHashMap<Name, (ModuleDefId, Visibility)>,
    macros: FxHashMap<Name, (MacroDefId, Visibility)>,
    unresolved: FxHashSet<Name>,

    defs: Vec<ModuleDefId>,
    impls: Vec<ImplId>,
    /// Macros visible in current module in legacy textual scope
    ///
    /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public)))
        .collect()
});

/// Shadow mode for builtin type which can be shadowed by module.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum BuiltinShadowMode {
    /// Prefer user-defined modules (or other types) over builtins.
    Module,
    /// Prefer builtins over user-defined modules (but not other types).
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ItemScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
        // FIXME: shadowing
        let keys: FxHashSet<_> = self
            .types
            .keys()
            .chain(self.values.keys())
            .chain(self.macros.keys())
            .chain(self.unresolved.iter())
            .collect();

        keys.into_iter().map(move |name| (name, self.get(name)))
    }

    pub fn entries_without_primitives<'a>(
        &'a self,
    ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
        self.entries()
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.defs.iter().copied()
    }

    pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
        self.impls.iter().copied()
    }

    pub fn visibility_of(&self, def: ModuleDefId) -> Option<Visibility> {
        self.name_of(ItemInNs::Types(def))
            .or_else(|| self.name_of(ItemInNs::Values(def)))
            .map(|(_, v)| v)
    }

    /// Iterate over all module scoped macros
    pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visible at the end of the module
    pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub(crate) fn get(&self, name: &Name) -> PerNs {
        PerNs {
            types: self.types.get(name).copied(),
            values: self.values.get(name).copied(),
            macros: self.macros.get(name).copied(),
        }
    }

    pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
        for (name, per_ns) in self.entries() {
            if let Some(vis) = item.match_with(per_ns) {
                return Some((name, vis));
            }
        }
        None
    }

    pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.types.values().filter_map(|(def, _)| match def {
            ModuleDefId::TraitId(t) => Some(*t),
            _ => None,
        })
    }

    pub(crate) fn define_def(&mut self, def: ModuleDefId) {
        self.defs.push(def)
    }

    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }

    pub(crate) fn define_impl(&mut self, imp: ImplId) {
        self.impls.push(imp)
    }

    pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
        self.legacy_macros.insert(name, mac);
    }

    pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
        let mut changed = false;

        if let Some(types) = def.types {
            match self.types.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(types);
                    changed = true;
                }
            }
        }
        if let Some(values) = def.values {
            match self.values.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(values);
                    changed = true;
                }
            }
        }
        if let Some(macros) = def.macros {
            match self.macros.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(macros);
                    changed = true;
                }
            }
        }

        if def.is_none() {
            if self.unresolved.insert(name) {
                changed = true;
            }
        }

        changed
    }

    pub(crate) fn push_res_with_import(
        &mut self,
        glob_imports: &mut PerNsGlobImports,
        lookup: (LocalModuleId, Name),
        def: PerNs,
        def_import_type: ImportType,
    ) -> bool {
        let mut changed = false;

        macro_rules! check_changed {
            (
                $changed:ident,
                ( $this:ident / $def:ident ) . $field:ident,
                $glob_imports:ident [ $lookup:ident ],
                $def_import_type:ident
            ) => {{
                let existing = $this.$field.entry($lookup.1.clone());
                match (existing, $def.$field) {
                    (Entry::Vacant(entry), Some(_)) => {
                        match $def_import_type {
                            ImportType::Glob => {
                                $glob_imports.$field.insert($lookup.clone());
                            }
                            ImportType::Named => {
                                $glob_imports.$field.remove(&$lookup);
                            }
                        }

                        if let Some(fld) = $def.$field {
                            entry.insert(fld);
                        }
                        $changed = true;
                    }
                    (Entry::Occupied(mut entry), Some(_))
                        if $glob_imports.$field.contains(&$lookup)
                            && matches!($def_import_type, ImportType::Named) =>
                    {
                        mark::hit!(import_shadowed);
                        $glob_imports.$field.remove(&$lookup);
                        if let Some(fld) = $def.$field {
                            entry.insert(fld);
                        }
                        $changed = true;
                    }
                    _ => {}
                }
            }};
        }

        check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
        check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
        check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);

        if def.is_none() {
            if self.unresolved.insert(lookup.1) {
                changed = true;
            }
        }

        changed
    }

    pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a {
        self.entries().map(|(name, res)| (name.clone(), res))
    }

    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
        self.legacy_macros.clone()
    }
}

impl PerNs {
    pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
        match def {
            ModuleDefId::ModuleId(_) => PerNs::types(def, v),
            ModuleDefId::FunctionId(_) => PerNs::values(def, v),
            ModuleDefId::AdtId(adt) => match adt {
                AdtId::UnionId(_) => PerNs::types(def, v),
                AdtId::EnumId(_) => PerNs::types(def, v),
                AdtId::StructId(_) => {
                    if has_constructor {
                        PerNs::both(def, def, v)
                    } else {
                        PerNs::types(def, v)
                    }
                }
            },
            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
            ModuleDefId::TraitId(_) => PerNs::types(def, v),
            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
            ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum ItemInNs {
    Types(ModuleDefId),
    Values(ModuleDefId),
    Macros(MacroDefId),
}

impl ItemInNs {
    fn match_with(self, per_ns: PerNs) -> Option<Visibility> {
        match self {
            ItemInNs::Types(def) => {
                per_ns.types.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
            ItemInNs::Values(def) => {
                per_ns.values.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
            ItemInNs::Macros(def) => {
                per_ns.macros.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
        }
    }

    pub fn as_module_def_id(self) -> Option<ModuleDefId> {
        match self {
            ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
            ItemInNs::Macros(_) => None,
        }
    }

    /// Returns the crate defining this item (or `None` if `self` is built-in).
    pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
        Some(match self {
            ItemInNs::Types(did) | ItemInNs::Values(did) => match did {
                ModuleDefId::ModuleId(id) => id.krate,
                ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate,
                ModuleDefId::AdtId(id) => id.module(db).krate,
                ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate,
                ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
                ModuleDefId::BuiltinType(_) => return None,
            },
            ItemInNs::Macros(id) => return id.krate,
        })
    }
}
<commit_msg>Reorder imports<commit_after>//! Describes items defined or visible (ie, imported) in a certain scope.
//! This is shared between modules and blocks.

use std::collections::hash_map::Entry;

use hir_expand::name::Name;
use once_cell::sync::Lazy;
use ra_db::CrateId;
use rustc_hash::{FxHashMap, FxHashSet};
use test_utils::mark;

use crate::{
    db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
    LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
};

#[derive(Copy, Clone)]
pub(crate) enum ImportType {
    Glob,
    Named,
}

#[derive(Debug, Default)]
pub struct PerNsGlobImports {
    types: FxHashSet<(LocalModuleId, Name)>,
    values: FxHashSet<(LocalModuleId, Name)>,
    macros: FxHashSet<(LocalModuleId, Name)>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ItemScope {
    types: FxHashMap<Name, (ModuleDefId, Visibility)>,
    values: FxHashMap<Name, (ModuleDefId, Visibility)>,
    macros: FxHashMap<Name, (MacroDefId, Visibility)>,
    unresolved: FxHashSet<Name>,

    defs: Vec<ModuleDefId>,
    impls: Vec<ImplId>,
    /// Macros visible in current module in legacy textual scope
    ///
    /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into(), Visibility::Public)))
        .collect()
});

/// Shadow mode for builtin type which can be shadowed by module.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum BuiltinShadowMode {
    /// Prefer user-defined modules (or other types) over builtins.
    Module,
    /// Prefer builtins over user-defined modules (but not other types).
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ItemScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
        // FIXME: shadowing
        let keys: FxHashSet<_> = self
            .types
            .keys()
            .chain(self.values.keys())
            .chain(self.macros.keys())
            .chain(self.unresolved.iter())
            .collect();

        keys.into_iter().map(move |name| (name, self.get(name)))
    }

    pub fn entries_without_primitives<'a>(
        &'a self,
    ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
        self.entries()
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.defs.iter().copied()
    }

    pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
        self.impls.iter().copied()
    }

    pub fn visibility_of(&self, def: ModuleDefId) -> Option<Visibility> {
        self.name_of(ItemInNs::Types(def))
            .or_else(|| self.name_of(ItemInNs::Values(def)))
            .map(|(_, v)| v)
    }

    /// Iterate over all module scoped macros
    pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visible at the end of the module
    pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub(crate) fn get(&self, name: &Name) -> PerNs {
        PerNs {
            types: self.types.get(name).copied(),
            values: self.values.get(name).copied(),
            macros: self.macros.get(name).copied(),
        }
    }

    pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
        for (name, per_ns) in self.entries() {
            if let Some(vis) = item.match_with(per_ns) {
                return Some((name, vis));
            }
        }
        None
    }

    pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.types.values().filter_map(|(def, _)| match def {
            ModuleDefId::TraitId(t) => Some(*t),
            _ => None,
        })
    }

    pub(crate) fn define_def(&mut self, def: ModuleDefId) {
        self.defs.push(def)
    }

    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }

    pub(crate) fn define_impl(&mut self, imp: ImplId) {
        self.impls.push(imp)
    }

    pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
        self.legacy_macros.insert(name, mac);
    }

    pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
        let mut changed = false;

        if let Some(types) = def.types {
            match self.types.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(types);
                    changed = true;
                }
            }
        }
        if let Some(values) = def.values {
            match self.values.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(values);
                    changed = true;
                }
            }
        }
        if let Some(macros) = def.macros {
            match self.macros.entry(name.clone()) {
                Entry::Occupied(_) => {}
                Entry::Vacant(e) => {
                    e.insert(macros);
                    changed = true;
                }
            }
        }

        if def.is_none() {
            if self.unresolved.insert(name) {
                changed = true;
            }
        }

        changed
    }

    pub(crate) fn push_res_with_import(
        &mut self,
        glob_imports: &mut PerNsGlobImports,
        lookup: (LocalModuleId, Name),
        def: PerNs,
        def_import_type: ImportType,
    ) -> bool {
        let mut changed = false;

        macro_rules! check_changed {
            (
                $changed:ident,
                ( $this:ident / $def:ident ) . $field:ident,
                $glob_imports:ident [ $lookup:ident ],
                $def_import_type:ident
            ) => {{
                let existing = $this.$field.entry($lookup.1.clone());
                match (existing, $def.$field) {
                    (Entry::Vacant(entry), Some(_)) => {
                        match $def_import_type {
                            ImportType::Glob => {
                                $glob_imports.$field.insert($lookup.clone());
                            }
                            ImportType::Named => {
                                $glob_imports.$field.remove(&$lookup);
                            }
                        }

                        if let Some(fld) = $def.$field {
                            entry.insert(fld);
                        }
                        $changed = true;
                    }
                    (Entry::Occupied(mut entry), Some(_))
                        if $glob_imports.$field.contains(&$lookup)
                            && matches!($def_import_type, ImportType::Named) =>
                    {
                        mark::hit!(import_shadowed);
                        $glob_imports.$field.remove(&$lookup);
                        if let Some(fld) = $def.$field {
                            entry.insert(fld);
                        }
                        $changed = true;
                    }
                    _ => {}
                }
            }};
        }

        check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
        check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
        check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);

        if def.is_none() {
            if self.unresolved.insert(lookup.1) {
                changed = true;
            }
        }

        changed
    }

    pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a {
        self.entries().map(|(name, res)| (name.clone(), res))
    }

    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
        self.legacy_macros.clone()
    }
}

impl PerNs {
    pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
        match def {
            ModuleDefId::ModuleId(_) => PerNs::types(def, v),
            ModuleDefId::FunctionId(_) => PerNs::values(def, v),
            ModuleDefId::AdtId(adt) => match adt {
                AdtId::UnionId(_) => PerNs::types(def, v),
                AdtId::EnumId(_) => PerNs::types(def, v),
                AdtId::StructId(_) => {
                    if has_constructor {
                        PerNs::both(def, def, v)
                    } else {
                        PerNs::types(def, v)
                    }
                }
            },
            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
            ModuleDefId::TraitId(_) => PerNs::types(def, v),
            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
            ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum ItemInNs {
    Types(ModuleDefId),
    Values(ModuleDefId),
    Macros(MacroDefId),
}

impl ItemInNs {
    fn match_with(self, per_ns: PerNs) -> Option<Visibility> {
        match self {
            ItemInNs::Types(def) => {
                per_ns.types.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
            ItemInNs::Values(def) => {
                per_ns.values.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
            ItemInNs::Macros(def) => {
                per_ns.macros.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
            }
        }
    }

    pub fn as_module_def_id(self) -> Option<ModuleDefId> {
        match self {
            ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
            ItemInNs::Macros(_) => None,
        }
    }

    /// Returns the crate defining this item (or `None` if `self` is built-in).
    pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
        Some(match self {
            ItemInNs::Types(did) | ItemInNs::Values(did) => match did {
                ModuleDefId::ModuleId(id) => id.krate,
                ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate,
                ModuleDefId::AdtId(id) => id.module(db).krate,
                ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate,
                ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate,
                ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
                ModuleDefId::BuiltinType(_) => return None,
            },
            ItemInNs::Macros(id) => return id.krate,
        })
    }
}
<|endoftext|>


<commit_before>//! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`).

use std::sync::Arc;

use hir_expand::{hygiene::Hygiene, InFile};
use ra_syntax::ast;

use crate::{
    db::DefDatabase,
    path::{ModPath, PathKind},
    ModuleId,
};

/// Visibility of an item, not yet resolved.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RawVisibility {
    // FIXME: We could avoid the allocation in many cases by special-casing
    // pub(crate), pub(super) and private. Alternatively, `ModPath` could be
    // made to contain an Arc<[Segment]> instead of a Vec?
    /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
    /// equivalent to `pub(self)`.
    Module(Arc<ModPath>),
    /// `pub`.
    Public,
}

impl RawVisibility {
    fn private() -> RawVisibility {
        let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() };
        RawVisibility::Module(Arc::new(path))
    }

    pub(crate) fn from_ast(
        db: &impl DefDatabase,
        node: InFile<Option<ast::Visibility>>,
    ) -> RawVisibility {
        Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id))
    }

    pub(crate) fn from_ast_with_hygiene(
        node: Option<ast::Visibility>,
        hygiene: &Hygiene,
    ) -> RawVisibility {
        let node = match node {
            None => return RawVisibility::private(),
            Some(node) => node,
        };
        match node.kind() {
            ast::VisibilityKind::In(path) => {
                let path = ModPath::from_src(path, hygiene);
                let path = match path {
                    None => return RawVisibility::private(),
                    Some(path) => path,
                };
                RawVisibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubCrate => {
                let path = ModPath { kind: PathKind::Crate, segments: Vec::new() };
                RawVisibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubSuper => {
                let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
                RawVisibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::Pub => RawVisibility::Public,
        }
    }

    pub fn resolve(
        &self,
        db: &impl DefDatabase,
        resolver: &crate::resolver::Resolver,
    ) -> Visibility {
        // we fall back to public visibility (i.e. fail open) if the path can't be resolved
        resolver.resolve_visibility(db, self).unwrap_or(Visibility::Public)
    }
}

/// Visibility of an item, with the path resolved.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Visibility {
    /// Visibility is restricted to a certain module.
    Module(ModuleId),
    /// Visibility is unrestricted.
    Public,
}

impl Visibility {
    pub fn visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool {
        let to_module = match self {
            Visibility::Module(m) => m,
            Visibility::Public => return true,
        };
        // if they're not in the same crate, it can't be visible
        if from_module.krate != to_module.krate {
            return false;
        }
        let def_map = db.crate_def_map(from_module.krate);
        self.visible_from_def_map(&def_map, from_module.local_id)
    }

    pub(crate) fn visible_from_other_crate(self) -> bool {
        match self {
            Visibility::Module(_) => false,
            Visibility::Public => true,
        }
    }

    pub(crate) fn visible_from_def_map(
        self,
        def_map: &crate::nameres::CrateDefMap,
        from_module: crate::LocalModuleId,
    ) -> bool {
        let to_module = match self {
            Visibility::Module(m) => m,
            Visibility::Public => return true,
        };
        // from_module needs to be a descendant of to_module
        let mut ancestors = std::iter::successors(Some(from_module), |m| {
            let parent_id = def_map[*m].parent?;
            Some(parent_id)
        });
        ancestors.any(|m| m == to_module.local_id)
    }
}
<commit_msg>Remove Arc from RawVisibility<commit_after>//! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`).

use hir_expand::{hygiene::Hygiene, InFile};
use ra_syntax::ast;

use crate::{
    db::DefDatabase,
    path::{ModPath, PathKind},
    ModuleId,
};

/// Visibility of an item, not yet resolved.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RawVisibility {
    /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
    /// equivalent to `pub(self)`.
    Module(ModPath),
    /// `pub`.
    Public,
}

impl RawVisibility {
    const fn private() -> RawVisibility {
        let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() };
        RawVisibility::Module(path)
    }

    pub(crate) fn from_ast(
        db: &impl DefDatabase,
        node: InFile<Option<ast::Visibility>>,
    ) -> RawVisibility {
        Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id))
    }

    pub(crate) fn from_ast_with_hygiene(
        node: Option<ast::Visibility>,
        hygiene: &Hygiene,
    ) -> RawVisibility {
        let node = match node {
            None => return RawVisibility::private(),
            Some(node) => node,
        };
        match node.kind() {
            ast::VisibilityKind::In(path) => {
                let path = ModPath::from_src(path, hygiene);
                let path = match path {
                    None => return RawVisibility::private(),
                    Some(path) => path,
                };
                RawVisibility::Module(path)
            }
            ast::VisibilityKind::PubCrate => {
                let path = ModPath { kind: PathKind::Crate, segments: Vec::new() };
                RawVisibility::Module(path)
            }
            ast::VisibilityKind::PubSuper => {
                let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
                RawVisibility::Module(path)
            }
            ast::VisibilityKind::Pub => RawVisibility::Public,
        }
    }

    pub fn resolve(
        &self,
        db: &impl DefDatabase,
        resolver: &crate::resolver::Resolver,
    ) -> Visibility {
        // we fall back to public visibility (i.e. fail open) if the path can't be resolved
        resolver.resolve_visibility(db, self).unwrap_or(Visibility::Public)
    }
}

/// Visibility of an item, with the path resolved.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Visibility {
    /// Visibility is restricted to a certain module.
    Module(ModuleId),
    /// Visibility is unrestricted.
    Public,
}

impl Visibility {
    pub fn visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool {
        let to_module = match self {
            Visibility::Module(m) => m,
            Visibility::Public => return true,
        };
        // if they're not in the same crate, it can't be visible
        if from_module.krate != to_module.krate {
            return false;
        }
        let def_map = db.crate_def_map(from_module.krate);
        self.visible_from_def_map(&def_map, from_module.local_id)
    }

    pub(crate) fn visible_from_other_crate(self) -> bool {
        match self {
            Visibility::Module(_) => false,
            Visibility::Public => true,
        }
    }

    pub(crate) fn visible_from_def_map(
        self,
        def_map: &crate::nameres::CrateDefMap,
        from_module: crate::LocalModuleId,
    ) -> bool {
        let to_module = match self {
            Visibility::Module(m) => m,
            Visibility::Public => return true,
        };
        // from_module needs to be a descendant of to_module
        let mut ancestors = std::iter::successors(Some(from_module), |m| {
            let parent_id = def_map[*m].parent?;
            Some(parent_id)
        });
        ancestors.any(|m| m == to_module.local_id)
    }
}
<|endoftext|>


<commit_before>//! Verification of MIPS MSA intrinsics
#![feature(try_trait)]
#![allow(bad_style, unused)]

// This file is obtained from
// https://gcc.gnu.org/onlinedocs//gcc/MIPS-SIMD-Architecture-Built-in-Functions.html
static HEADER: &str = include_str!("../mips-msa.h");

stdsimd_verify::mips_functions!(static FUNCTIONS);

struct Function {
    name: &'static str,
    arguments: &'static [&'static Type],
    ret: Option<&'static Type>,
    target_feature: Option<&'static str>,
    instrs: &'static [&'static str],
    file: &'static str,
    required_const: &'static [usize],
}

static F16: Type = Type::PrimFloat(16);
static F32: Type = Type::PrimFloat(32);
static F64: Type = Type::PrimFloat(64);
static I8: Type = Type::PrimSigned(8);
static I16: Type = Type::PrimSigned(16);
static I32: Type = Type::PrimSigned(32);
static I64: Type = Type::PrimSigned(64);
static U8: Type = Type::PrimUnsigned(8);
static U16: Type = Type::PrimUnsigned(16);
static U32: Type = Type::PrimUnsigned(32);
static U64: Type = Type::PrimUnsigned(64);
static NEVER: Type = Type::Never;
static TUPLE: Type = Type::Tuple;
static v16i8: Type = Type::I(8, 16, 1);
static v8i16: Type = Type::I(16, 8, 1);
static v4i32: Type = Type::I(32, 4, 1);
static v2i64: Type = Type::I(64, 2, 1);
static v16u8: Type = Type::U(8, 16, 1);
static v8u16: Type = Type::U(16, 8, 1);
static v4u32: Type = Type::U(32, 4, 1);
static v2u64: Type = Type::U(64, 2, 1);
static v8f16: Type = Type::F(16, 8, 1);
static v4f32: Type = Type::F(32, 4, 1);
static v2f64: Type = Type::F(64, 2, 1);

#[derive(Debug, Copy, Clone, PartialEq)]
enum Type {
    PrimFloat(u8),
    PrimSigned(u8),
    PrimUnsigned(u8),
    PrimPoly(u8),
    MutPtr(&'static Type),
    ConstPtr(&'static Type),
    Ptr(&'static Type),
    Tuple,
    I(u8, u8, u8),
    U(u8, u8, u8),
    P(u8, u8, u8),
    F(u8, u8, u8),
    Never,
}

#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
enum MsaTy {
    v16i8,
    v8i16,
    v4i32,
    v2i64,
    v16u8,
    v8u16,
    v4u32,
    v2u64,
    v8f16,
    v4f32,
    v2f64,
    imm0_1,
    imm0_3,
    imm0_7,
    imm0_15,
    imm0_31,
    imm0_63,
    imm0_255,
    imm_n16_15,
    imm_n512_511,
    imm_n1024_1022,
    imm_n2048_2044,
    imm_n4096_4088,
    i32,
    u32,
    i64,
    u64,
    Void,
    VoidPtr,
}

impl<'a> From<&'a str> for MsaTy {
    fn from(s: &'a str) -> MsaTy {
        match s {
            "v16i8" => MsaTy::v16i8,
            "v8i16" => MsaTy::v8i16,
            "v4i32" => MsaTy::v4i32,
            "v2i64" => MsaTy::v2i64,
            "v16u8" => MsaTy::v16u8,
            "v8u16" => MsaTy::v8u16,
            "v4u32" => MsaTy::v4u32,
            "v2u64" => MsaTy::v2u64,
            "v8f16" => MsaTy::v8f16,
            "v4f32" => MsaTy::v4f32,
            "v2f64" => MsaTy::v2f64,
            "imm0_1" => MsaTy::imm0_1,
            "imm0_3" => MsaTy::imm0_3,
            "imm0_7" => MsaTy::imm0_7,
            "imm0_15" => MsaTy::imm0_15,
            "imm0_31" => MsaTy::imm0_31,
            "imm0_63" => MsaTy::imm0_63,
            "imm0_255" => MsaTy::imm0_255,
            "imm_n16_15" => MsaTy::imm_n16_15,
            "imm_n512_511" => MsaTy::imm_n512_511,
            "imm_n1024_1022" => MsaTy::imm_n1024_1022,
            "imm_n2048_2044" => MsaTy::imm_n2048_2044,
            "imm_n4096_4088" => MsaTy::imm_n4096_4088,
            "i32" => MsaTy::i32,
            "u32" => MsaTy::u32,
            "i64" => MsaTy::i64,
            "u64" => MsaTy::u64,
            "void" => MsaTy::Void,
            "void *" => MsaTy::VoidPtr,
            v => panic!("unknown ty: \"{}\"", v),
        }
    }
}

#[derive(Debug, Clone)]
struct MsaIntrinsic {
    id: String,
    arg_tys: Vec<MsaTy>,
    ret_ty: MsaTy,
    instruction: String,
}

impl std::convert::TryFrom<&'static str> for MsaIntrinsic {
    // The intrinsics are just C function declarations of the form:
    // $ret_ty __builtin_${fn_id}($($arg_ty),*);
    type Error = std::option::NoneError;
    fn try_from(line: &'static str) -> Result<Self, Self::Error> {
        let first_whitespace = line.find(char::is_whitespace)?;
        let ret_ty = &line[0..first_whitespace];
        let ret_ty = MsaTy::from(ret_ty);

        let first_parentheses = line.find('(')?;
        assert!(first_parentheses > first_whitespace);
        let id = &line[first_whitespace+1..first_parentheses].trim();
        assert!(id.starts_with("__builtin"));
        let mut id_str = "_".to_string();
        id_str += &id[9..];
        let id = id_str;

        let mut arg_tys = Vec::new();

        let last_parentheses = line.find(')')?;
        for arg in (&line[first_parentheses+1..last_parentheses]).split(',') {
            let arg = arg.trim();
            arg_tys.push(MsaTy::from(arg));
        }

        // The instruction is the intrinsic name without the __msa_ prefix.
        let instruction = &id[6..];
        let mut instruction = instruction.to_string();
        // With all underscores but the first one replaced with a `.`
        if let Some(first_underscore) = instruction.find('_') {
            let postfix = instruction[first_underscore+1 ..].replace('_', ".");
            instruction = instruction[0..=first_underscore].to_string();
            instruction += &postfix;
        }

        Ok(
            MsaIntrinsic {
                id,
                ret_ty,
                arg_tys,
                instruction,
            }
        )
    }
}

#[test]
fn verify_all_signatures() {
    // Parse the C intrinsic header file:
    let mut intrinsics = std::collections::HashMap::<String, MsaIntrinsic>::new();
    for line in HEADER.lines() {
        if line.is_empty() {
            continue;
        }

        use std::convert::TryFrom;
        let intrinsic: MsaIntrinsic = TryFrom::try_from(line).expect(
            &format!("failed to parse line: \"{}\"", line)
        );
        assert!(!intrinsics.contains_key(&intrinsic.id));
        intrinsics.insert(intrinsic.id.clone(), intrinsic);
    }

    let mut all_valid = true;
    for rust in FUNCTIONS {
        // Skip some intrinsics that aren't part of MSA
        match rust.name {
            "break_" => continue,
            _ => {}
        }
        let mips = match intrinsics.get(rust.name) {
            Some(i) => i,
            None => {
                eprintln!(
                    "missing mips definition for {:?} in {}",
                    rust.name, rust.file
                );
                all_valid = false;
                continue;
            }
        };

        if let Err(e) = matches(rust, mips) {
            println!("failed to verify `{}`", rust.name);
            println!("  * {}", e);
            all_valid = false;
        }
    }
    assert!(all_valid);
}

fn matches(rust: &Function, mips: &MsaIntrinsic) -> Result<(), String> {
    macro_rules! bail {
        ($($t:tt)*) => (return Err(format!($($t)*)))
    }

    if rust.ret.is_none() && mips.ret_ty != MsaTy::Void {
        bail!("mismatched return value")
    }

    if rust.arguments.len() != mips.arg_tys.len() {
        bail!("mismatched argument lengths");
    }

    let mut nconst = 0;
    for (i, (rust_arg, mips_arg))
        in rust.arguments.iter().zip(mips.arg_tys.iter()).enumerate() {
            match mips_arg {
                MsaTy::v16i8 if **rust_arg == v16i8 => (),
                MsaTy::v8i16 if **rust_arg == v8i16 => (),
                MsaTy::v4i32 if **rust_arg == v4i32 => (),
                MsaTy::v2i64 if **rust_arg == v2i64 => (),
                MsaTy::v16u8 if **rust_arg == v16u8 => (),
                MsaTy::v8u16 if **rust_arg == v8u16 => (),
                MsaTy::v4u32 if **rust_arg == v4u32 => (),
                MsaTy::v2u64 if **rust_arg == v2u64 => (),
                MsaTy::v4f32 if **rust_arg == v4f32 => (),
                MsaTy::v2f64 if **rust_arg == v2f64 => (),
                MsaTy::imm0_1 |
                MsaTy::imm0_3 |
                MsaTy::imm0_7 |
                MsaTy::imm0_15 |
                MsaTy::imm0_31 |
                MsaTy::imm0_63 |
                MsaTy::imm0_255 |
                MsaTy::imm_n16_15 |
                MsaTy::imm_n512_511 |
                MsaTy::imm_n1024_1022 |
                MsaTy::imm_n2048_2044 |
                MsaTy::imm_n4096_4088
                    if  **rust_arg == I32 => (),
                MsaTy::i32 if  **rust_arg == I32 => (),
                MsaTy::i64 if  **rust_arg == I64 => (),
                MsaTy::u32 if  **rust_arg == U32 => (),
                MsaTy::u64 if  **rust_arg == U64 => (),
                MsaTy::VoidPtr if **rust_arg == Type::Ptr(&U8) => (),
                m => {
                    bail!(
                        "mismatched argument \"{}\"= \"{:?}\" != \"{:?}\"",
                        i, m, *rust_arg
                    )
                }
            }

            let is_const = match mips_arg {
                MsaTy::imm0_1 |
                MsaTy::imm0_3 |
                MsaTy::imm0_7 |
                MsaTy::imm0_15 |
                MsaTy::imm0_31 |
                MsaTy::imm0_63 |
                MsaTy::imm0_255 |
                MsaTy::imm_n16_15 |
                MsaTy::imm_n512_511 |
                MsaTy::imm_n1024_1022 |
                MsaTy::imm_n2048_2044 |
                MsaTy::imm_n4096_4088 => true,
                _ => false,
            };
            if is_const {
                nconst += 1;
                if !rust.required_const.contains(&i) {
                    bail!("argument const mismatch");
                }
            }
        }

    if nconst != rust.required_const.len() {
        bail!("wrong number of const arguments");
    }

    if rust.target_feature != Some("msa") {
        bail!("wrong target_feature");
    }

    /* FIXME:
    if !rust.instrs.is_empty() {
        if rust.instrs[0] != mips.instruction {
            bail!("wrong instruction: \"{}\" != \"{}\"", rust.instrs[0], mips.instruction);
        }
    } else {
        bail!(
            "missing assert_instr for \"{}\" (should be \"{}\")",
            mips.id, mips.instruction);
    }*/

    Ok(())
}
<commit_msg>Formatting<commit_after>//! Verification of MIPS MSA intrinsics
#![feature(try_trait)]
#![allow(bad_style, unused)]

// This file is obtained from
// https://gcc.gnu.org/onlinedocs//gcc/MIPS-SIMD-Architecture-Built-in-Functions.html
static HEADER: &str = include_str!("../mips-msa.h");

stdsimd_verify::mips_functions!(static FUNCTIONS);

struct Function {
    name: &'static str,
    arguments: &'static [&'static Type],
    ret: Option<&'static Type>,
    target_feature: Option<&'static str>,
    instrs: &'static [&'static str],
    file: &'static str,
    required_const: &'static [usize],
}

static F16: Type = Type::PrimFloat(16);
static F32: Type = Type::PrimFloat(32);
static F64: Type = Type::PrimFloat(64);
static I8: Type = Type::PrimSigned(8);
static I16: Type = Type::PrimSigned(16);
static I32: Type = Type::PrimSigned(32);
static I64: Type = Type::PrimSigned(64);
static U8: Type = Type::PrimUnsigned(8);
static U16: Type = Type::PrimUnsigned(16);
static U32: Type = Type::PrimUnsigned(32);
static U64: Type = Type::PrimUnsigned(64);
static NEVER: Type = Type::Never;
static TUPLE: Type = Type::Tuple;
static v16i8: Type = Type::I(8, 16, 1);
static v8i16: Type = Type::I(16, 8, 1);
static v4i32: Type = Type::I(32, 4, 1);
static v2i64: Type = Type::I(64, 2, 1);
static v16u8: Type = Type::U(8, 16, 1);
static v8u16: Type = Type::U(16, 8, 1);
static v4u32: Type = Type::U(32, 4, 1);
static v2u64: Type = Type::U(64, 2, 1);
static v8f16: Type = Type::F(16, 8, 1);
static v4f32: Type = Type::F(32, 4, 1);
static v2f64: Type = Type::F(64, 2, 1);

#[derive(Debug, Copy, Clone, PartialEq)]
enum Type {
    PrimFloat(u8),
    PrimSigned(u8),
    PrimUnsigned(u8),
    PrimPoly(u8),
    MutPtr(&'static Type),
    ConstPtr(&'static Type),
    Ptr(&'static Type),
    Tuple,
    I(u8, u8, u8),
    U(u8, u8, u8),
    P(u8, u8, u8),
    F(u8, u8, u8),
    Never,
}

#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(non_camel_case_types)]
enum MsaTy {
    v16i8,
    v8i16,
    v4i32,
    v2i64,
    v16u8,
    v8u16,
    v4u32,
    v2u64,
    v8f16,
    v4f32,
    v2f64,
    imm0_1,
    imm0_3,
    imm0_7,
    imm0_15,
    imm0_31,
    imm0_63,
    imm0_255,
    imm_n16_15,
    imm_n512_511,
    imm_n1024_1022,
    imm_n2048_2044,
    imm_n4096_4088,
    i32,
    u32,
    i64,
    u64,
    Void,
    VoidPtr,
}

impl<'a> From<&'a str> for MsaTy {
    fn from(s: &'a str) -> MsaTy {
        match s {
            "v16i8" => MsaTy::v16i8,
            "v8i16" => MsaTy::v8i16,
            "v4i32" => MsaTy::v4i32,
            "v2i64" => MsaTy::v2i64,
            "v16u8" => MsaTy::v16u8,
            "v8u16" => MsaTy::v8u16,
            "v4u32" => MsaTy::v4u32,
            "v2u64" => MsaTy::v2u64,
            "v8f16" => MsaTy::v8f16,
            "v4f32" => MsaTy::v4f32,
            "v2f64" => MsaTy::v2f64,
            "imm0_1" => MsaTy::imm0_1,
            "imm0_3" => MsaTy::imm0_3,
            "imm0_7" => MsaTy::imm0_7,
            "imm0_15" => MsaTy::imm0_15,
            "imm0_31" => MsaTy::imm0_31,
            "imm0_63" => MsaTy::imm0_63,
            "imm0_255" => MsaTy::imm0_255,
            "imm_n16_15" => MsaTy::imm_n16_15,
            "imm_n512_511" => MsaTy::imm_n512_511,
            "imm_n1024_1022" => MsaTy::imm_n1024_1022,
            "imm_n2048_2044" => MsaTy::imm_n2048_2044,
            "imm_n4096_4088" => MsaTy::imm_n4096_4088,
            "i32" => MsaTy::i32,
            "u32" => MsaTy::u32,
            "i64" => MsaTy::i64,
            "u64" => MsaTy::u64,
            "void" => MsaTy::Void,
            "void *" => MsaTy::VoidPtr,
            v => panic!("unknown ty: \"{}\"", v),
        }
    }
}

#[derive(Debug, Clone)]
struct MsaIntrinsic {
    id: String,
    arg_tys: Vec<MsaTy>,
    ret_ty: MsaTy,
    instruction: String,
}

impl std::convert::TryFrom<&'static str> for MsaIntrinsic {
    // The intrinsics are just C function declarations of the form:
    // $ret_ty __builtin_${fn_id}($($arg_ty),*);
    type Error = std::option::NoneError;
    fn try_from(line: &'static str) -> Result<Self, Self::Error> {
        let first_whitespace = line.find(char::is_whitespace)?;
        let ret_ty = &line[0..first_whitespace];
        let ret_ty = MsaTy::from(ret_ty);

        let first_parentheses = line.find('(')?;
        assert!(first_parentheses > first_whitespace);
        let id = &line[first_whitespace + 1..first_parentheses].trim();
        assert!(id.starts_with("__builtin"));
        let mut id_str = "_".to_string();
        id_str += &id[9..];
        let id = id_str;

        let mut arg_tys = Vec::new();

        let last_parentheses = line.find(')')?;
        for arg in (&line[first_parentheses + 1..last_parentheses]).split(',') {
            let arg = arg.trim();
            arg_tys.push(MsaTy::from(arg));
        }

        // The instruction is the intrinsic name without the __msa_ prefix.
        let instruction = &id[6..];
        let mut instruction = instruction.to_string();
        // With all underscores but the first one replaced with a `.`
        if let Some(first_underscore) = instruction.find('_') {
            let postfix = instruction[first_underscore + 1..].replace('_', ".");
            instruction = instruction[0..=first_underscore].to_string();
            instruction += &postfix;
        }

        Ok(MsaIntrinsic {
            id,
            ret_ty,
            arg_tys,
            instruction,
        })
    }
}

#[test]
fn verify_all_signatures() {
    // Parse the C intrinsic header file:
    let mut intrinsics = std::collections::HashMap::<String, MsaIntrinsic>::new();
    for line in HEADER.lines() {
        if line.is_empty() {
            continue;
        }

        use std::convert::TryFrom;
        let intrinsic: MsaIntrinsic =
            TryFrom::try_from(line).expect(&format!("failed to parse line: \"{}\"", line));
        assert!(!intrinsics.contains_key(&intrinsic.id));
        intrinsics.insert(intrinsic.id.clone(), intrinsic);
    }

    let mut all_valid = true;
    for rust in FUNCTIONS {
        // Skip some intrinsics that aren't part of MSA
        match rust.name {
            "break_" => continue,
            _ => {}
        }
        let mips = match intrinsics.get(rust.name) {
            Some(i) => i,
            None => {
                eprintln!(
                    "missing mips definition for {:?} in {}",
                    rust.name, rust.file
                );
                all_valid = false;
                continue;
            }
        };

        if let Err(e) = matches(rust, mips) {
            println!("failed to verify `{}`", rust.name);
            println!("  * {}", e);
            all_valid = false;
        }
    }
    assert!(all_valid);
}

fn matches(rust: &Function, mips: &MsaIntrinsic) -> Result<(), String> {
    macro_rules! bail {
        ($($t:tt)*) => (return Err(format!($($t)*)))
    }

    if rust.ret.is_none() && mips.ret_ty != MsaTy::Void {
        bail!("mismatched return value")
    }

    if rust.arguments.len() != mips.arg_tys.len() {
        bail!("mismatched argument lengths");
    }

    let mut nconst = 0;
    for (i, (rust_arg, mips_arg)) in rust.arguments.iter().zip(mips.arg_tys.iter()).enumerate() {
        match mips_arg {
            MsaTy::v16i8 if **rust_arg == v16i8 => (),
            MsaTy::v8i16 if **rust_arg == v8i16 => (),
            MsaTy::v4i32 if **rust_arg == v4i32 => (),
            MsaTy::v2i64 if **rust_arg == v2i64 => (),
            MsaTy::v16u8 if **rust_arg == v16u8 => (),
            MsaTy::v8u16 if **rust_arg == v8u16 => (),
            MsaTy::v4u32 if **rust_arg == v4u32 => (),
            MsaTy::v2u64 if **rust_arg == v2u64 => (),
            MsaTy::v4f32 if **rust_arg == v4f32 => (),
            MsaTy::v2f64 if **rust_arg == v2f64 => (),
            MsaTy::imm0_1
            | MsaTy::imm0_3
            | MsaTy::imm0_7
            | MsaTy::imm0_15
            | MsaTy::imm0_31
            | MsaTy::imm0_63
            | MsaTy::imm0_255
            | MsaTy::imm_n16_15
            | MsaTy::imm_n512_511
            | MsaTy::imm_n1024_1022
            | MsaTy::imm_n2048_2044
            | MsaTy::imm_n4096_4088
                if **rust_arg == I32 =>
            {
                ()
            }
            MsaTy::i32 if **rust_arg == I32 => (),
            MsaTy::i64 if **rust_arg == I64 => (),
            MsaTy::u32 if **rust_arg == U32 => (),
            MsaTy::u64 if **rust_arg == U64 => (),
            MsaTy::VoidPtr if **rust_arg == Type::Ptr(&U8) => (),
            m => bail!(
                "mismatched argument \"{}\"= \"{:?}\" != \"{:?}\"",
                i,
                m,
                *rust_arg
            ),
        }

        let is_const = match mips_arg {
            MsaTy::imm0_1
            | MsaTy::imm0_3
            | MsaTy::imm0_7
            | MsaTy::imm0_15
            | MsaTy::imm0_31
            | MsaTy::imm0_63
            | MsaTy::imm0_255
            | MsaTy::imm_n16_15
            | MsaTy::imm_n512_511
            | MsaTy::imm_n1024_1022
            | MsaTy::imm_n2048_2044
            | MsaTy::imm_n4096_4088 => true,
            _ => false,
        };
        if is_const {
            nconst += 1;
            if !rust.required_const.contains(&i) {
                bail!("argument const mismatch");
            }
        }
    }

    if nconst != rust.required_const.len() {
        bail!("wrong number of const arguments");
    }

    if rust.target_feature != Some("msa") {
        bail!("wrong target_feature");
    }

    /* FIXME:
    if !rust.instrs.is_empty() {
        if rust.instrs[0] != mips.instruction {
            bail!("wrong instruction: \"{}\" != \"{}\"", rust.instrs[0], mips.instruction);
        }
    } else {
        bail!(
            "missing assert_instr for \"{}\" (should be \"{}\")",
            mips.id, mips.instruction);
    }*/

    Ok(())
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use glib::ffi::GType;
use gtk;
use gtk::ffi;

pub struct TreeStore {
    pointer: *mut ffi::C_GtkTreeStore
}

impl TreeStore {
    pub fn new(column_types: Vec<GType>) -> Option<TreeStore> {
        let tmp_pointer = unsafe { ffi::gtk_tree_store_newv(column_types.len().to_i32().unwrap(), column_types.as_slice()) };
        check_pointer!(tmp_pointer, TreeStore)
    }

    pub fn set_column_types(&self, column_types: Vec<GType>) {
        unsafe { ffi::gtk_tree_store_set_column_types(self.pointer, column_types.len().to_i32().unwrap(), column_types.as_slice()) }
    }

    pub fn set_column_text(&self, iter: &mut ffi::C_GtkTreeIter, column: i32, text: &str) {
        let text_c = text.to_c_str();
        unsafe { ffi::gtk_tree_store_set(self.pointer, iter, column, text_c.as_ptr(), -1i) }
    }

    pub fn remove(&self, iter: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_remove(self.pointer, iter) }
    }

    pub fn insert(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, position: i32) {
        unsafe { ffi::gtk_tree_store_insert(self.pointer, iter, parent, position) }
    }

    pub fn insert_before(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, sibling: &mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_insert_before(self.pointer, iter, parent, sibling) }
    }

    pub fn insert_after(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, sibling: &mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_insert_after(self.pointer, iter, parent, sibling) }
    }

    pub fn prepend(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_prepend(self.pointer, iter, parent) }
    }

    pub fn append(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_append(self.pointer, iter, parent) }
    }

    pub fn is_ancestor(&self, iter: &mut ffi::C_GtkTreeIter, descendent: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_is_ancestor(self.pointer, iter, descendent) }
    }

    pub fn iter_depth(&self, iter: &mut ffi::C_GtkTreeIter) -> i32 {
        unsafe { ffi::gtk_tree_store_iter_depth(self.pointer, iter) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_tree_store_clear(self.pointer) }
    }

    pub fn iter_is_valid(&self, iter: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_iter_is_valid(self.pointer, iter) }
    }

    pub fn reorder(&self, parent: &mut ffi::C_GtkTreeIter, new_order: *mut i32) {
        unsafe { ffi::gtk_tree_store_reorder(self.pointer, parent, new_order) }
    }

    pub fn swap(&self, a: &mut ffi::C_GtkTreeIter, b: &mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_swap(self.pointer, a, b) }
    }

    pub fn move_before(&self, iter: &mut ffi::C_GtkTreeIter, position: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_move_before(self.pointer, iter, position) }
    }

    pub fn move_after(&self, iter: &mut ffi::C_GtkTreeIter, position: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_move_before(self.pointer, iter, position) }
    }

    pub fn get_model(&self) -> Option<gtk::TreeModel> {
        if self.pointer.is_null() {
            None
        } else {
            Some(gtk::TreeModel::wrap_pointer(gtk::cast::GTK_TREE_MODEL_FROM_TREE_STORE(self.pointer)))
        }
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_GtkTreeStore {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(c_treestore: *mut ffi::C_GtkTreeStore) -> TreeStore {
        TreeStore {
            pointer: c_treestore
        }
    }
}
<commit_msg>Add *mut to a few more places<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use glib::ffi::GType;
use gtk;
use gtk::ffi;

pub struct TreeStore {
    pointer: *mut ffi::C_GtkTreeStore
}

impl TreeStore {
    pub fn new(column_types: Vec<GType>) -> Option<TreeStore> {
        let tmp_pointer = unsafe { ffi::gtk_tree_store_newv(column_types.len().to_i32().unwrap(), column_types.as_slice()) };
        check_pointer!(tmp_pointer, TreeStore)
    }

    pub fn set_column_types(&self, column_types: Vec<GType>) {
        unsafe { ffi::gtk_tree_store_set_column_types(self.pointer, column_types.len().to_i32().unwrap(), column_types.as_slice()) }
    }

    pub fn set_column_text(&self, iter: &mut ffi::C_GtkTreeIter, column: i32, text: &str) {
        let text_c = text.to_c_str();
        unsafe { ffi::gtk_tree_store_set(self.pointer, iter, column, text_c.as_ptr(), -1i) }
    }

    pub fn remove(&self, iter: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_remove(self.pointer, iter) }
    }

    pub fn insert(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, position: i32) {
        unsafe { ffi::gtk_tree_store_insert(self.pointer, iter, parent, position) }
    }

    pub fn insert_before(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, sibling: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_insert_before(self.pointer, iter, parent, sibling) }
    }

    pub fn insert_after(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter, sibling: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_insert_after(self.pointer, iter, parent, sibling) }
    }

    pub fn prepend(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_prepend(self.pointer, iter, parent) }
    }

    pub fn append(&self, iter: &mut ffi::C_GtkTreeIter, parent: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_append(self.pointer, iter, parent) }
    }

    pub fn is_ancestor(&self, iter: &mut ffi::C_GtkTreeIter, descendent: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_is_ancestor(self.pointer, iter, descendent) }
    }

    pub fn iter_depth(&self, iter: &mut ffi::C_GtkTreeIter) -> i32 {
        unsafe { ffi::gtk_tree_store_iter_depth(self.pointer, iter) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_tree_store_clear(self.pointer) }
    }

    pub fn iter_is_valid(&self, iter: &mut ffi::C_GtkTreeIter) -> bool {
        unsafe { ffi::gtk_tree_store_iter_is_valid(self.pointer, iter) }
    }

    pub fn reorder(&self, parent: &mut ffi::C_GtkTreeIter, new_order: *mut i32) {
        unsafe { ffi::gtk_tree_store_reorder(self.pointer, parent, new_order) }
    }

    pub fn swap(&self, a: &mut ffi::C_GtkTreeIter, b: &mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_swap(self.pointer, a, b) }
    }

    pub fn move_before(&self, iter: &mut ffi::C_GtkTreeIter, position: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_move_before(self.pointer, iter, position) }
    }

    pub fn move_after(&self, iter: &mut ffi::C_GtkTreeIter, position: *mut ffi::C_GtkTreeIter) {
        unsafe { ffi::gtk_tree_store_move_before(self.pointer, iter, position) }
    }

    pub fn get_model(&self) -> Option<gtk::TreeModel> {
        if self.pointer.is_null() {
            None
        } else {
            Some(gtk::TreeModel::wrap_pointer(gtk::cast::GTK_TREE_MODEL_FROM_TREE_STORE(self.pointer)))
        }
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_GtkTreeStore {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(c_treestore: *mut ffi::C_GtkTreeStore) -> TreeStore {
        TreeStore {
            pointer: c_treestore
        }
    }
}
<|endoftext|>