<commit_before>use collision::{Aabb3};
use std::sync::Mutex;
use stopwatch;
use time;

use common::entity_id;
use common::fnv_map;
use common::id_allocator;
use common::voxel;

use in_progress_terrain;
use lod;
use physics::Physics;
use terrain;
use update_gaia;
use update_gaia::LoadReason;

// TODO: Consider factoring this logic such that what to load is separated from how it's loaded.

/// Load and unload terrain::TerrainBlocks from the game.
/// Each terrain::TerrainBlock can be owned by a set of owners, each of which can independently request LODs.
/// The maximum lod::T requested is the one that is actually loaded.
pub struct T {
  pub terrain: terrain::T,
  pub in_progress_terrain: Mutex<in_progress_terrain::T>,
  pub lod_map: Mutex<lod::Map>,
  pub loaded: Mutex<fnv_map::T<voxel::bounds::T, Vec<entity_id::T>>>,
}

impl T {
  pub fn new() -> T {
    T {
      terrain: terrain::T::new(terrain::Seed::new(0)),
      in_progress_terrain: Mutex::new(in_progress_terrain::T::new()),
      lod_map: Mutex::new(lod::Map::new()),
      loaded: Mutex::new(fnv_map::new()),
    }
  }

  // TODO: Avoid the double-lookup when unload and load the same index.

  pub fn load<LoadBlock>(
    &self,
    id_allocator: &Mutex<id_allocator::T<entity_id::T>>,
    physics: &Mutex<Physics>,
    block_position: &voxel::bounds::T,
    new_lod: lod::T,
    owner: lod::OwnerId,
    load_block: &mut LoadBlock,
  ) where LoadBlock: FnMut(update_gaia::Message)
  {
    let prev_lod;
    let max_lod_changed: bool;
    let mut lod_map = self.lod_map.lock().unwrap();
    let mut in_progress_terrain = self.in_progress_terrain.lock().unwrap();
    match lod_map.get(block_position, owner) {
      Some((Some(prev), lods)) => {
        prev_lod = Some(prev);
        if new_lod == prev {
          return;
        }

        if new_lod < prev {
          max_lod_changed = lods.iter().filter(|&&(_, l)| l >= prev).count() < 2;
        } else {
          max_lod_changed = lods.iter().filter(|&&(_, l)| l >= new_lod).count() == 0;
        }
      },
      Some((None, lods)) => {
        max_lod_changed = lods.iter().filter(|&&(_, l)| l >= new_lod).count() == 0;
        prev_lod = None;
      },
      None => {
        max_lod_changed = true;
        prev_lod = None;
      },
    }

    if !max_lod_changed {
      // Maximum lod::T is unchanged.
      let (_, change) = lod_map.insert(*block_position, new_lod, owner);
      assert!(change.is_none());
      return;
    }

    match new_lod {
      lod::Placeholder => {
        let (_, change) = lod_map.insert(*block_position, new_lod, owner);
        let change = change.unwrap();
        assert!(change.loaded == None);
        assert!(prev_lod == None);
        assert!(change.desired == Some(lod::Placeholder));
        in_progress_terrain.insert(id_allocator, physics, block_position);
      },
      lod::Full => {
        let mut generate_block = || {
          debug!("{:?} requested from gaia", block_position);
          load_block(
            update_gaia::Message::Load(time::precise_time_ns(), vec!(*block_position), LoadReason::Local(owner))
          );
        };
        generate_block();
      },
    };
  }

  pub fn insert_block(
    block: &LoadedTerrain,
    position: &voxel::bounds::T,
    owner: lod::OwnerId,
    physics: &Mutex<Physics>,
    lod_map: &mut lod::Map,
    in_progress_terrain: &mut in_progress_terrain::T,
    loaded: &mut fnv_map::T<voxel::bounds::T, Vec<entity_id::T>>,
  ) {
    let lod = lod::Full;
    let (_, change) = lod_map.insert(*position, lod, owner);
    // TODO: This should be an unwrap, but the preconditions of another TODO aren't
    // satisfied in src/update_gaia.rs.
    // (i.e. blocks sometimes get here when they're stale).
    let change = match change {
      None => return,
      Some(change) => change,
    };
    assert!(change.desired == Some(lod));
    change.loaded.map(|loaded_lod|
      match loaded_lod {
        lod::Placeholder => {
          in_progress_terrain.remove(physics, position);
        }
        lod::Full => {
          stopwatch::time("terrain_loader.load.unload", || {
            let ids = loaded.get(position).unwrap();
            let mut physics = physics.lock().unwrap();
            for id in ids {
              physics.remove_terrain(*id);
            }
          });
        },
      }
    );

    stopwatch::time("terrain_loader.load.physics", || {
      let mut physics = physics.lock().unwrap();
      for &(ref id, ref bounds) in &block.bounds {
        physics.insert_terrain(*id, bounds);
      }
    });
  }

  pub fn unload(
    &self,
    physics: &Mutex<Physics>,
    block_position: &voxel::bounds::T,
    owner: lod::OwnerId,
  ) {
    let lod_change;
    match self.lod_map.lock().unwrap().remove(*block_position, owner) {
      (_, None) => return,
      (_, Some(c)) => lod_change = c,
    }

    lod_change.loaded.map(|loaded_lod| {
      match loaded_lod {
        lod::Placeholder => {
          self.in_progress_terrain.lock().unwrap().remove(physics, block_position);
        }
        lod::Full => {
          stopwatch::time("terrain_loader.unload", || {
            match self.loaded.lock().unwrap().get(block_position) {
              None => {
                // Unloaded before the load request completed.
              },
              Some(ids) => {
                let mut physics = physics.lock().unwrap();
                for id in ids {
                  physics.remove_terrain(*id);
                }
              },
            }
          });
        },
      }
    });
  }
}

pub struct LoadedTerrain {
  pub bounds: Vec<(entity_id::T, Aabb3<f32>)>,
}
<commit_msg>alignment<commit_after>use collision::{Aabb3};
use std::sync::Mutex;
use stopwatch;
use time;

use common::entity_id;
use common::fnv_map;
use common::id_allocator;
use common::voxel;

use in_progress_terrain;
use lod;
use physics::Physics;
use terrain;
use update_gaia;
use update_gaia::LoadReason;

// TODO: Consider factoring this logic such that what to load is separated from how it's loaded.

/// Load and unload terrain::TerrainBlocks from the game.
/// Each terrain::TerrainBlock can be owned by a set of owners, each of which can independently request LODs.
/// The maximum lod::T requested is the one that is actually loaded.
pub struct T {
  pub terrain             : terrain::T,
  pub in_progress_terrain : Mutex<in_progress_terrain::T>,
  pub lod_map             : Mutex<lod::Map>,
  pub loaded              : Mutex<fnv_map::T<voxel::bounds::T, Vec<entity_id::T>>>,
}

impl T {
  pub fn new() -> T {
    T {
      terrain             : terrain::T::new(terrain::Seed::new(0)),
      in_progress_terrain : Mutex::new(in_progress_terrain::T::new()),
      lod_map             : Mutex::new(lod::Map::new()),
      loaded              : Mutex::new(fnv_map::new()),
    }
  }

  // TODO: Avoid the double-lookup when unload and load the same index.

  pub fn load<LoadBlock>(
    &self,
    id_allocator   : &Mutex<id_allocator::T<entity_id::T>>,
    physics        : &Mutex<Physics>,
    block_position : &voxel::bounds::T,
    new_lod        : lod::T,
    owner          : lod::OwnerId,
    load_block     : &mut LoadBlock,
  ) where LoadBlock: FnMut(update_gaia::Message)
  {
    let prev_lod;
    let max_lod_changed: bool;
    let mut lod_map = self.lod_map.lock().unwrap();
    let mut in_progress_terrain = self.in_progress_terrain.lock().unwrap();
    match lod_map.get(block_position, owner) {
      Some((Some(prev), lods)) => {
        prev_lod = Some(prev);
        if new_lod == prev {
          return;
        }

        if new_lod < prev {
          max_lod_changed = lods.iter().filter(|&&(_, l)| l >= prev).count() < 2;
        } else {
          max_lod_changed = lods.iter().filter(|&&(_, l)| l >= new_lod).count() == 0;
        }
      },
      Some((None, lods)) => {
        max_lod_changed = lods.iter().filter(|&&(_, l)| l >= new_lod).count() == 0;
        prev_lod = None;
      },
      None => {
        max_lod_changed = true;
        prev_lod = None;
      },
    }

    if !max_lod_changed {
      // Maximum lod::T is unchanged.
      let (_, change) = lod_map.insert(*block_position, new_lod, owner);
      assert!(change.is_none());
      return;
    }

    match new_lod {
      lod::Placeholder => {
        let (_, change) = lod_map.insert(*block_position, new_lod, owner);
        let change = change.unwrap();
        assert!(change.loaded == None);
        assert!(prev_lod == None);
        assert!(change.desired == Some(lod::Placeholder));
        in_progress_terrain.insert(id_allocator, physics, block_position);
      },
      lod::Full => {
        let mut generate_block = || {
          debug!("{:?} requested from gaia", block_position);
          load_block(
            update_gaia::Message::Load(time::precise_time_ns(), vec!(*block_position), LoadReason::Local(owner))
          );
        };
        generate_block();
      },
    };
  }

  pub fn insert_block(
    block               : &LoadedTerrain,
    position            : &voxel::bounds::T,
    owner               : lod::OwnerId,
    physics             : &Mutex<Physics>,
    lod_map             : &mut lod::Map,
    in_progress_terrain : &mut in_progress_terrain::T,
    loaded              : &mut fnv_map::T<voxel::bounds::T, Vec<entity_id::T>>,
  ) {
    let lod = lod::Full;
    let (_, change) = lod_map.insert(*position, lod, owner);
    // TODO: This should be an unwrap, but the preconditions of another TODO aren't
    // satisfied in src/update_gaia.rs.
    // (i.e. blocks sometimes get here when they're stale).
    let change = match change {
      None => return,
      Some(change) => change,
    };
    assert!(change.desired == Some(lod));
    change.loaded.map(|loaded_lod|
      match loaded_lod {
        lod::Placeholder => {
          in_progress_terrain.remove(physics, position);
        }
        lod::Full => {
          stopwatch::time("terrain_loader.load.unload", || {
            let ids = loaded.get(position).unwrap();
            let mut physics = physics.lock().unwrap();
            for id in ids {
              physics.remove_terrain(*id);
            }
          });
        },
      }
    );

    stopwatch::time("terrain_loader.load.physics", || {
      let mut physics = physics.lock().unwrap();
      for &(ref id, ref bounds) in &block.bounds {
        physics.insert_terrain(*id, bounds);
      }
    });
  }

  pub fn unload(
    &self,
    physics        : &Mutex<Physics>,
    block_position : &voxel::bounds::T,
    owner          : lod::OwnerId,
  ) {
    let lod_change;
    match self.lod_map.lock().unwrap().remove(*block_position, owner) {
      (_, None) => return,
      (_, Some(c)) => lod_change = c,
    }

    lod_change.loaded.map(|loaded_lod| {
      match loaded_lod {
        lod::Placeholder => {
          self.in_progress_terrain.lock().unwrap().remove(physics, block_position);
        }
        lod::Full => {
          stopwatch::time("terrain_loader.unload", || {
            match self.loaded.lock().unwrap().get(block_position) {
              None => {
                // Unloaded before the load request completed.
              },
              Some(ids) => {
                let mut physics = physics.lock().unwrap();
                for id in ids {
                  physics.remove_terrain(*id);
                }
              },
            }
          });
        },
      }
    });
  }
}

pub struct LoadedTerrain {
  pub bounds: Vec<(entity_id::T, Aabb3<f32>)>,
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use hyper::{Method, StatusCode, HttpVersion};

use farmhash;

pub struct CacheRoute;

impl CacheRoute {
    pub fn gen_ns(shard: u8, version: HttpVersion, method: &Method, path: &str,
                    query: Option<&str>, authorization: &str) -> String {
        let namespace_raw = format!("[{}][{}][{}][{}][{}]", version, method,
            path, query.unwrap_or(""), authorization);
        let namespace_hash = farmhash::hash64(namespace_raw.as_bytes());

        debug!("Generated namespace: {} with hash: {}", namespace_raw,
            namespace_hash);

        format!("{}.{:x}", shard, namespace_hash)
    }
}

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

    #[test]
    fn it_generates_valid_ns() {
        assert_eq!(CacheRoute::gen_ns(
            0, HttpVersion::Http11, &Method::Get, "/", Some(""), ""),
            "0.f8bb423988eb2814", "[shard=0][auth=no] HTTP/1.1 GET /");
        assert_eq!(CacheRoute::gen_ns(
            0, HttpVersion::Http11, &Method::Post, "/login", Some(""), ""),
            "0.9927a78b4d94dbf5", "[shard=0][auth=no] HTTP/1.1 POST /login");
        assert_eq!(CacheRoute::gen_ns(
            7, HttpVersion::Http11, &Method::Options, "/feed", Some(""), "8ab"),
            "7.2b5dc16d448eecb9", "[shard=7][auth=yes] HTTP/1.1 OPTIONS /feed");
        assert_eq!(CacheRoute::gen_ns(
            80, HttpVersion::H2, &Method::Head, "/user", Some("u=1"), "2d"),
            "80.7011223c059f2bfb", "[shard=80][auth=yes] h2 HEAD /feed");
    }
}

<commit_msg>Prefix memcached keys w/ bloom:<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use hyper::{Method, StatusCode, HttpVersion};

use farmhash;

pub struct CacheRoute;

impl CacheRoute {
    pub fn gen_ns(shard: u8, version: HttpVersion, method: &Method, path: &str,
                    query: Option<&str>, authorization: &str) -> String {
        let namespace_raw = format!("[{}][{}][{}][{}][{}]", version, method,
            path, query.unwrap_or(""), authorization);
        let namespace_hash = farmhash::hash64(namespace_raw.as_bytes());

        debug!("Generated namespace: {} with hash: {}", namespace_raw,
            namespace_hash);

        format!("bloom:{}:{:x}", shard, namespace_hash)
    }
}

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

    #[test]
    fn it_generates_valid_ns() {
        assert_eq!(CacheRoute::gen_ns(
            0, HttpVersion::Http11, &Method::Get, "/", Some(""), ""),
            "bloom:0:f8bb423988eb2814",
            "[shard=0][auth=no] HTTP/1.1 GET /");
        assert_eq!(CacheRoute::gen_ns(
            0, HttpVersion::Http11, &Method::Post, "/login", Some(""), ""),
            "bloom:0:9927a78b4d94dbf5",
            "[shard=0][auth=no] HTTP/1.1 POST /login");
        assert_eq!(CacheRoute::gen_ns(
            7, HttpVersion::Http11, &Method::Options, "/feed", Some(""), "8ab"),
            "bloom:7:2b5dc16d448eecb9",
            "[shard=7][auth=yes] HTTP/1.1 OPTIONS /feed");
        assert_eq!(CacheRoute::gen_ns(
            80, HttpVersion::H2, &Method::Head, "/user", Some("u=1"), "2d"),
            "bloom:80:7011223c059f2bfb",
            "[shard=80][auth=yes] h2 HEAD /feed");
    }
}

<|endoftext|>


<commit_before>
use std::process;
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::ops;

use value::{Value, ToLisp, FromLisp};
use parse::Token;
use eval::{Lisp, FuncError, FuncResult};

macro_rules! math {
    ($name:ident, $op:path) => {
        pub fn $name(mut items: Vec<Value>, _: &mut Lisp) -> FuncResult {
            let mut total = match items.remove(0) {
                Value::Number(n) => n,
                _ => return Err(FuncError::InvalidArguments),
            };

            for item in items {
                match item {
                    Value::Number(next) => {
                        total = $op(total, next);
                    },
                    _ => return Err(FuncError::InvalidArguments),
                }
            }

            Ok(total.to_lisp())
        }
    }
}

// Core functions
pub fn define(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        let token = try!(Token::from_lisp(val));
        let mut list = try!(token.as_list());

        if list.len() != 2 {
            return Err(FuncError::InvalidArguments);
        }

        let sym = try!(list.remove(0).as_sym());
        let value = try!(lisp.eval_token(list.remove(0)));

        lisp.cur_scope().set(&sym, value);
    }

    Ok(Value::Nil)
}

pub fn pow(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let base = try!(f32::from_lisp(vals.remove(0)));
    let exp = try!(f32::from_lisp(vals.remove(0)));

    Ok(base.powf(exp).to_lisp())
}

pub fn print(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Str(string) => print!("{}", string),
            _ => print!("{:?}", val),
        }
    }

    println!("");
    Ok(Value::Nil)
}

pub fn input(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let prompt = if vals.len() == 1 {
        match vals.remove(0) {
            Value::Str(prompt) => prompt,
            _ => return Err(FuncError::InvalidArguments),
        }
    } else {
        "".to_string()
    };

    print!("{}", prompt);
    match io::stdout().flush() {
        Ok(_) => (),
        Err(err) => return Err(FuncError::IoError(err)),
    }

    let mut stdin = io::stdin();

    let mut input = String::new();
    match stdin.read_line(&mut input) {
        Ok(_) => {
            input.pop(); // remove newline
            Ok(input.to_lisp())
        }
        Err(err) => Err(FuncError::IoError(err)),
    }
}

pub fn exit(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let exit_code = if vals.len() == 1 {
        match vals[0] {
            Value::Number(code) => code as i32,
            _ => return Err(FuncError::InvalidArguments),
        }
    } else {
        0
    };

    process::exit(exit_code);
}

pub fn str_fn(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let mut result = String::new();

    for val in vals {
        let string = match val {
            Value::Str(str) => str,
            other => format!("{:?}", other),
        };

        result.push_str(&string);
    }

    Ok(result.to_lisp())
}

pub fn eq(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for i in (0 .. vals.len() - 1) {
        if vals[i] != vals[i + 1] {
            return Ok(false.to_lisp());
        }
    }

    Ok(true.to_lisp())
}

pub fn and(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if !val {
                    return Ok(false.to_lisp());
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(true.to_lisp())
}

pub fn or(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if val {
                    return Ok(true.to_lisp());
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(false.to_lisp())
}

pub fn not(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    match vals[0] {
        Value::Bool(val) => Ok(Value::Bool(!val)),
        _ => Err(FuncError::InvalidArguments),
    }
}

pub fn cons(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let head: Token = try!(Token::from_lisp(vals.remove(0)));
    let tail: Token = try!(Token::from_lisp(vals.remove(0)));

    let mut tail_tokens = match tail {
        Token::List(toks) => toks,
        _ => return Err(FuncError::InvalidArguments),
    };

    tail_tokens.insert(0, head);

    Ok(Value::Quote(Token::List(tail_tokens)))
}

math!(add, ops::Add::add);
math!(sub, ops::Sub::sub);
math!(mul, ops::Mul::mul);
math!(div, ops::Div::div);
<commit_msg>Define now modifies the global scope<commit_after>
use std::process;
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::ops;

use value::{Value, ToLisp, FromLisp};
use parse::Token;
use eval::{Lisp, FuncError, FuncResult};

macro_rules! math {
    ($name:ident, $op:path) => {
        pub fn $name(mut items: Vec<Value>, _: &mut Lisp) -> FuncResult {
            let mut total = match items.remove(0) {
                Value::Number(n) => n,
                _ => return Err(FuncError::InvalidArguments),
            };

            for item in items {
                match item {
                    Value::Number(next) => {
                        total = $op(total, next);
                    },
                    _ => return Err(FuncError::InvalidArguments),
                }
            }

            Ok(total.to_lisp())
        }
    }
}

// Core functions
pub fn define(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        let token = try!(Token::from_lisp(val));
        let mut list = try!(token.as_list());

        if list.len() != 2 {
            return Err(FuncError::InvalidArguments);
        }

        let sym = try!(list.remove(0).as_sym());
        let value = try!(lisp.eval_token(list.remove(0)));

        lisp.set_global(&sym, value);
    }

    Ok(Value::Nil)
}

pub fn pow(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let base = try!(f32::from_lisp(vals.remove(0)));
    let exp = try!(f32::from_lisp(vals.remove(0)));

    Ok(base.powf(exp).to_lisp())
}

pub fn print(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Str(string) => print!("{}", string),
            _ => print!("{:?}", val),
        }
    }

    println!("");
    Ok(Value::Nil)
}

pub fn input(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let prompt = if vals.len() == 1 {
        match vals.remove(0) {
            Value::Str(prompt) => prompt,
            _ => return Err(FuncError::InvalidArguments),
        }
    } else {
        "".to_string()
    };

    print!("{}", prompt);
    match io::stdout().flush() {
        Ok(_) => (),
        Err(err) => return Err(FuncError::IoError(err)),
    }

    let mut stdin = io::stdin();

    let mut input = String::new();
    match stdin.read_line(&mut input) {
        Ok(_) => {
            input.pop(); // remove newline
            Ok(input.to_lisp())
        }
        Err(err) => Err(FuncError::IoError(err)),
    }
}

pub fn exit(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let exit_code = if vals.len() == 1 {
        match vals[0] {
            Value::Number(code) => code as i32,
            _ => return Err(FuncError::InvalidArguments),
        }
    } else {
        0
    };

    process::exit(exit_code);
}

pub fn str_fn(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let mut result = String::new();

    for val in vals {
        let string = match val {
            Value::Str(str) => str,
            other => format!("{:?}", other),
        };

        result.push_str(&string);
    }

    Ok(result.to_lisp())
}

pub fn eq(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for i in (0 .. vals.len() - 1) {
        if vals[i] != vals[i + 1] {
            return Ok(false.to_lisp());
        }
    }

    Ok(true.to_lisp())
}

pub fn and(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if !val {
                    return Ok(false.to_lisp());
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(true.to_lisp())
}

pub fn or(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if val {
                    return Ok(true.to_lisp());
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(false.to_lisp())
}

pub fn not(vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    match vals[0] {
        Value::Bool(val) => Ok(Value::Bool(!val)),
        _ => Err(FuncError::InvalidArguments),
    }
}

pub fn cons(mut vals: Vec<Value>, lisp: &mut Lisp) -> FuncResult {
    let head: Token = try!(Token::from_lisp(vals.remove(0)));
    let tail: Token = try!(Token::from_lisp(vals.remove(0)));

    let mut tail_tokens = match tail {
        Token::List(toks) => toks,
        _ => return Err(FuncError::InvalidArguments),
    };

    tail_tokens.insert(0, head);

    Ok(Value::Quote(Token::List(tail_tokens)))
}

math!(add, ops::Add::add);
math!(sub, ops::Sub::sub);
math!(mul, ops::Mul::mul);
math!(div, ops::Div::div);
<|endoftext|>


<commit_before>use fake_adapter::FakeBluetoothAdapter;
use fake_service::FakeBluetoothGATTService;
use std::cell::{Cell, RefCell};
use std::error::Error;

#[derive(Clone, Debug)]
pub struct FakeBluetoothDevice {
    object_path: RefCell<String>,
    adapter: RefCell<FakeBluetoothAdapter>,
    address: RefCell<String>,
    appearance: Cell<u16>,
    //connectionError: Cell<u32>,
    //deviceClass: Cell<u32>,
    gattServices: RefCell<Vec<FakeBluetoothGATTService>>,
    //isPaired: Cell<bool>,
    isConnectable: Cell<bool>,
    isConnected: Cell<bool>,
    //isTrusted: Cell<bool>,
    isBlocked: Cell<bool>,
    //isLegacyPairing: Cell<bool>,
    uuids: RefCell<Vec<String>>,
    name: RefCell<String>,
    //productId: Cell<u32>,
    //productVersion: Cell<u32>,
    rssi: Cell<i16>,
    txPower: Cell<i16>,
    //vendorId: Cell<u32>,
    //vendorIdSource: RefCell<String>,
}

impl FakeBluetoothDevice {
    pub fn new(object_path: String,
               adapter: FakeBluetoothAdapter,
               address: String,
               appearance: u16,
               //connectionError: u32,
               //deviceClass: u32,
               gattServices: Vec<FakeBluetoothGATTService>,
               //isPaired: bool,
               isConnectable: bool,
               isConnected: bool,
               //isTrusted: bool,
               isBlocked: bool,
               //isLegacyPairing: bool,
               uuids: Vec<String>,
               name: String,
               //productId: u32,
               //productVersion: u32,
               rssi: i16,
               txPower: i16,
               //vendorId: u32,
               //vendorIdSource: String
               )
               -> FakeBluetoothDevice {
        FakeBluetoothDevice{
            object_path: RefCell::new(object_path),
            adapter: RefCell::new(adapter),
            address: RefCell::new(address),
            appearance: Cell::new(appearance),
            //connectionError: Cell::new(connectionError),
            //deviceClass: Cell::new(deviceClass),
            gattServices: RefCell::new(gattServices),
            //isPaired: Cell::new(isPaired),
            isConnectable: Cell::new(isConnectable),
            isConnected: Cell::new(isConnected),
            //isTrusted: Cell::new(isTrusted),
            isBlocked: Cell::new(isBlocked),
            //isLegacyPairing: Cell::new(isLegacyPairing),
            uuids: RefCell::new(uuids),
            name: RefCell::new(name),
            //productId: Cell::new(productId),
            //productVersion: Cell::new(productVersion),
            rssi: Cell::new(rssi),
            txPower: Cell::new(txPower),
            //vendorId: Cell::new(vendorId),
            //vendorIdSource: RefCell::new(vendorIdSource),
        }
    }

    pub fn new_empty() -> FakeBluetoothDevice {
        FakeBluetoothDevice{
            object_path: RefCell::new(String::new()),
            adapter: RefCell::new(FakeBluetoothAdapter::new_empty()),
            address: RefCell::new(String::new()),
            appearance: Cell::new(0),
            //connectionError: Cell::new(0),
            //deviceClass: Cell::new(0),
            gattServices: RefCell::new(vec![]),
            //isPaired: Cell::new(false),
            isConnectable: Cell::new(false),
            isConnected: Cell::new(false),
            //isTrusted: Cell::new(false),
            isBlocked: Cell::new(false),
            //isLegacyPairing: Cell::new(false),
            uuids: RefCell::new(vec![]),
            name: RefCell::new(String::new()),
            //productId: Cell::new(0),
            //productVersion: Cell::new(0),
            rssi: Cell::new(0),
            txPower: Cell::new(0),
            //vendorId: Cell::new(0),
            //vendorIdSource: RefCell::new(String::new()),
        }
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.borrow().clone()
    }

    pub fn set_object_path(&mut self, path: String) {
        *self.object_path.borrow_mut() = path;
    }

    pub fn get_adapter(&self) -> FakeBluetoothAdapter {
        self.adapter.borrow().clone()
    }

    pub fn set_adapter(&mut self, adapter: FakeBluetoothAdapter) {
        *self.adapter.borrow_mut() = adapter;
    }

    pub fn get_address(&self) -> String {
        self.address.borrow().clone()
    }

    pub fn set_address(&mut self, address: String) {
        *self.address.borrow_mut() = address;
    }

    pub fn get_appearance(&self) -> u16 {
        self.appearance.get()
    }

    pub fn set_appearance(&mut self, value: u16) {
        self.appearance.set(value);
    }

    /*pub fn get_connection_error(&self) -> u32 {
        self.connectionError.get()
    }

    pub fn set_connection_error(&mut self, value: u32) {
        self.connectionError.set(value);
    }*/

    /*pub fn get_device_class(&self) -> u32 {
        self.deviceClass.get()
    }

    pub fn set_device_class(&mut self, value: u32) {
        self.deviceClass.set(value);
    }*/

    pub fn get_gatt_services(&self) -> Vec<FakeBluetoothGATTService> {
        self.gattServices.borrow().clone()
    }

    pub fn set_gatt_service(&mut self, services: Vec<FakeBluetoothGATTService>) {
        *self.gattServices.borrow_mut() = services;
    }

    /*pub fn is_paired(&self) -> bool {
        self.isPaired.get()
    }

    pub fn set_paired(&mut self, value: bool) {
        self.isPaired.set(value);
    }*/

    pub fn is_connected(&self) -> bool {
        self.isConnected.get()
    }

    pub fn set_connected(&mut self, value: bool) {
        self.isConnected.set(value);
    }

    /*pub fn is_trusted(&self) -> bool {
        self.isTrusted.get()
    }

    pub fn set_trusted(&mut self, value: bool) {
        self.isTrusted.set(value);
    }*/

    pub fn is_blocked(&self) -> bool {
        self.isBlocked.get()
    }

    pub fn set_blocked(&mut self, value: bool) {
        self.isBlocked.set(value);
    }

    /*pub fn is_legacy_pairing(&self) -> bool {
        self.isLegacyPairing.get()
    }

    pub fn set_legacy_pairing(&mut self, value: bool) {
        self.isLegacyPairing.set(value);
    }*/

    pub fn get_uuids(&self) -> Vec<String> {
        self.uuids.borrow().clone()
    }

    pub fn set_uuids(&mut self, uuids: Vec<String>) {
        *self.uuids.borrow_mut() = uuids;
    }

    pub fn get_name(&self) -> String {
        self.name.borrow().clone()
    }

    pub fn set_name(&mut self, name: String) {
        *self.name.borrow_mut() = name;
    }

    /*pub fn get_product_id(&self) -> u32 {
        self.productId.get()
    }

    pub fn set_product_id(&mut self, value: u32) {
        self.productId.set(value);
    }

    pub fn get_product_version(&self) -> u32 {
        self.productVersion.get()
    }

    pub fn set_product_version(&mut self, value: u32) {
        self.productVersion.set(value);
    }*/

    pub fn get_rssi(&self) -> i16 {
        self.rssi.get()
    }

    pub fn set_rssi(&mut self, value: i16) {
        self.rssi.set(value);
    }

    pub fn get_tx_power(&self) -> i16 {
        self.txPower.get()
    }

    pub fn set_tx_power(&mut self, value: i16) {
        self.txPower.set(value);
    }

    /*pub fn get_vendor_id(&self) -> u32 {
        self.vendorId.get()
    }

    pub fn set_vendor_id(&mut self, value: u32) {
        self.vendorId.set(value);
    }

    pub fn get_vendor_id_source(&self) -> String {
        self.vendorIdSource.borrow().clone()
    }

    pub fn set_vendor_id_source(&mut self, value: String) {
        *self.vendorIdSource.borrow_mut() = value;
    }*/

    pub fn connect(&mut self) -> Result<(), Box<Error>> {
        if self.isConnectable.get() && !self.isConnected.get() {
            self.isConnected.set(true);
            return Ok(());
        } else {
            return Err(Box::from("Could not connect to the device."));
        }
    }

    pub fn disconnect(&mut self) -> Result<(), Box<Error>>{
        if self.isConnected.get() {
            self.isConnected.set(false);
            return Ok(());
        } else {
            return Err(Box::from("The device is not connected."));
        }
    }
}
<commit_msg>Deleted some unused functions of the BlDevice<commit_after>use fake_adapter::FakeBluetoothAdapter;
use fake_service::FakeBluetoothGATTService;
use std::cell::{Cell, RefCell};
use std::error::Error;

#[derive(Clone, Debug)]
pub struct FakeBluetoothDevice {
    object_path: RefCell<String>,
    adapter: RefCell<FakeBluetoothAdapter>,
    address: RefCell<String>,
    appearance: Cell<u16>,
    //connectionError: Cell<u32>,
    //deviceClass: Cell<u32>,
    gattServices: RefCell<Vec<FakeBluetoothGATTService>>,
    //isPaired: Cell<bool>,
    isConnectable: Cell<bool>,
    isConnected: Cell<bool>,
    //isTrusted: Cell<bool>,
    isBlocked: Cell<bool>,
    //isLegacyPairing: Cell<bool>,
    uuids: RefCell<Vec<String>>,
    name: RefCell<String>,
    //productId: Cell<u32>,
    //productVersion: Cell<u32>,
    rssi: Cell<i16>,
    txPower: Cell<i16>,
    //vendorId: Cell<u32>,
    //vendorIdSource: RefCell<String>,
}

impl FakeBluetoothDevice {
    pub fn new(object_path: String,
               adapter: FakeBluetoothAdapter,
               address: String,
               appearance: u16,
               //connectionError: u32,
               //deviceClass: u32,
               gattServices: Vec<FakeBluetoothGATTService>,
               //isPaired: bool,
               isConnectable: bool,
               isConnected: bool,
               //isTrusted: bool,
               isBlocked: bool,
               //isLegacyPairing: bool,
               uuids: Vec<String>,
               name: String,
               //productId: u32,
               //productVersion: u32,
               rssi: i16,
               txPower: i16,
               //vendorId: u32,
               //vendorIdSource: String
               )
               -> FakeBluetoothDevice {
        FakeBluetoothDevice{
            object_path: RefCell::new(object_path),
            adapter: RefCell::new(adapter),
            address: RefCell::new(address),
            appearance: Cell::new(appearance),
            //connectionError: Cell::new(connectionError),
            //deviceClass: Cell::new(deviceClass),
            gattServices: RefCell::new(gattServices),
            //isPaired: Cell::new(isPaired),
            isConnectable: Cell::new(isConnectable),
            isConnected: Cell::new(isConnected),
            //isTrusted: Cell::new(isTrusted),
            isBlocked: Cell::new(isBlocked),
            //isLegacyPairing: Cell::new(isLegacyPairing),
            uuids: RefCell::new(uuids),
            name: RefCell::new(name),
            //productId: Cell::new(productId),
            //productVersion: Cell::new(productVersion),
            rssi: Cell::new(rssi),
            txPower: Cell::new(txPower),
            //vendorId: Cell::new(vendorId),
            //vendorIdSource: RefCell::new(vendorIdSource),
        }
    }

    pub fn new_empty() -> FakeBluetoothDevice {
        FakeBluetoothDevice{
            object_path: RefCell::new(String::new()),
            adapter: RefCell::new(FakeBluetoothAdapter::new_empty()),
            address: RefCell::new(String::new()),
            appearance: Cell::new(0),
            //connectionError: Cell::new(0),
            //deviceClass: Cell::new(0),
            gattServices: RefCell::new(vec![]),
            //isPaired: Cell::new(false),
            isConnectable: Cell::new(false),
            isConnected: Cell::new(false),
            //isTrusted: Cell::new(false),
            isBlocked: Cell::new(false),
            //isLegacyPairing: Cell::new(false),
            uuids: RefCell::new(vec![]),
            name: RefCell::new(String::new()),
            //productId: Cell::new(0),
            //productVersion: Cell::new(0),
            rssi: Cell::new(0),
            txPower: Cell::new(0),
            //vendorId: Cell::new(0),
            //vendorIdSource: RefCell::new(String::new()),
        }
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.borrow().clone()
    }

    pub fn set_object_path(&mut self, path: String) {
        *self.object_path.borrow_mut() = path;
    }

    pub fn get_adapter(&self) -> FakeBluetoothAdapter {
        self.adapter.borrow().clone()
    }

    pub fn set_adapter(&mut self, adapter: FakeBluetoothAdapter) {
        *self.adapter.borrow_mut() = adapter;
    }

    pub fn get_address(&self) -> String {
        self.address.borrow().clone()
    }

    pub fn set_address(&mut self, address: String) {
        *self.address.borrow_mut() = address;
    }

    pub fn get_appearance(&self) -> u16 {
        self.appearance.get()
    }

    pub fn set_appearance(&mut self, value: u16) {
        self.appearance.set(value);
    }

    pub fn get_gatt_services(&self) -> Vec<FakeBluetoothGATTService> {
        self.gattServices.borrow().clone()
    }

    pub fn set_gatt_service(&mut self, services: Vec<FakeBluetoothGATTService>) {
        *self.gattServices.borrow_mut() = services;
    }

    pub fn is_connected(&self) -> bool {
        self.isConnected.get()
    }

    pub fn set_connected(&mut self, value: bool) {
        self.isConnected.set(value);
    }

    pub fn is_blocked(&self) -> bool {
        self.isBlocked.get()
    }

    pub fn set_blocked(&mut self, value: bool) {
        self.isBlocked.set(value);
    }

    pub fn get_uuids(&self) -> Vec<String> {
        self.uuids.borrow().clone()
    }

    pub fn set_uuids(&mut self, uuids: Vec<String>) {
        *self.uuids.borrow_mut() = uuids;
    }

    pub fn get_name(&self) -> String {
        self.name.borrow().clone()
    }

    pub fn set_name(&mut self, name: String) {
        *self.name.borrow_mut() = name;
    }

    pub fn get_rssi(&self) -> i16 {
        self.rssi.get()
    }

    pub fn set_rssi(&mut self, value: i16) {
        self.rssi.set(value);
    }

    pub fn get_tx_power(&self) -> i16 {
        self.txPower.get()
    }

    pub fn set_tx_power(&mut self, value: i16) {
        self.txPower.set(value);
    }

    pub fn connect(&mut self) -> Result<(), Box<Error>> {
        if self.isConnectable.get() && !self.isConnected.get() {
            self.isConnected.set(true);
            return Ok(());
        } else {
            return Err(Box::from("Could not connect to the device."));
        }
    }

    pub fn disconnect(&mut self) -> Result<(), Box<Error>>{
        if self.isConnected.get() {
            self.isConnected.set(false);
            return Ok(());
        } else {
            return Err(Box::from("The device is not connected."));
        }
    }
}
<|endoftext|>


<commit_before>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetLayerDefn(hLayer: *()) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_FD_GetFieldCount(hDefn: *()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *(), iField: c_int) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *()) -> *c_char;
    fn OGR_Fld_GetNameRef(hDefn: *()) -> *c_char;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
    fn VSIFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn fields<'a>(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as int;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *(),
    next_id: int,
    total: int,
}

impl<'a> Iterator<String> for FieldIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<String> {
        if self.next_id == self.total {
            return None;
        }
        let name = unsafe {
            let c_field_defn = OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            );
            let c_name = OGR_Fld_GetNameRef(c_field_defn);
            raw::from_c_str(c_name)
        };
        self.next_id += 1;
        return Some(name);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(raw::from_c_str(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(RealValue(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = raw::from_c_str(c_json);
            VSIFree(c_json as *());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self { StringValue(rv) => rv, _ => fail!("not a StringValue") }
    }

    pub fn as_real(self) -> f64 {
        match self { RealValue(rv) => rv, _ => fail!("not a RealValue") }
    }
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.layer_count(), 1);
    }

    fn with_features(fixture: &str, f: |FeatureIterator|) {
        let ds = open(&fixture_path(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature(fixture: &str, f: |Feature|) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |mut features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway".to_string())
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.count(|field| {
                    let highway = field.field("highway".to_string())
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() }),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key".to_string())
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field".to_string()).is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer.fields().collect();
        let ok_names = vec!("kind", "sort_key", "is_link", "is_tunnel",
                        "is_bridge", "railway", "highway")
                       .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<commit_msg>iterator yields Field objects<commit_after>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetLayerDefn(hLayer: *()) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_FD_GetFieldCount(hDefn: *()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *(), iField: c_int) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *()) -> *c_char;
    fn OGR_Fld_GetNameRef(hDefn: *()) -> *c_char;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
    fn VSIFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn fields<'a>(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as int;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *(),
    next_id: int,
    total: int,
}

impl<'a> Iterator<Field<'a>> for FieldIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    layer: &'a Layer<'a>,
    c_field_defn: *(),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        unsafe { raw::from_c_str(OGR_Fld_GetNameRef(self.c_field_defn)) }
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(raw::from_c_str(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(RealValue(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = raw::from_c_str(c_json);
            VSIFree(c_json as *());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self { StringValue(rv) => rv, _ => fail!("not a StringValue") }
    }

    pub fn as_real(self) -> f64 {
        match self { RealValue(rv) => rv, _ => fail!("not a RealValue") }
    }
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.layer_count(), 1);
    }

    fn with_features(fixture: &str, f: |FeatureIterator|) {
        let ds = open(&fixture_path(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature(fixture: &str, f: |Feature|) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |mut features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway".to_string())
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.count(|field| {
                    let highway = field.field("highway".to_string())
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() }),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key".to_string())
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field".to_string()).is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names = vec!("kind", "sort_key", "is_link", "is_tunnel",
                        "is_bridge", "railway", "highway")
                       .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<|endoftext|>


<commit_before>//! Unsafe pointer utility functions

export addr_of;
export assimilate;
export mut_addr_of;
export offset;
export const_offset;
export mut_offset;
export null;
export is_null;
export is_not_null;
export memcpy;
export memmove;
export memset;
export to_uint;
export ref_eq;
export buf_len;
export position;
export Ptr;

import cmp::Eq;
import libc::{c_void, size_t};

#[nolink]
#[abi = "cdecl"]
extern mod libc_ {
    #[rust_stack]
    fn memcpy(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void;
    #[rust_stack]
    fn memmove(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void;
    #[rust_stack]
    fn memset(dest: *c_void, c: libc::c_int, len: libc::size_t) -> *c_void;
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn addr_of<T>(val: T) -> *T;
}

/// Get an unsafe pointer to a value
#[inline(always)]
pure fn addr_of<T>(val: T) -> *T { unchecked { rusti::addr_of(val) } }

/// Get an unsafe mut pointer to a value
#[inline(always)]
pure fn mut_addr_of<T>(val: T) -> *mut T {
    unsafe {
        unsafe::reinterpret_cast(rusti::addr_of(val))
    }
}

/// Calculate the offset from a pointer
#[inline(always)]
fn offset<T>(ptr: *T, count: uint) -> *T {
    unsafe {
        (ptr as uint + count * sys::size_of::<T>()) as *T
    }
}

/// Calculate the offset from a const pointer
#[inline(always)]
fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
    unsafe {
        (ptr as uint + count * sys::size_of::<T>()) as *T
    }
}

/// Calculate the offset from a mut pointer
#[inline(always)]
fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T {
    (ptr as uint + count * sys::size_of::<T>()) as *mut T
}

/// Return the offset of the first null pointer in `buf`.
#[inline(always)]
unsafe fn buf_len<T>(buf: **T) -> uint {
    position(buf, |i| i == null())
}

/// Return the first offset `i` such that `f(buf[i]) == true`.
#[inline(always)]
unsafe fn position<T>(buf: *T, f: fn(T) -> bool) -> uint {
    let mut i = 0u;
    loop {
        if f(*offset(buf, i)) { return i; }
        else { i += 1u; }
    }
}

/// Create an unsafe null pointer
#[inline(always)]
pure fn null<T>() -> *T { unsafe { unsafe::reinterpret_cast(0u) } }

/// Returns true if the pointer is equal to the null pointer.
pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }

/// Returns true if the pointer is not equal to the null pointer.
pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }

/**
 * Copies data from one location to another
 *
 * Copies `count` elements (not bytes) from `src` to `dst`. The source
 * and destination may not overlap.
 */
#[inline(always)]
unsafe fn memcpy<T>(dst: *T, src: *T, count: uint) {
    let n = count * sys::size_of::<T>();
    libc_::memcpy(dst as *c_void, src as *c_void, n as size_t);
}

/**
 * Copies data from one location to another
 *
 * Copies `count` elements (not bytes) from `src` to `dst`. The source
 * and destination may overlap.
 */
#[inline(always)]
unsafe fn memmove<T>(dst: *T, src: *T, count: uint)  {
    let n = count * sys::size_of::<T>();
    libc_::memmove(dst as *c_void, src as *c_void, n as size_t);
}

#[inline(always)]
unsafe fn memset<T>(dst: *mut T, c: int, count: uint)  {
    let n = count * sys::size_of::<T>();
    libc_::memset(dst as *c_void, c as libc::c_int, n as size_t);
}

/**
  Transform a region pointer - &T - to an unsafe pointer - *T.
  This is safe, but is implemented with an unsafe block due to
  reinterpret_cast.

  ("assimilate" because it makes the pointer forget its region.)
*/
#[inline(always)]
fn assimilate<T>(thing: &T) -> *T unsafe {
    unsafe::reinterpret_cast(thing)
}
/**
  Cast a region pointer - &T - to a uint.
  This is safe, but is implemented with an unsafe block due to
  reinterpret_cast.

  (I couldn't think of a cutesy name for this one.)
*/
#[inline(always)]
fn to_uint<T>(thing: &T) -> uint unsafe {
    unsafe::reinterpret_cast(thing)
}

/// Determine if two borrowed pointers point to the same thing.
#[inline(always)]
fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
    to_uint(thing) == to_uint(other)
}

trait Ptr {
    pure fn is_null() -> bool;
    pure fn is_not_null() -> bool;
}

/// Extension methods for pointers
impl<T> *T: Ptr {
    /// Returns true if the pointer is equal to the null pointer.
    pure fn is_null() -> bool { is_null(self) }

    /// Returns true if the pointer is not equal to the null pointer.
    pure fn is_not_null() -> bool { is_not_null(self) }
}

// Equality for pointers
impl<T> *T : Eq {
    pure fn eq(&&other: *T) -> bool { self == other }
}

#[test]
fn test() {
    unsafe {
        type Pair = {mut fst: int, mut snd: int};
        let p = {mut fst: 10, mut snd: 20};
        let pptr: *mut Pair = mut_addr_of(p);
        let iptr: *mut int = unsafe::reinterpret_cast(pptr);
        assert (*iptr == 10);;
        *iptr = 30;
        assert (*iptr == 30);
        assert (p.fst == 30);;

        *pptr = {mut fst: 50, mut snd: 60};
        assert (*iptr == 50);
        assert (p.fst == 50);
        assert (p.snd == 60);

        let v0 = ~[32000u16, 32001u16, 32002u16];
        let v1 = ~[0u16, 0u16, 0u16];

        ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u),
                    ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u);
        assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
        ptr::memcpy(vec::unsafe::to_ptr(v1),
                    ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u);
        assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
        ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u),
                    vec::unsafe::to_ptr(v0), 1u);
        assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
    }
}

#[test]
fn test_position() {
    import str::as_c_str;
    import libc::c_char;

    let s = ~"hello";
    unsafe {
        assert 2u == as_c_str(s, |p| position(p, |c| c == 'l' as c_char));
        assert 4u == as_c_str(s, |p| position(p, |c| c == 'o' as c_char));
        assert 5u == as_c_str(s, |p| position(p, |c| c == 0 as c_char));
    }
}

#[test]
fn test_buf_len() {
    let s0 = ~"hello";
    let s1 = ~"there";
    let s2 = ~"thing";
    do str::as_c_str(s0) |p0| {
        do str::as_c_str(s1) |p1| {
            do str::as_c_str(s2) |p2| {
                let v = ~[p0, p1, p2, null()];
                do vec::as_buf(v) |vp, len| {
                    assert unsafe { buf_len(vp) } == 3u;
                    assert len == 4u;
                }
            }
        }
    }
}

#[test]
fn test_is_null() {
   let p: *int = ptr::null();
   assert p.is_null();
   assert !p.is_not_null();

   let q = ptr::offset(p, 1u);
   assert !q.is_null();
   assert q.is_not_null();
}
<commit_msg>libcore: Fix equality for pointers... again<commit_after>//! Unsafe pointer utility functions

export addr_of;
export assimilate;
export mut_addr_of;
export offset;
export const_offset;
export mut_offset;
export null;
export is_null;
export is_not_null;
export memcpy;
export memmove;
export memset;
export to_uint;
export ref_eq;
export buf_len;
export position;
export Ptr;

import cmp::Eq;
import libc::{c_void, size_t};

#[nolink]
#[abi = "cdecl"]
extern mod libc_ {
    #[rust_stack]
    fn memcpy(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void;
    #[rust_stack]
    fn memmove(dest: *c_void, src: *c_void, n: libc::size_t) -> *c_void;
    #[rust_stack]
    fn memset(dest: *c_void, c: libc::c_int, len: libc::size_t) -> *c_void;
}

#[abi = "rust-intrinsic"]
extern mod rusti {
    fn addr_of<T>(val: T) -> *T;
}

/// Get an unsafe pointer to a value
#[inline(always)]
pure fn addr_of<T>(val: T) -> *T { unchecked { rusti::addr_of(val) } }

/// Get an unsafe mut pointer to a value
#[inline(always)]
pure fn mut_addr_of<T>(val: T) -> *mut T {
    unsafe {
        unsafe::reinterpret_cast(rusti::addr_of(val))
    }
}

/// Calculate the offset from a pointer
#[inline(always)]
fn offset<T>(ptr: *T, count: uint) -> *T {
    unsafe {
        (ptr as uint + count * sys::size_of::<T>()) as *T
    }
}

/// Calculate the offset from a const pointer
#[inline(always)]
fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
    unsafe {
        (ptr as uint + count * sys::size_of::<T>()) as *T
    }
}

/// Calculate the offset from a mut pointer
#[inline(always)]
fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T {
    (ptr as uint + count * sys::size_of::<T>()) as *mut T
}

/// Return the offset of the first null pointer in `buf`.
#[inline(always)]
unsafe fn buf_len<T>(buf: **T) -> uint {
    position(buf, |i| i == null())
}

/// Return the first offset `i` such that `f(buf[i]) == true`.
#[inline(always)]
unsafe fn position<T>(buf: *T, f: fn(T) -> bool) -> uint {
    let mut i = 0u;
    loop {
        if f(*offset(buf, i)) { return i; }
        else { i += 1u; }
    }
}

/// Create an unsafe null pointer
#[inline(always)]
pure fn null<T>() -> *T { unsafe { unsafe::reinterpret_cast(0u) } }

/// Returns true if the pointer is equal to the null pointer.
pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }

/// Returns true if the pointer is not equal to the null pointer.
pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }

/**
 * Copies data from one location to another
 *
 * Copies `count` elements (not bytes) from `src` to `dst`. The source
 * and destination may not overlap.
 */
#[inline(always)]
unsafe fn memcpy<T>(dst: *T, src: *T, count: uint) {
    let n = count * sys::size_of::<T>();
    libc_::memcpy(dst as *c_void, src as *c_void, n as size_t);
}

/**
 * Copies data from one location to another
 *
 * Copies `count` elements (not bytes) from `src` to `dst`. The source
 * and destination may overlap.
 */
#[inline(always)]
unsafe fn memmove<T>(dst: *T, src: *T, count: uint)  {
    let n = count * sys::size_of::<T>();
    libc_::memmove(dst as *c_void, src as *c_void, n as size_t);
}

#[inline(always)]
unsafe fn memset<T>(dst: *mut T, c: int, count: uint)  {
    let n = count * sys::size_of::<T>();
    libc_::memset(dst as *c_void, c as libc::c_int, n as size_t);
}

/**
  Transform a region pointer - &T - to an unsafe pointer - *T.
  This is safe, but is implemented with an unsafe block due to
  reinterpret_cast.

  ("assimilate" because it makes the pointer forget its region.)
*/
#[inline(always)]
fn assimilate<T>(thing: &T) -> *T unsafe {
    unsafe::reinterpret_cast(thing)
}
/**
  Cast a region pointer - &T - to a uint.
  This is safe, but is implemented with an unsafe block due to
  reinterpret_cast.

  (I couldn't think of a cutesy name for this one.)
*/
#[inline(always)]
fn to_uint<T>(thing: &T) -> uint unsafe {
    unsafe::reinterpret_cast(thing)
}

/// Determine if two borrowed pointers point to the same thing.
#[inline(always)]
fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
    to_uint(thing) == to_uint(other)
}

trait Ptr {
    pure fn is_null() -> bool;
    pure fn is_not_null() -> bool;
}

/// Extension methods for pointers
impl<T> *T: Ptr {
    /// Returns true if the pointer is equal to the null pointer.
    pure fn is_null() -> bool { is_null(self) }

    /// Returns true if the pointer is not equal to the null pointer.
    pure fn is_not_null() -> bool { is_not_null(self) }
}

// Equality for pointers
impl<T> *const T : Eq {
    pure fn eq(&&other: *const T) -> bool { self == other }
}

#[test]
fn test() {
    unsafe {
        type Pair = {mut fst: int, mut snd: int};
        let p = {mut fst: 10, mut snd: 20};
        let pptr: *mut Pair = mut_addr_of(p);
        let iptr: *mut int = unsafe::reinterpret_cast(pptr);
        assert (*iptr == 10);;
        *iptr = 30;
        assert (*iptr == 30);
        assert (p.fst == 30);;

        *pptr = {mut fst: 50, mut snd: 60};
        assert (*iptr == 50);
        assert (p.fst == 50);
        assert (p.snd == 60);

        let v0 = ~[32000u16, 32001u16, 32002u16];
        let v1 = ~[0u16, 0u16, 0u16];

        ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 1u),
                    ptr::offset(vec::unsafe::to_ptr(v0), 1u), 1u);
        assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
        ptr::memcpy(vec::unsafe::to_ptr(v1),
                    ptr::offset(vec::unsafe::to_ptr(v0), 2u), 1u);
        assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
        ptr::memcpy(ptr::offset(vec::unsafe::to_ptr(v1), 2u),
                    vec::unsafe::to_ptr(v0), 1u);
        assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
    }
}

#[test]
fn test_position() {
    import str::as_c_str;
    import libc::c_char;

    let s = ~"hello";
    unsafe {
        assert 2u == as_c_str(s, |p| position(p, |c| c == 'l' as c_char));
        assert 4u == as_c_str(s, |p| position(p, |c| c == 'o' as c_char));
        assert 5u == as_c_str(s, |p| position(p, |c| c == 0 as c_char));
    }
}

#[test]
fn test_buf_len() {
    let s0 = ~"hello";
    let s1 = ~"there";
    let s2 = ~"thing";
    do str::as_c_str(s0) |p0| {
        do str::as_c_str(s1) |p1| {
            do str::as_c_str(s2) |p2| {
                let v = ~[p0, p1, p2, null()];
                do vec::as_buf(v) |vp, len| {
                    assert unsafe { buf_len(vp) } == 3u;
                    assert len == 4u;
                }
            }
        }
    }
}

#[test]
fn test_is_null() {
   let p: *int = ptr::null();
   assert p.is_null();
   assert !p.is_not_null();

   let q = ptr::offset(p, 1u);
   assert !q.is_null();
   assert q.is_not_null();
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::Type;

#[test]
fn test_mut_self() {
    syn::parse_str::<Type>("fn(mut self)").unwrap();
    syn::parse_str::<Type>("fn(mut self: ())").unwrap();
    syn::parse_str::<Type>("fn(mut self: ...)").unwrap_err();
    syn::parse_str::<Type>("fn(mut self: mut self)").unwrap_err();
    syn::parse_str::<Type>("fn(mut self::T)").unwrap_err();
}

#[test]
fn test_macro_variable_type() {
    // mimics the token stream corresponding to `$ty<T>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Ident(Ident::new("T", Span::call_site())),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "ty",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "T",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);

    // mimics the token stream corresponding to `$ty::<T>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Ident(Ident::new("T", Span::call_site())),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "ty",
                    arguments: PathArguments::AngleBracketed {
                        colon2_token: Some,
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "T",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_group_angle_brackets() {
    // mimics the token stream corresponding to `Option<$ty>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("Option", Span::call_site())),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "Option",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Group {
                                elem: Type::Path {
                                    path: Path {
                                        segments: [
                                            PathSegment {
                                                ident: "Vec",
                                                arguments: PathArguments::AngleBracketed {
                                                    args: [
                                                        Type(Type::Path {
                                                            path: Path {
                                                                segments: [
                                                                    PathSegment {
                                                                        ident: "u8",
                                                                        arguments: None,
                                                                    },
                                                                ],
                                                            },
                                                        }),
                                                    ],
                                                },
                                            },
                                        ],
                                    },
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_group_colons() {
    // mimics the token stream corresponding to `$ty::Item`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Ident(Ident::new("Item", Span::call_site())),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "Vec",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "u8",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
                PathSegment {
                    ident: "Item",
                    arguments: None,
                },
            ],
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Ident(Ident::new("Element", Span::call_site())),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        qself: Some(QSelf {
            ty: Type::Slice {
                elem: Type::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "T",
                                arguments: None,
                            },
                        ],
                    },
                },
            },
            position: 0,
        }),
        path: Path {
            leading_colon: Some,
            segments: [
                PathSegment {
                    ident: "Element",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_trait_object() {
    let tokens = quote!(dyn for<'a> Trait<'a> + 'static);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Trait(TraitBound {
                modifier: None,
                lifetimes: Some(BoundLifetimes {
                    lifetimes: [
                        LifetimeDef {
                            lifetime: Lifetime {
                                ident: "a",
                            },
                        },
                    ],
                }),
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: PathArguments::AngleBracketed {
                                args: [
                                    Lifetime(Lifetime {
                                        ident: "a",
                                    }),
                                ],
                            },
                        },
                    ],
                },
            }),
            Lifetime(Lifetime {
                ident: "static",
            }),
        ],
    }
    "###);

    let tokens = quote!(dyn 'a + Trait);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Lifetime(Lifetime {
                ident: "a",
            }),
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    // None of the following are valid Rust types.
    syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err();
    syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err();
}

#[test]
fn test_trailing_plus() {
    #[rustfmt::skip]
    let tokens = quote!(impl Trait +);
    snapshot!(tokens as Type, @r###"
    Type::ImplTrait {
        bounds: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(dyn Trait +);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}
<commit_msg>Add test of trailing plus on bare (non-dyn) trait object<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::Type;

#[test]
fn test_mut_self() {
    syn::parse_str::<Type>("fn(mut self)").unwrap();
    syn::parse_str::<Type>("fn(mut self: ())").unwrap();
    syn::parse_str::<Type>("fn(mut self: ...)").unwrap_err();
    syn::parse_str::<Type>("fn(mut self: mut self)").unwrap_err();
    syn::parse_str::<Type>("fn(mut self::T)").unwrap_err();
}

#[test]
fn test_macro_variable_type() {
    // mimics the token stream corresponding to `$ty<T>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Ident(Ident::new("T", Span::call_site())),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "ty",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "T",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);

    // mimics the token stream corresponding to `$ty::<T>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { ty })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Ident(Ident::new("T", Span::call_site())),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "ty",
                    arguments: PathArguments::AngleBracketed {
                        colon2_token: Some,
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "T",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_group_angle_brackets() {
    // mimics the token stream corresponding to `Option<$ty>`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("Option", Span::call_site())),
        TokenTree::Punct(Punct::new('<', Spacing::Alone)),
        TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
        TokenTree::Punct(Punct::new('>', Spacing::Alone)),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "Option",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Group {
                                elem: Type::Path {
                                    path: Path {
                                        segments: [
                                            PathSegment {
                                                ident: "Vec",
                                                arguments: PathArguments::AngleBracketed {
                                                    args: [
                                                        Type(Type::Path {
                                                            path: Path {
                                                                segments: [
                                                                    PathSegment {
                                                                        ident: "u8",
                                                                        arguments: None,
                                                                    },
                                                                ],
                                                            },
                                                        }),
                                                    ],
                                                },
                                            },
                                        ],
                                    },
                                },
                            }),
                        ],
                    },
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_group_colons() {
    // mimics the token stream corresponding to `$ty::Item`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { Vec<u8> })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Ident(Ident::new("Item", Span::call_site())),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        path: Path {
            segments: [
                PathSegment {
                    ident: "Vec",
                    arguments: PathArguments::AngleBracketed {
                        args: [
                            Type(Type::Path {
                                path: Path {
                                    segments: [
                                        PathSegment {
                                            ident: "u8",
                                            arguments: None,
                                        },
                                    ],
                                },
                            }),
                        ],
                    },
                },
                PathSegment {
                    ident: "Item",
                    arguments: None,
                },
            ],
        },
    }
    "###);

    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })),
        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
        TokenTree::Ident(Ident::new("Element", Span::call_site())),
    ]);

    snapshot!(tokens as Type, @r###"
    Type::Path {
        qself: Some(QSelf {
            ty: Type::Slice {
                elem: Type::Path {
                    path: Path {
                        segments: [
                            PathSegment {
                                ident: "T",
                                arguments: None,
                            },
                        ],
                    },
                },
            },
            position: 0,
        }),
        path: Path {
            leading_colon: Some,
            segments: [
                PathSegment {
                    ident: "Element",
                    arguments: None,
                },
            ],
        },
    }
    "###);
}

#[test]
fn test_trait_object() {
    let tokens = quote!(dyn for<'a> Trait<'a> + 'static);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Trait(TraitBound {
                modifier: None,
                lifetimes: Some(BoundLifetimes {
                    lifetimes: [
                        LifetimeDef {
                            lifetime: Lifetime {
                                ident: "a",
                            },
                        },
                    ],
                }),
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: PathArguments::AngleBracketed {
                                args: [
                                    Lifetime(Lifetime {
                                        ident: "a",
                                    }),
                                ],
                            },
                        },
                    ],
                },
            }),
            Lifetime(Lifetime {
                ident: "static",
            }),
        ],
    }
    "###);

    let tokens = quote!(dyn 'a + Trait);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Lifetime(Lifetime {
                ident: "a",
            }),
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    // None of the following are valid Rust types.
    syn::parse_str::<Type>("for<'a> dyn Trait<'a>").unwrap_err();
    syn::parse_str::<Type>("dyn for<'a> 'a + Trait").unwrap_err();
}

#[test]
fn test_trailing_plus() {
    #[rustfmt::skip]
    let tokens = quote!(impl Trait +);
    snapshot!(tokens as Type, @r###"
    Type::ImplTrait {
        bounds: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(dyn Trait +);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        dyn_token: Some,
        bounds: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(Trait +);
    snapshot!(tokens as Type, @r###"
    Type::TraitObject {
        bounds: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Trait",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}
<|endoftext|>


<commit_before>import std.sys;

fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
fn mul(uint x, uint y) -> uint { ret x * y; }
fn div(uint x, uint y) -> uint { ret x / y; }
fn rem(uint x, uint y) -> uint { ret x % y; }

fn lt(uint x, uint y) -> bool { ret x < y; }
fn le(uint x, uint y) -> bool { ret x <= y; }
fn eq(uint x, uint y) -> bool { ret x == y; }
fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }

iter range(mutable uint lo, uint hi) -> uint {
  while (lo < hi) {
    put lo;
    lo += 1u;
  }
}

fn next_power_of_two(uint n) -> uint {
  // FIXME change |* uint(4)| below to |* uint(8) / uint(2)| and watch the
  // world explode.
  let uint halfbits = sys.rustrt.size_of[uint]() * 4u;
  let uint tmp = n - 1u;
  let uint shift = 1u;
  while (shift <= halfbits) {
    tmp |= tmp >> shift;
    shift <<= 1u;
  }
  ret tmp + 1u;
}

fn to_str(mutable uint n, uint radix) -> str
{
  check (0u < radix && radix <= 16u);
  fn digit(uint n) -> str {
    alt (n) {
      case (0u) { ret "0"; }
      case (1u) { ret "1"; }
      case (2u) { ret "2"; }
      case (3u) { ret "3"; }
      case (4u) { ret "4"; }
      case (5u) { ret "5"; }
      case (6u) { ret "6"; }
      case (7u) { ret "7"; }
      case (8u) { ret "8"; }
      case (9u) { ret "9"; }
      case (10u) { ret "a"; }
      case (11u) { ret "b"; }
      case (12u) { ret "c"; }
      case (13u) { ret "d"; }
      case (14u) { ret "e"; }
      case (15u) { ret "f"; }
    }
  }

  if (n == 0u) { ret "0"; }

  let str s = "";
  while (n > 0u) {
    s = digit(n % radix) + s;
    n /= radix;
  }
  ret s;
}
<commit_msg>Redo _uint.to_str to work with chars and only one tmp str, built left-to-right.<commit_after>import std.sys;

fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
fn mul(uint x, uint y) -> uint { ret x * y; }
fn div(uint x, uint y) -> uint { ret x / y; }
fn rem(uint x, uint y) -> uint { ret x % y; }

fn lt(uint x, uint y) -> bool { ret x < y; }
fn le(uint x, uint y) -> bool { ret x <= y; }
fn eq(uint x, uint y) -> bool { ret x == y; }
fn ne(uint x, uint y) -> bool { ret x != y; }
fn ge(uint x, uint y) -> bool { ret x >= y; }
fn gt(uint x, uint y) -> bool { ret x > y; }

iter range(mutable uint lo, uint hi) -> uint {
  while (lo < hi) {
    put lo;
    lo += 1u;
  }
}

fn next_power_of_two(uint n) -> uint {
  // FIXME change |* uint(4)| below to |* uint(8) / uint(2)| and watch the
  // world explode.
  let uint halfbits = sys.rustrt.size_of[uint]() * 4u;
  let uint tmp = n - 1u;
  let uint shift = 1u;
  while (shift <= halfbits) {
    tmp |= tmp >> shift;
    shift <<= 1u;
  }
  ret tmp + 1u;
}

fn to_str(mutable uint n, uint radix) -> str
{
  check (0u < radix && radix <= 16u);
  fn digit(uint n) -> char {
    alt (n) {
      case (0u) { ret '0'; }
      case (1u) { ret '1'; }
      case (2u) { ret '2'; }
      case (3u) { ret '3'; }
      case (4u) { ret '4'; }
      case (5u) { ret '5'; }
      case (6u) { ret '6'; }
      case (7u) { ret '7'; }
      case (8u) { ret '8'; }
      case (9u) { ret '9'; }
      case (10u) { ret 'a'; }
      case (11u) { ret 'b'; }
      case (12u) { ret 'c'; }
      case (13u) { ret 'd'; }
      case (14u) { ret 'e'; }
      case (15u) { ret 'f'; }
    }
  }

  if (n == 0u) { ret "0"; }

  let uint r = 1u;
  if (n > r) {
    while ((r*radix) < n) {
      r *= radix;
    }
  }

  let str s = "";
  while (n > 0u) {

    auto i = n/r;

    n -= (i * r);
    r /= radix;

    s += digit(i) as u8;
  }

  while (r > 0u) {
    s += '0' as u8;
    r /= radix;
  }

  ret s;
}
<|endoftext|>