<commit_before>#![deny(warnings)]
extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::fs::FileType;
use std::path::Path;
use std::io::{stdout, StdoutLock, stderr, Stderr, Write};
use std::os::unix::fs::MetadataExt;
use std::process::exit;

use coreutils::{ArgParser, to_human_readable_string, format_system_time};
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{ls} */ r#"
NAME
    ls - list directory contents

SYNOPSIS
    ls [ -h | --help | -l ] [FILE]...

DESCRIPTION
    List information about the FILE(s), or the current directory

OPTIONS
    -a, --all
        do not ignore entries starting with .
    -h, --human-readable
        with -l, print human readable sizes
    --help
        display this help and exit
    -l
        use a long listing format
    -r, --reverse
        reverse order while sorting
    -R, --recursive
        list subdirectories recursively
    --mdate --modified-date
        display date of last modification
    --adate --accessed-date
        display date of last access
    --cdate --created-date
        display date of creation

"#; /* @MANEND */

fn mode_to_human_readable(file_type: &FileType, symlink_file_type: &FileType, mode: u32) -> String {

    let mut result = String::from("");
    if symlink_file_type.is_symlink() {
        result.push('l')
    } else if file_type.is_dir() {
        result.push('d');
    } else {
        result.push('-');
    }

    let mode_str = format!("{:>6o}", mode);
    let mode_chars = mode_str[3..].chars();
    for i in mode_chars {
        match i {
            '7' => result.push_str("rwx"),
            '6' => result.push_str("rw-"),
            '5' => result.push_str("r-x"),
            '4' => result.push_str("r--"),
            '3' => result.push_str("-wx"),
            '2' => result.push_str("-w-"),
            '1' => result.push_str("--x"),
            _ => result.push_str("---"),
        }
    }

    return result;
}

fn print_item(item_path: &str, parser: &ArgParser, stdout: &mut StdoutLock, stderr: &mut Stderr) {

    let mut link_error = "";
    let symlink_metadata = fs::symlink_metadata(&item_path).try(stderr);
    let metadata = match fs::metadata(&item_path) {
        Ok(metadata) => metadata,
        Err(_) => {
            link_error = "broken link";
            fs::symlink_metadata(&item_path).try(stderr)
        }
    };
    if parser.found("long-format") {
        stdout.write(&format!("{} {:>5} {:>5} ",
                              mode_to_human_readable(&(metadata.file_type()), &(symlink_metadata.file_type()), metadata.mode()),
                              metadata.uid(),
                              metadata.gid())
                              .as_bytes())
            .try(stderr);
        if parser.found("human-readable") {
            stdout.write(&format!("{:>6} ", to_human_readable_string(metadata.size())).as_bytes()).try(stderr);
        } else {
            stdout.write(&format!("{:>8} ", metadata.size()).as_bytes()).try(stderr);
        }
    }
    if parser.found("modified-date") || parser.found("long-format") {
        let mtime = match metadata.modified(){
            Ok(mtime) => format_system_time(mtime),
            Err(_) => "mdate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", mtime).as_bytes()).try(stderr);
    }
    if parser.found("accessed-date") {
        let atime = match metadata.accessed(){
            Ok(atime) => format_system_time(atime),
            Err(_) => "adate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", atime).as_bytes()).try(stderr);
    }
    if parser.found("created-date") {
        let ctime = match metadata.created(){
            Ok(ctime) => format_system_time(ctime),
            Err(_) => "cdate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", ctime).as_bytes()).try(stderr);
    }

    if item_path.starts_with("./") {
        stdout.write(&item_path[2..].as_bytes()).try(stderr);
    } else {
        stdout.write(item_path.as_bytes()).try(stderr);
    }
    if parser.found("long-format") && symlink_metadata.file_type().is_symlink() {
        let symlink_target = fs::read_link(item_path)
            .expect("can't read link")
            .into_os_string()
            .into_string()
            .expect("c'ant get path as string");
        stdout.write(&format!(" -> {}", symlink_target).as_bytes()).try(stderr);
        if !link_error.is_empty() {
            stdout.write(&format!(" ({})", link_error).as_bytes()).try(stderr);
        }
    }

    stdout.write("\n".as_bytes()).try(stderr);
    stdout.flush().try(stderr);
}

fn list_dir(path: &str, parser: &ArgParser, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut show_hidden = false;
    if parser.found("all") {
        show_hidden = true;
    }

    let metadata = fs::metadata(path).try(stderr);
    if metadata.is_dir() {
        let read_dir = Path::new(path).read_dir().try(stderr);

        let mut entries: Vec<String> = read_dir.filter_map(|x| x.ok())
            .map(|x| {
                     let file_name = x.file_name().to_string_lossy().into_owned();
                     file_name
                 })
            .filter(|x| match show_hidden {
                        true => true,
                        false => !x.starts_with("."),
                    })
            .collect();

        if parser.found("reverse") {
            entries.sort_by(|a, b| b.cmp(a));
        } else {
            entries.sort_by(|a, b| a.cmp(b));
        }

        for entry in entries.iter() {
            let mut entry_path = path.to_owned();
            if !entry_path.ends_with('/') {
                entry_path.push('/');
            }
            entry_path.push_str(&entry);
            print_item(&entry_path, &parser, stdout, stderr);
            if parser.found("recursive") && metadata.is_dir() {
                list_dir(&entry_path, parser, stdout, stderr);
            }
        }
    } else {
        print_item(&path, &parser, stdout, stderr);
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    let mut parser = ArgParser::new(6)
        .add_flag(&["a", "all"])
        .add_flag(&["l", "long-format"])
        .add_flag(&["h", "human-readable"])
        .add_flag(&["r", "reverse"])
        .add_flag(&["R", "recursive"])
        .add_flag(&["mdate", "modified-date"])
        .add_flag(&["adate", "accessed-date"])
        .add_flag(&["cdate", "created-date"])
        .add_flag(&["", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    if parser.args.is_empty() {
        list_dir(".", &parser, &mut stdout, &mut stderr);
    } else {
        for dir in parser.args.iter() {
            list_dir(&dir, &parser, &mut stdout, &mut stderr);
        }
    }
}

#[test]
fn test_human_readable() {
    assert_eq!(to_human_readable_string(0), "0");
    assert_eq!(to_human_readable_string(1023), "1023");
    assert_eq!(to_human_readable_string(1024), "1.0K");
    assert_eq!(to_human_readable_string(1024 + 100), "1.1K");
    assert_eq!(to_human_readable_string(1024u64.pow(2) * 2), "2.0M");
    assert_eq!(to_human_readable_string(1024u64.pow(3) * 3), "3.0G");
    assert_eq!(to_human_readable_string(1024u64.pow(4) * 4), "4.0T");
    assert_eq!(to_human_readable_string(1024u64.pow(5) * 5), "5.0P");
    assert_eq!(to_human_readable_string(1024u64.pow(6) * 6), "6.0E");
}

#[test]
fn test_format_system_time() {
    use std::ops::Add;
    use std::time::{SystemTime, Duration};
    let now = SystemTime::now();
    let future = SystemTime::now().add(Duration::from_secs(10));
    assert_ne!(format_system_time(now), format_system_time(future));
    // compare up to ten minutes: 2017-03-21 17:1_:__
    assert_eq!(format_system_time(now)[..15], format_system_time(future)[..15]);
}
<commit_msg>Fix error string typo<commit_after>#![deny(warnings)]
extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::fs::FileType;
use std::path::Path;
use std::io::{stdout, StdoutLock, stderr, Stderr, Write};
use std::os::unix::fs::MetadataExt;
use std::process::exit;

use coreutils::{ArgParser, to_human_readable_string, format_system_time};
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{ls} */ r#"
NAME
    ls - list directory contents

SYNOPSIS
    ls [ -h | --help | -l ] [FILE]...

DESCRIPTION
    List information about the FILE(s), or the current directory

OPTIONS
    -a, --all
        do not ignore entries starting with .
    -h, --human-readable
        with -l, print human readable sizes
    --help
        display this help and exit
    -l
        use a long listing format
    -r, --reverse
        reverse order while sorting
    -R, --recursive
        list subdirectories recursively
    --mdate --modified-date
        display date of last modification
    --adate --accessed-date
        display date of last access
    --cdate --created-date
        display date of creation

"#; /* @MANEND */

fn mode_to_human_readable(file_type: &FileType, symlink_file_type: &FileType, mode: u32) -> String {

    let mut result = String::from("");
    if symlink_file_type.is_symlink() {
        result.push('l')
    } else if file_type.is_dir() {
        result.push('d');
    } else {
        result.push('-');
    }

    let mode_str = format!("{:>6o}", mode);
    let mode_chars = mode_str[3..].chars();
    for i in mode_chars {
        match i {
            '7' => result.push_str("rwx"),
            '6' => result.push_str("rw-"),
            '5' => result.push_str("r-x"),
            '4' => result.push_str("r--"),
            '3' => result.push_str("-wx"),
            '2' => result.push_str("-w-"),
            '1' => result.push_str("--x"),
            _ => result.push_str("---"),
        }
    }

    return result;
}

fn print_item(item_path: &str, parser: &ArgParser, stdout: &mut StdoutLock, stderr: &mut Stderr) {

    let mut link_error = "";
    let symlink_metadata = fs::symlink_metadata(&item_path).try(stderr);
    let metadata = match fs::metadata(&item_path) {
        Ok(metadata) => metadata,
        Err(_) => {
            link_error = "broken link";
            fs::symlink_metadata(&item_path).try(stderr)
        }
    };
    if parser.found("long-format") {
        stdout.write(&format!("{} {:>5} {:>5} ",
                              mode_to_human_readable(&(metadata.file_type()), &(symlink_metadata.file_type()), metadata.mode()),
                              metadata.uid(),
                              metadata.gid())
                              .as_bytes())
            .try(stderr);
        if parser.found("human-readable") {
            stdout.write(&format!("{:>6} ", to_human_readable_string(metadata.size())).as_bytes()).try(stderr);
        } else {
            stdout.write(&format!("{:>8} ", metadata.size()).as_bytes()).try(stderr);
        }
    }
    if parser.found("modified-date") || parser.found("long-format") {
        let mtime = match metadata.modified(){
            Ok(mtime) => format_system_time(mtime),
            Err(_) => "mdate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", mtime).as_bytes()).try(stderr);
    }
    if parser.found("accessed-date") {
        let atime = match metadata.accessed(){
            Ok(atime) => format_system_time(atime),
            Err(_) => "adate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", atime).as_bytes()).try(stderr);
    }
    if parser.found("created-date") {
        let ctime = match metadata.created(){
            Ok(ctime) => format_system_time(ctime),
            Err(_) => "cdate err".to_string(),
        };
        stdout.write(&format!("{:>20} ", ctime).as_bytes()).try(stderr);
    }

    if item_path.starts_with("./") {
        stdout.write(&item_path[2..].as_bytes()).try(stderr);
    } else {
        stdout.write(item_path.as_bytes()).try(stderr);
    }
    if parser.found("long-format") && symlink_metadata.file_type().is_symlink() {
        let symlink_target = fs::read_link(item_path)
            .expect("can't read link")
            .into_os_string()
            .into_string()
            .expect("can't get path as string");
        stdout.write(&format!(" -> {}", symlink_target).as_bytes()).try(stderr);
        if !link_error.is_empty() {
            stdout.write(&format!(" ({})", link_error).as_bytes()).try(stderr);
        }
    }

    stdout.write("\n".as_bytes()).try(stderr);
    stdout.flush().try(stderr);
}

fn list_dir(path: &str, parser: &ArgParser, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut show_hidden = false;
    if parser.found("all") {
        show_hidden = true;
    }

    let metadata = fs::metadata(path).try(stderr);
    if metadata.is_dir() {
        let read_dir = Path::new(path).read_dir().try(stderr);

        let mut entries: Vec<String> = read_dir.filter_map(|x| x.ok())
            .map(|x| {
                     let file_name = x.file_name().to_string_lossy().into_owned();
                     file_name
                 })
            .filter(|x| match show_hidden {
                        true => true,
                        false => !x.starts_with("."),
                    })
            .collect();

        if parser.found("reverse") {
            entries.sort_by(|a, b| b.cmp(a));
        } else {
            entries.sort_by(|a, b| a.cmp(b));
        }

        for entry in entries.iter() {
            let mut entry_path = path.to_owned();
            if !entry_path.ends_with('/') {
                entry_path.push('/');
            }
            entry_path.push_str(&entry);
            print_item(&entry_path, &parser, stdout, stderr);
            if parser.found("recursive") && metadata.is_dir() {
                list_dir(&entry_path, parser, stdout, stderr);
            }
        }
    } else {
        print_item(&path, &parser, stdout, stderr);
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    let mut parser = ArgParser::new(6)
        .add_flag(&["a", "all"])
        .add_flag(&["l", "long-format"])
        .add_flag(&["h", "human-readable"])
        .add_flag(&["r", "reverse"])
        .add_flag(&["R", "recursive"])
        .add_flag(&["mdate", "modified-date"])
        .add_flag(&["adate", "accessed-date"])
        .add_flag(&["cdate", "created-date"])
        .add_flag(&["", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    if parser.args.is_empty() {
        list_dir(".", &parser, &mut stdout, &mut stderr);
    } else {
        for dir in parser.args.iter() {
            list_dir(&dir, &parser, &mut stdout, &mut stderr);
        }
    }
}

#[test]
fn test_human_readable() {
    assert_eq!(to_human_readable_string(0), "0");
    assert_eq!(to_human_readable_string(1023), "1023");
    assert_eq!(to_human_readable_string(1024), "1.0K");
    assert_eq!(to_human_readable_string(1024 + 100), "1.1K");
    assert_eq!(to_human_readable_string(1024u64.pow(2) * 2), "2.0M");
    assert_eq!(to_human_readable_string(1024u64.pow(3) * 3), "3.0G");
    assert_eq!(to_human_readable_string(1024u64.pow(4) * 4), "4.0T");
    assert_eq!(to_human_readable_string(1024u64.pow(5) * 5), "5.0P");
    assert_eq!(to_human_readable_string(1024u64.pow(6) * 6), "6.0E");
}

#[test]
fn test_format_system_time() {
    use std::ops::Add;
    use std::time::{SystemTime, Duration};
    let now = SystemTime::now();
    let future = SystemTime::now().add(Duration::from_secs(10));
    assert_ne!(format_system_time(now), format_system_time(future));
    // compare up to ten minutes: 2017-03-21 17:1_:__
    assert_eq!(format_system_time(now)[..15], format_system_time(future)[..15]);
}
<|endoftext|>


<commit_before>use std::mem::replace;

/**
(
a0,
a1,
a2,
...
),
⊗
 →
(
a0,
(a0 ⊗ a1),
((a0 ⊗ a1) ⊗ a2),
...
)

*/
pub trait AccumulateIterator<E>: Iterator<Item=E> + Sized {
    /**
Creates an iterator that scans from left to right over the input sequence, returning the accumulated result of calling the provided function on the entire sequence up to that point.

# Example

```
let v = vec![0us, 1, 2, 3, 4];

// `r` is the sequence of partial sums of `v`.
let r: Vec<_> = v.into_iter().accumulate(|a,b| a+b).collect();
assert_eq!(r, vec![0, 1, 3, 6, 10]);
```
    */
    fn accumulate<F: FnMut(E, E) -> E>(self, f: F) -> Accumulate<Self, E, F> {
        Accumulate {
            iter: self,
            f: f,
            accum: None,
        }
    }
}

impl<E, It> AccumulateIterator<E> for It where It: Iterator<Item=E> {}

#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Accumulate<It, E, F> where It: Iterator<Item=E> {
    iter: It,
    f: F,
    accum: Option<E>,
}

impl<It, E, F> Accumulate<It, E, F> where It: Iterator<Item=E> {
    /**
Unwraps the iterator, returning the underlying iterator.
    */
    pub fn unwrap(self) -> It {
        let Accumulate { iter, .. } = self;
        iter
    }
}

impl<It, E, F> Iterator for Accumulate<It, E, F> where It: Iterator<Item=E>, F: FnMut(E, E) -> E, E: Clone {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        match replace(&mut self.accum, None) {
            None => match self.iter.next() {
                None => None,
                e @ _ => {
                    self.accum = e;
                    self.accum.clone()
                }
            },
            Some(accum) => match self.iter.next() {
                None => {
                    self.accum = None;
                    None
                },
                Some(rhs) => {
                    self.accum = Some((self.f)(accum, rhs));
                    self.accum.clone()
                }
            }
        }
    }
}

#[test]
fn test_accumulate() {
    let v = vec![0us, 1, 2, 3, 4];
    let r: Vec<_> = v.into_iter().accumulate(|a,b| a+b).collect();
    assert_eq!(r, vec![0, 1, 3, 6, 10]);
}

#[test]
fn test_accumulate_unwrap() {
    let v = vec![0us, 1, 2, 3, 4];
    let mut i = v.into_iter().accumulate(|a,b| a+b);
    assert_eq!(i.next(), Some(0));
    assert_eq!(i.next(), Some(1));
    assert_eq!(i.next(), Some(3));
    let r: Vec<_> = i.unwrap().collect();
    assert_eq!(r, vec![3, 4]);
}
<commit_msg>Fixed failing example for accumulate.<commit_after>use std::mem::replace;

/**
(
a0,
a1,
a2,
...
),
⊗
 →
(
a0,
(a0 ⊗ a1),
((a0 ⊗ a1) ⊗ a2),
...
)

*/
pub trait AccumulateIterator<E>: Iterator<Item=E> + Sized {
    /**
Creates an iterator that scans from left to right over the input sequence, returning the accumulated result of calling the provided function on the entire sequence up to that point.

# Example

```
# extern crate grabbag;
# use grabbag::iter::AccumulateIterator;
# fn main() {
let v = vec![0us, 1, 2, 3, 4];

// `r` is the sequence of partial sums of `v`.
let r: Vec<_> = v.into_iter().accumulate(|a,b| a+b).collect();
assert_eq!(r, vec![0, 1, 3, 6, 10]);
# }
```
    */
    fn accumulate<F: FnMut(E, E) -> E>(self, f: F) -> Accumulate<Self, E, F> {
        Accumulate {
            iter: self,
            f: f,
            accum: None,
        }
    }
}

impl<E, It> AccumulateIterator<E> for It where It: Iterator<Item=E> {}

#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Accumulate<It, E, F> where It: Iterator<Item=E> {
    iter: It,
    f: F,
    accum: Option<E>,
}

impl<It, E, F> Accumulate<It, E, F> where It: Iterator<Item=E> {
    /**
Unwraps the iterator, returning the underlying iterator.
    */
    pub fn unwrap(self) -> It {
        let Accumulate { iter, .. } = self;
        iter
    }
}

impl<It, E, F> Iterator for Accumulate<It, E, F> where It: Iterator<Item=E>, F: FnMut(E, E) -> E, E: Clone {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        match replace(&mut self.accum, None) {
            None => match self.iter.next() {
                None => None,
                e @ _ => {
                    self.accum = e;
                    self.accum.clone()
                }
            },
            Some(accum) => match self.iter.next() {
                None => {
                    self.accum = None;
                    None
                },
                Some(rhs) => {
                    self.accum = Some((self.f)(accum, rhs));
                    self.accum.clone()
                }
            }
        }
    }
}

#[test]
fn test_accumulate() {
    let v = vec![0us, 1, 2, 3, 4];
    let r: Vec<_> = v.into_iter().accumulate(|a,b| a+b).collect();
    assert_eq!(r, vec![0, 1, 3, 6, 10]);
}

#[test]
fn test_accumulate_unwrap() {
    let v = vec![0us, 1, 2, 3, 4];
    let mut i = v.into_iter().accumulate(|a,b| a+b);
    assert_eq!(i.next(), Some(0));
    assert_eq!(i.next(), Some(1));
    assert_eq!(i.next(), Some(3));
    let r: Vec<_> = i.unwrap().collect();
    assert_eq!(r, vec![3, 4]);
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//! Validate UUIDs.
//! A UUID is an unique number of 128bit.  UUIDs are used to  assign
//! unique identifiers to entities.
//! Check against 3 formats specified by the RFC: https://tools.ietf.org/html/rfc4122.
//! * simple:       9856BAC1F9CBD6b9d80C712AF75C832A7
//! * hyphenated:   551e7604-e35c-42b3-b825-416853441234
//! * urn: urn:uuid:551e7604-e35c-42b3-b825-416853441234
use std::result;

#[derive(Debug, PartialEq)]
pub enum UUIDError {
    InvalidChar(char),
    InvalidGroupCount(usize),
    InvalidLength(usize),
    InvalidGroupLength(u8),
}

type Result<T> = result::Result<T, UUIDError>;

// Length of each of the 5 hyphen delimited groups from the RFC.
const GROUP_LENS: [u8; 5] = [8, 4, 4, 4, 12];
const HYPHEN_FORMAT_GROUP_COUNT: usize = 4;
const HYPHEN_FORMAT_LEN: usize = 36;
const SIMPLE_FORMAT_LEN: usize = 32;
const URN_FORMAT_PREFIX_LEN: usize = 9;

/// Validate a `Uuid` from a string of hexadecimal digits against three of the
/// supported formats.
pub fn validate(mut input: &str) -> Result<()> {
    // Check against correct length of each format.
    let len = input.len();
    if input.starts_with("urn:uuid:") && len == (HYPHEN_FORMAT_LEN + URN_FORMAT_PREFIX_LEN) {
        input = &input[9..];
    } else if len != SIMPLE_FORMAT_LEN && len != HYPHEN_FORMAT_LEN {
        return Err(UUIDError::InvalidLength(len));
    }

    // Used to count digits from each group.
    let mut group_index = 0;
    let mut group_count = 0;

    // Iterate over index and value of each byte of the input string.
    for (index, value) in input.bytes().enumerate() {
        // If length is bigger than that of the simple format, check that the
        // groups are exactly 4 at this moment.
        if index as usize >= SIMPLE_FORMAT_LEN && group_index != HYPHEN_FORMAT_GROUP_COUNT {
            return Err(UUIDError::InvalidGroupCount(group_index + 1));
        }
        // Never let the UUID get more than 5 groups.
        if group_index > HYPHEN_FORMAT_GROUP_COUNT {
            return Err(UUIDError::InvalidGroupCount(group_index + 1));
        }
        match value {
            b'0'...b'9' => group_count += 1,
            b'a'...b'f' => group_count += 1,
            b'A'...b'F' => group_count += 1,
            // With each hyphen we need to make sure that the
            // number of digits from the current group meets the RFC.
            b'-' => {
                if GROUP_LENS[group_index] != group_count {
                    return Err(UUIDError::InvalidGroupLength(group_count));
                }
                group_index += 1;
                group_count = 0;
            }
            _ => {
                return Err(UUIDError::InvalidChar(
                    input[index..].chars().next().unwrap_or('\0'),
                ))
            }
        }
    }
    if group_index > 0 && GROUP_LENS[group_index] != group_count {
        return Err(UUIDError::InvalidGroupLength(group_count));
    }
    Ok(())
}

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

        // Testing invalid uuids.
        assert_eq!(validate(""), Err(UUIDError::InvalidLength(0)));
        assert_eq!(validate("a"), Err(UUIDError::InvalidLength(1)));
        assert_eq!(
            validate("551e7604-CDB3-5fbb-C6ADD-338BD51DB2F5"),
            Err(UUIDError::InvalidLength(37))
        );
        assert_eq!(
            validate("551e7604-DFC3A5abbAC7CAA431CA48AB2F3"),
            Err(UUIDError::InvalidGroupCount(2))
        );
        assert_eq!(
            validate("551e7604-DFC3-DFC3A5abbAC7CAA431CA48"),
            Err(UUIDError::InvalidGroupCount(3))
        );
        assert_eq!(
            validate("551e7604-DFC3-DFC3X5AbbAC7CAA431CA48"),
            Err(UUIDError::InvalidChar('X'))
        );

        assert_eq!(
            validate("551e7604-DAF-35ab-fC7CAA43-CA48AB2F5"),
            Err(UUIDError::InvalidGroupLength(3))
        );
        assert_eq!(
            validate("01020304-1112-2122-3132-41424344"),
            Err(UUIDError::InvalidGroupLength(8))
        );
        assert_eq!(
            validate("67e5604510c1436%9257bca00e6fe1da"),
            Err(UUIDError::InvalidChar('%'))
        );
        assert_eq!(
            validate("342342323323534535435434587353276861"),
            Err(UUIDError::InvalidGroupCount(1))
        );

        // Testing valid ones also.
        assert!(validate("00000000000000000000000000000000").is_ok());
        assert!(validate("68f56045-20c2-437a-8257-bb781e5ae0c9").is_ok());
        assert!(validate("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
        assert!(validate("67e5504410b1426f9247bb680e5fe0c8").is_ok());
        assert!(validate("01020304-1112-2122-3132-414243444546").is_ok());
        assert!(validate("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());

        assert!(validate("00000000000000000000000000000000").is_ok());
        assert!(validate("00000000-0000-0000-0000-000000000000").is_ok());
    }
}
<commit_msg>jailer: removed uuid module<commit_after><|endoftext|>


<commit_before>extern crate anagram;

#[test]
fn test_no_matches() {
    let inputs = ["hello", "world", "zombies", "pants"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("diaper", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_simple_anagram() {
    let inputs = ["tan", "stand", "at"];
    let outputs: Vec<&str> = vec!["tan"];
    assert_eq!(anagram::anagrams_for("ant", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_confuse_different_duplicates() {
    let inputs = ["eagle"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("galea", &inputs), outputs);
}

#[test]
#[ignore]
fn test_eliminate_anagram_subsets() {
    let inputs = ["dog", "goody"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("good", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_anagram() {
    let inputs = ["enlists", "google", "inlets", "banana"];
    let outputs: Vec<&str> = vec!["inlets"];
    assert_eq!(anagram::anagrams_for("listen", &inputs), outputs);
}

#[test]
#[ignore]
fn test_multiple_anagrams() {
    let inputs = ["gallery", "ballerina", "regally", "clergy", "largely", "leading"];
    let outputs: Vec<&str> = vec!["gallery", "regally", "largely"];
    assert_eq!(anagram::anagrams_for("allergy", &inputs), outputs);
}

#[test]
#[ignore]
fn test_case_insensitive_anagrams() {
    let inputs = ["cashregister", "Carthorse", "radishes"];
    let outputs: Vec<&str> = vec!["Carthorse"];
    assert_eq!(anagram::anagrams_for("Orchestra", &inputs), outputs);
}

#[test]
#[ignore]
fn test_unicode_anagrams() {
    // These words don't make sense, they're just greek letters cobbled together.
    let inputs = ["ΒΓΑ", "ΒΓΔ", "γβα"];
    let outputs: Vec<&str> = vec!["ΒΓΑ", "γβα"];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_misleading_unicode_anagrams() {
    // Despite what a human might think these words different letters, the input uses Greek A and B
    // while the list of potential anagrams uses Latin A and B.
    let inputs = ["ABΓ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_word_as_its_own_anagram() {
    let inputs = ["banana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_word_as_its_own_anagram() {
    let inputs = ["bAnana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}
<commit_msg>Fixed false positive with test_multiple_anagrams<commit_after>extern crate anagram;

#[test]
fn test_no_matches() {
    let inputs = ["hello", "world", "zombies", "pants"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("diaper", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_simple_anagram() {
    let inputs = ["tan", "stand", "at"];
    let outputs: Vec<&str> = vec!["tan"];
    assert_eq!(anagram::anagrams_for("ant", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_confuse_different_duplicates() {
    let inputs = ["eagle"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("galea", &inputs), outputs);
}

#[test]
#[ignore]
fn test_eliminate_anagram_subsets() {
    let inputs = ["dog", "goody"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("good", &inputs), outputs);
}

#[test]
#[ignore]
fn test_detect_anagram() {
    let inputs = ["enlists", "google", "inlets", "banana"];
    let outputs: Vec<&str> = vec!["inlets"];
    assert_eq!(anagram::anagrams_for("listen", &inputs), outputs);
}

#[test]
#[ignore]
fn test_multiple_anagrams() {
    let inputs = ["gallery", "ballerina", "regally", "clergy", "largely", "leading"];
    let mut outputs: Vec<&str> = vec!["gallery", "regally", "largely"];
    outputs.sort();
    let mut result = anagram::anagrams_for("allergy", &inputs);
    result.sort();
    assert_eq!(result, outputs);
}

#[test]
#[ignore]
fn test_case_insensitive_anagrams() {
    let inputs = ["cashregister", "Carthorse", "radishes"];
    let outputs: Vec<&str> = vec!["Carthorse"];
    assert_eq!(anagram::anagrams_for("Orchestra", &inputs), outputs);
}

#[test]
#[ignore]
fn test_unicode_anagrams() {
    // These words don't make sense, they're just greek letters cobbled together.
    let inputs = ["ΒΓΑ", "ΒΓΔ", "γβα"];
    let outputs: Vec<&str> = vec!["ΒΓΑ", "γβα"];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_misleading_unicode_anagrams() {
    // Despite what a human might think these words different letters, the input uses Greek A and B
    // while the list of potential anagrams uses Latin A and B.
    let inputs = ["ABΓ"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("ΑΒΓ", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_word_as_its_own_anagram() {
    let inputs = ["banana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}

#[test]
#[ignore]
fn test_does_not_detect_a_differently_cased_word_as_its_own_anagram() {
    let inputs = ["bAnana"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagram::anagrams_for("banana", &inputs), outputs);
}
<|endoftext|>


<commit_before>use super::{CHUNK_SIZE, ChunkIndex, HexPillar, PillarIndexComponent};
use std::ops;
use math::*;
use std::iter::Iterator;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

pub struct ChunkPillars<'a> {
    pillars: &'a [HexPillar],
    i: u16,
}

impl<'a> Iterator for ChunkPillars<'a> {
    type Item = (AxialVector, &'a HexPillar);

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < CHUNK_SIZE * CHUNK_SIZE {
            let axial = AxialVector::new((self.i / CHUNK_SIZE).into(),
                                         (self.i % CHUNK_SIZE).into());
            let item = (axial, &self.pillars[self.i as usize]);
            self.i += 1;
            Some(item)
        } else {
            None
        }
    }
}

impl Chunk {
    /// Creates a chunk from a `Vec<HexPillar>`
    pub fn from_pillars(pillars: Vec<HexPillar>) -> Self {
        assert_eq!(pillars.len() as usize, CHUNK_SIZE.pow(2) as usize);

        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> ChunkPillars {
        ChunkPillars {
            pillars: &self.pillars,
            i: 0,
        }
    }

    /// Safer method to get through a chunk with an ìndex
    pub fn get(&self, pos: AxialPoint) -> Option<&HexPillar> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
        } else {
           None
        }
    }

    /// Calls the given closure with all pillar positions
    /// that are contained in a `Chunk`
    pub fn for_pillars_positions<F>(mut func: F)
        where F: FnMut(AxialPoint)
    {
        for q in 0..CHUNK_SIZE {
            for r in 0..CHUNK_SIZE {
                let pos = AxialPoint::new(q.into(), r.into());
                func(pos);
            }
        }
    }

    /// Creates a `Chunk` using individual pillars returned by a closure
    pub fn with_pillars<F>(chunk_index: ChunkIndex, mut func: F) -> Chunk
        where F: FnMut(AxialPoint) -> HexPillar
    {
        let mut hec = Vec::new();
        let start_q = CHUNK_SIZE as i32 * chunk_index.0.q;
        let start_r = CHUNK_SIZE as i32 * chunk_index.0.r;

        for q in start_q..start_q + CHUNK_SIZE as i32 {
            for r in start_r..start_r + CHUNK_SIZE as i32 {
                let pos = AxialPoint::new(q.into(), r.into());
                hec.push(func(pos));
            }
        }
        Chunk { pillars: hec }
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> &Self::Output {
        self.get(pos).unwrap_or_else(|| {
            panic!("Index out of Bounds length is: {} index was {:?}",
                   self.pillars.len(),
                   pos)
        })
    }
}
<commit_msg>fixed formatting<commit_after>use super::{CHUNK_SIZE, ChunkIndex, HexPillar, PillarIndexComponent};
use std::ops;
use math::*;
use std::iter::Iterator;

/// Represents one part of the game world.
///
/// A chunk saves `CHUNK_SIZE`² many hex pillars which are arranged rougly in
/// the form of a parallelogram. See [this blog post][1] for more information
/// (the shape is called "rhombus" there).
///
/// This type implements the `Index` trait and can be indexed with an
/// `AxialPoint`.
///
/// [1]: http://www.redblobgames.com/grids/hexagons/#map-storage
pub struct Chunk {
    /// All pillars are layed out in this one dimensional vector which saves
    /// all rows (same r-value) consecutive.
    pillars: Vec<HexPillar>,
}

pub struct ChunkPillars<'a> {
    pillars: &'a [HexPillar],
    i: u16,
}

impl<'a> Iterator for ChunkPillars<'a> {
    type Item = (AxialVector, &'a HexPillar);

    fn next(&mut self) -> Option<Self::Item> {
        if self.i < CHUNK_SIZE * CHUNK_SIZE {
            let axial = AxialVector::new((self.i / CHUNK_SIZE).into(),
                                         (self.i % CHUNK_SIZE).into());
            let item = (axial, &self.pillars[self.i as usize]);
            self.i += 1;
            Some(item)
        } else {
            None
        }
    }
}

impl Chunk {
    /// Creates a chunk from a `Vec<HexPillar>`
    pub fn from_pillars(pillars: Vec<HexPillar>) -> Self {
        assert_eq!(pillars.len() as usize, CHUNK_SIZE.pow(2) as usize);

        Chunk { pillars: pillars }
    }

    pub fn pillars(&self) -> ChunkPillars {
        ChunkPillars {
            pillars: &self.pillars,
            i: 0,
        }
    }

    /// Safer method to get through a chunk with an ìndex
    pub fn get(&self, pos: AxialPoint) -> Option<&HexPillar> {
        let chunk_size: PillarIndexComponent = CHUNK_SIZE.into();

        if pos.q >= 0 && pos.q < chunk_size && pos.r >= 0 && pos.r < chunk_size {
            Some(&self.pillars[(pos.r as usize) * (CHUNK_SIZE as usize) + (pos.q as usize)])
        } else {
            None
        }
    }

    /// Calls the given closure with all pillar positions
    /// that are contained in a `Chunk`
    pub fn for_pillars_positions<F>(mut func: F)
        where F: FnMut(AxialPoint)
    {
        for q in 0..CHUNK_SIZE {
            for r in 0..CHUNK_SIZE {
                let pos = AxialPoint::new(q.into(), r.into());
                func(pos);
            }
        }
    }

    /// Creates a `Chunk` using individual pillars returned by a closure
    pub fn with_pillars<F>(chunk_index: ChunkIndex, mut func: F) -> Chunk
        where F: FnMut(AxialPoint) -> HexPillar
    {
        let mut hec = Vec::new();
        let start_q = CHUNK_SIZE as i32 * chunk_index.0.q;
        let start_r = CHUNK_SIZE as i32 * chunk_index.0.r;

        for q in start_q..start_q + CHUNK_SIZE as i32 {
            for r in start_r..start_r + CHUNK_SIZE as i32 {
                let pos = AxialPoint::new(q.into(), r.into());
                hec.push(func(pos));
            }
        }
        Chunk { pillars: hec }
    }
}

impl ops::Index<AxialPoint> for Chunk {
    type Output = HexPillar;

    fn index(&self, pos: AxialPoint) -> &Self::Output {
        self.get(pos).unwrap_or_else(|| {
            panic!("Index out of Bounds length is: {} index was {:?}",
                   self.pillars.len(),
                   pos)
        })
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::borrow::Cow;
use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let vt = ValueTokenizer::new(original);
    vt.into_iter().map(|part|
        match part {
            ValuePart::Variable(ref name) => {
                match (*variables).get(&(*name).to_string()) {
                    Some(v) => v.to_owned(),
                    None => name.to_string(),
                }
            },
            ValuePart::String(ref s) => s.to_string(),
        }
    ).collect::<Vec<_>>().connect(" ")
}

#[derive(Debug, Clone, PartialEq)]
pub enum ValuePart<'a> {
    Variable(Cow<'a, str>),
    String(Cow<'a, str>),
}

impl<'a> fmt::Display for ValuePart<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let val = match self {
            &ValuePart::Variable(ref s) => s,
            &ValuePart::String(ref s) => s,
        };
        write!(f, "{}", val)
    }
}

fn isnt_space(c: u8) -> bool {
    c != b' '
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        if self.bytes[start] == b'$' {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::Variable(Borrowed(&self.value_str[start..i])))
        } else {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
        }
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Cow::Borrowed;
    use std::collections::HashMap;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variable() {
        let mut vt = ValueTokenizer::new("$foo");
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variables_and_string_parts() {
        let mut vt = ValueTokenizer::new("foo $bar baz $quux");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$bar"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"baz"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$quux"))), vt.next());
        assert_eq!(None, vt.next());
    }

    // evaluate tests =====================

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = evaluate("foo $bar baz $quux", &vars);
        assert_eq!("foo 4 baz 3px 10px", answer);
    }
}
<commit_msg>Parse numbers out of values<commit_after>use std::fmt;
use std::borrow::Cow;
use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let vt = ValueTokenizer::new(original);
    vt.into_iter().map(|part|
        match part {
            ValuePart::Variable(ref name) => {
                match (*variables).get(&(*name).to_string()) {
                    Some(v) => v.to_owned(),
                    None => name.to_string(),
                }
            },
            ValuePart::String(ref s) => s.to_string(),
            ValuePart::Number(n) => n.to_string(),
        }
    ).collect::<Vec<_>>().connect(" ")
}

#[derive(Debug, Clone, PartialEq)]
pub enum ValuePart<'a> {
    Variable(Cow<'a, str>),
    String(Cow<'a, str>),
    Number(f32),
}

impl<'a> fmt::Display for ValuePart<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let val = match self {
            &ValuePart::Variable(ref s) => s,
            &ValuePart::String(ref s) => s,
        };
        write!(f, "{}", val)
    }
}

fn isnt_space(c: u8) -> bool {
    c != b' '
}

fn is_number(c: u8) -> bool {
    let result = match c {
        b'0' ... b'9' | b'.' => true,
        _ => false,
    };
    result
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        if is_number(self.bytes[start]) {
            i += self.scan_while(&self.value_str[i..limit], is_number);
            self.offset = i + 1;
            Some(ValuePart::Number(self.value_str[start..i].parse().unwrap()))
        } else if self.bytes[start] == b'$' {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::Variable(Borrowed(&self.value_str[start..i])))
        } else {
            i += self.scan_while(&self.value_str[i..limit], isnt_space);
            self.offset = i + 1;
            Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
        }
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Cow::Borrowed;
    use std::collections::HashMap;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variable() {
        let mut vt = ValueTokenizer::new("$foo");
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variables_and_string_parts() {
        let mut vt = ValueTokenizer::new("foo $bar baz $quux");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$bar"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"baz"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$quux"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_number() {
        let mut vt = ValueTokenizer::new("3");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_two_numbers() {
        let mut vt = ValueTokenizer::new("3 8.9");
        assert_eq!(Some(ValuePart::Number(3.0)), vt.next());
        assert_eq!(Some(ValuePart::Number(8.9)), vt.next());
        assert_eq!(None, vt.next());
    }

    // evaluate tests =====================

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = evaluate("foo $bar baz $quux", &vars);
        assert_eq!("foo 4 baz 3px 10px", answer);
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::slice;
use buffer::ArrayBufferBinding;
use types::DataType;

pub trait VertexData: Copy {
    type Binder: VertexAttribBinder;

    fn build_attrib_binder() -> <Self::Binder as VertexAttribBinder>::Builder;
}

pub trait VertexAttribBinder {
    type Builder;

    fn bind(&self, gl_buffer: &ArrayBufferBinding);
}

pub trait VertexPrimitive {
    fn gl_type() -> DataType;
}

impl VertexPrimitive for i8 {
    fn gl_type() -> DataType { DataType::Byte }
}

impl VertexPrimitive for u8 {
    fn gl_type() -> DataType { DataType::UnsignedByte }
}

impl VertexPrimitive for i16 {
    fn gl_type() -> DataType { DataType::Short }
}

impl VertexPrimitive for u16 {
    fn gl_type() -> DataType { DataType::UnsignedShort }
}

impl VertexPrimitive for f32 {
    fn gl_type() -> DataType { DataType::Float }
}

pub trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

impl<T> VertexDatum for T where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 1] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

impl<T> VertexDatum for [T; 2] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 2 }
}

impl<T> VertexDatum for [T; 3] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 3 }
}

impl<T> VertexDatum for [T; 4] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 4 }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(mem::transmute(self), mem::size_of::<Self>())
        }
    }
}

impl<T> VertexBytes for [T] where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        let size = mem::size_of::<T>() * self.len();
        unsafe {
            slice::from_raw_parts(mem::transmute(&self[0]), size)
        }
    }
}

// TODO: Use a proper compiler intrinsic/macro (when available)
// see: https://github.com/rust-lang/rust/issues/24111
#[macro_export]
macro_rules! offset_of {
    ($T:ty, $field:ident) => {
        unsafe {
            use std::mem::{uninitialized, transmute};

            let obj : $T = uninitialized();
            let obj_ptr : *const u8 = transmute(&obj);
            let member_ptr : *const u8 = transmute(&obj.$field);

            (member_ptr as usize) - (obj_ptr as usize)
        }
    }
}

#[macro_use(offset_of)]
#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {$(
            #[allow(non_snake_case)]
            pub mod $name {
                #[repr(C)]
                #[derive(Debug, Clone, Copy)]
                pub struct $name {
                    $(pub $field_name: $field_type),*
                }

                impl $crate::VertexData for $name {
                    type Binder = Binder;

                    fn build_attrib_binder() -> BinderBuilder {
                        BinderBuilder::new()
                    }
                }

                #[allow(dead_code)]
                pub struct Binder {
                    $($field_name: $crate::ProgramAttrib),*
                }

                impl $crate::VertexAttribBinder for Binder {
                    type Builder = BinderBuilder;

                    fn bind(&self, gl_buffer: &$crate::ArrayBufferBinding) {
                        use std::mem;
                        use $crate::VertexDatum as Datum;

                        $({
                            let components =
                                <$field_type as Datum>::components();
                            let gl_type =
                              <$field_type as Datum>::gl_type();
                            let normalized =
                                <$field_type as Datum>::normalized();
                            let stride = mem::size_of::<$name>();
                            let offset = offset_of!($name, $field_name);

                            unsafe {
                                gl_buffer.vertex_attrib_pointer(
                                    self.$field_name,
                                    components,
                                    gl_type,
                                    normalized,
                                    stride,
                                    offset);
                            }
                        };)*
                    }
                }

                #[allow(dead_code)]
                pub struct BinderBuilder {
                    $($field_name: Option<$crate::ProgramAttrib>),*
                }

                #[allow(dead_code)]
                impl BinderBuilder {
                    pub fn new() -> Self {
                        BinderBuilder {
                            $($field_name: None),*
                        }
                    }

                    pub fn unwrap(self, gl: &$crate::Context) -> self::Binder {
                        let binder = self::Binder {
                            $($field_name: self.$field_name.expect(
                                concat!("No attribute provided for ",
                                        stringify!($field_name))
                            )),*
                        };

                        $(gl.enable_vertex_attrib_array(binder.$field_name);)*

                        binder
                    }

                    $(
                        pub fn $field_name(mut self,
                                           attrib: $crate::ProgramAttrib)
                        -> Self
                        {
                            self.$field_name = Some(attrib);
                            self
                        }
                    )*
                }
            })+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<commit_msg>Mark `VertexPrimitive` and `VertexDatum` traits/impls as unsafe<commit_after>use std::mem;
use std::slice;
use buffer::ArrayBufferBinding;
use types::DataType;

pub unsafe trait VertexData: Copy {
    type Binder: VertexAttribBinder;

    fn build_attrib_binder() -> <Self::Binder as VertexAttribBinder>::Builder;
}

pub trait VertexAttribBinder {
    type Builder;

    fn bind(&self, gl_buffer: &ArrayBufferBinding);
}

pub unsafe trait VertexPrimitive {
    fn gl_type() -> DataType;
}

unsafe impl VertexPrimitive for i8 {
    fn gl_type() -> DataType { DataType::Byte }
}

unsafe impl VertexPrimitive for u8 {
    fn gl_type() -> DataType { DataType::UnsignedByte }
}

unsafe impl VertexPrimitive for i16 {
    fn gl_type() -> DataType { DataType::Short }
}

unsafe impl VertexPrimitive for u16 {
    fn gl_type() -> DataType { DataType::UnsignedShort }
}

unsafe impl VertexPrimitive for f32 {
    fn gl_type() -> DataType { DataType::Float }
}

pub unsafe trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

unsafe impl<T> VertexDatum for T where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

unsafe impl<T> VertexDatum for [T; 1] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 1 }
}

unsafe impl<T> VertexDatum for [T; 2] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 2 }
}

unsafe impl<T> VertexDatum for [T; 3] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 3 }
}

unsafe impl<T> VertexDatum for [T; 4] where T: VertexPrimitive {
    fn gl_type() -> DataType { <T as VertexPrimitive>::gl_type() }
    fn components() -> i8 { 4 }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(mem::transmute(self), mem::size_of::<Self>())
        }
    }
}

impl<T> VertexBytes for [T] where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        let size = mem::size_of::<T>() * self.len();
        unsafe {
            slice::from_raw_parts(mem::transmute(&self[0]), size)
        }
    }
}

// TODO: Use a proper compiler intrinsic/macro (when available)
// see: https://github.com/rust-lang/rust/issues/24111
#[macro_export]
macro_rules! offset_of {
    ($T:ty, $field:ident) => {
        unsafe {
            use std::mem::{uninitialized, transmute};

            let obj : $T = uninitialized();
            let obj_ptr : *const u8 = transmute(&obj);
            let member_ptr : *const u8 = transmute(&obj.$field);

            (member_ptr as usize) - (obj_ptr as usize)
        }
    }
}

#[macro_use(offset_of)]
#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {$(
            #[allow(non_snake_case)]
            pub mod $name {
                #[repr(C)]
                #[derive(Debug, Clone, Copy)]
                pub struct $name {
                    $(pub $field_name: $field_type),*
                }

                unsafe impl $crate::VertexData for $name {
                    type Binder = Binder;

                    fn build_attrib_binder() -> BinderBuilder {
                        BinderBuilder::new()
                    }
                }

                #[allow(dead_code)]
                pub struct Binder {
                    $($field_name: $crate::ProgramAttrib),*
                }

                impl $crate::VertexAttribBinder for Binder {
                    type Builder = BinderBuilder;

                    fn bind(&self, gl_buffer: &$crate::ArrayBufferBinding) {
                        use std::mem;
                        use $crate::VertexDatum as Datum;

                        $({
                            let components =
                                <$field_type as Datum>::components();
                            let gl_type =
                              <$field_type as Datum>::gl_type();
                            let normalized =
                                <$field_type as Datum>::normalized();
                            let stride = mem::size_of::<$name>();
                            let offset = offset_of!($name, $field_name);

                            unsafe {
                                gl_buffer.vertex_attrib_pointer(
                                    self.$field_name,
                                    components,
                                    gl_type,
                                    normalized,
                                    stride,
                                    offset);
                            }
                        };)*
                    }
                }

                #[allow(dead_code)]
                pub struct BinderBuilder {
                    $($field_name: Option<$crate::ProgramAttrib>),*
                }

                #[allow(dead_code)]
                impl BinderBuilder {
                    pub fn new() -> Self {
                        BinderBuilder {
                            $($field_name: None),*
                        }
                    }

                    pub fn unwrap(self, gl: &$crate::Context) -> self::Binder {
                        let binder = self::Binder {
                            $($field_name: self.$field_name.expect(
                                concat!("No attribute provided for ",
                                        stringify!($field_name))
                            )),*
                        };

                        $(gl.enable_vertex_attrib_array(binder.$field_name);)*

                        binder
                    }

                    $(
                        pub fn $field_name(mut self,
                                           attrib: $crate::ProgramAttrib)
                        -> Self
                        {
                            self.$field_name = Some(attrib);
                            self
                        }
                    )*
                }
            })+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<|endoftext|>


<commit_before>use addressable::Addressable;
use addressable::AddressableUtil;
use memory::Memory;

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

struct Registers {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
}

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &Mos6502) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.reg.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.reg.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.reg.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.reg.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.reg.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.reg.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.reg.y as u16 },
		}
	}

	fn get (&self, cpu: &Mos6502) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.reg.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, cpu: &mut Mos6502, val: u8) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.reg.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

pub struct Mos6502<'self> {
	priv reg: Registers,					// internal CPU registers
	priv mem: &'self Memory<'self, u16>,	// memory as accessible to the CPU
}

impl<'self> Mos6502<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6502<'self> {
		Mos6502 {
			reg: Registers { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 },
			mem: mem,
		}
	}
}

impl<'self> Addressable<u16> for Mos6502<'self> {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

pub struct Mos6510<'self> {
	priv cpu: Mos6502<'self>,				// Core CPU
	priv port_ddr: u8,						// CPU port data direction register
	priv port_dat: u8,						// CPU port data register
}

impl<'self> Mos6510<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6510<'self> {
		Mos6510 { cpu: Mos6502::new(mem), port_ddr: 0, port_dat: 0 }
	}
}
<commit_msg>Removed implementation of addressable trait from CPU<commit_after>use memory::Memory;

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

struct Registers {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
}

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &Mos6502) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.reg.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.reg.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.reg.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.reg.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.reg.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.reg.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.reg.y as u16 },
		}
	}

	fn get (&self, cpu: &Mos6502) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.reg.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, cpu: &mut Mos6502, val: u8) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.reg.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

pub struct Mos6502<'self> {
	priv reg: Registers,					// internal CPU registers
	priv mem: &'self Memory<'self, u16>,	// memory as accessible to the CPU
}

impl<'self> Mos6502<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6502<'self> {
		Mos6502 {
			reg: Registers { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 },
			mem: mem,
		}
	}
}

pub struct Mos6510<'self> {
	priv cpu: Mos6502<'self>,				// Core CPU
	priv port_ddr: u8,						// CPU port data direction register
	priv port_dat: u8,						// CPU port data register
}

impl<'self> Mos6510<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6510<'self> {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		Mos6510 { cpu: Mos6502::new(mem), port_ddr: 0, port_dat: 0 }
	}
}
<|endoftext|>


<commit_before>#![feature(allocator_api)]
#![feature(const_fn)]
#![feature(integer_atomics)]
#![forbid(private_in_public)]
#![forbid(bare_trait_objects)]
#![deny(unused_assignments)]
#![no_std]

extern crate spin;

use core::alloc::{Alloc, AllocErr, GlobalAlloc, Layout};
use core::ptr::NonNull;

pub const HEAP_START: u64 = 0x40_000_000; // At 1 GiB
pub const HEAP_SIZE: u64 = 0x1_000_000;

use spin::Mutex;

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: u64, align: u64) -> u64 {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: u64, align: u64) -> u64 {
    align_down(addr + align - 1, align)
}

use core::sync::atomic::{AtomicU64, Ordering};

/// A simple allocator that allocates memory linearly and ignores freed memory.
#[derive(Debug)]
pub struct BumpAllocator {
    heap_start: u64,
    heap_end: u64,
    next: AtomicU64,
}

impl BumpAllocator {
    pub const fn new(heap_start: u64, heap_end: u64) -> Self {
        Self {
            heap_start,
            heap_end,
            next: AtomicU64::new(heap_start),
        }
    }
}

unsafe impl<'a> Alloc for &'a BumpAllocator {
    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
        loop {
            // load current state of the `next` field
            let current_next = self.next.load(Ordering::Relaxed);
            let alloc_start = align_up(current_next, layout.align() as u64);
            let alloc_end = alloc_start.saturating_add(layout.size() as u64);

            if alloc_end <= self.heap_end {
                // update the `next` pointer if it still has the value `current_next`
                let next_now =
                    self.next
                        .compare_and_swap(current_next, alloc_end, Ordering::Relaxed);
                if next_now == current_next {
                    // next address was successfully updated, allocation succeeded
                    return Ok(
                        NonNull::new(alloc_start as *mut _).expect("Tried to alloc null ptr")
                    );
                }
            } else {
                return Err(AllocErr);
            }
        }
    }

    unsafe fn dealloc(&mut self, _ptr: NonNull<u8>, _layout: Layout) {
        // do nothing, leak memory
    }
}

pub struct GlobAlloc {
    alloc: Mutex<BumpAllocator>,
}
impl GlobAlloc {
    pub const fn new(alloc: BumpAllocator) -> Self {
        Self {
            alloc: Mutex::new(alloc),
        }
    }
}
unsafe impl GlobalAlloc for GlobAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let alloc = self.alloc.lock();
        (&*alloc)
            .alloc(layout)
            .expect("Could not allocate")
            .as_mut()
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        let alloc = self.alloc.lock();
        (&*alloc).dealloc(
            NonNull::new(ptr as *mut _).expect("Cannot deallocate null pointer"),
            layout,
        );
    }
}
<commit_msg>Increase heap size<commit_after>#![feature(allocator_api)]
#![feature(const_fn)]
#![feature(integer_atomics)]
#![forbid(private_in_public)]
#![forbid(bare_trait_objects)]
#![deny(unused_assignments)]
#![no_std]

extern crate spin;

use core::alloc::{Alloc, AllocErr, GlobalAlloc, Layout};
use core::ptr::NonNull;

pub const HEAP_START: u64 = 0x4000_0000; // At 1 GiB
pub const HEAP_SIZE: u64 = 0x640_0000; // 100 MiB heap

use spin::Mutex;

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: u64, align: u64) -> u64 {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: u64, align: u64) -> u64 {
    align_down(addr + align - 1, align)
}

use core::sync::atomic::{AtomicU64, Ordering};

/// A simple allocator that allocates memory linearly and ignores freed memory.
#[derive(Debug)]
pub struct BumpAllocator {
    heap_start: u64,
    heap_end: u64,
    next: AtomicU64,
}

impl BumpAllocator {
    pub const fn new(heap_start: u64, heap_end: u64) -> Self {
        Self {
            heap_start,
            heap_end,
            next: AtomicU64::new(heap_start),
        }
    }
}

unsafe impl<'a> Alloc for &'a BumpAllocator {
    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
        loop {
            // load current state of the `next` field
            let current_next = self.next.load(Ordering::Relaxed);
            let alloc_start = align_up(current_next, layout.align() as u64);
            let alloc_end = alloc_start.saturating_add(layout.size() as u64);

            if alloc_end <= self.heap_end {
                // update the `next` pointer if it still has the value `current_next`
                let next_now =
                    self.next
                        .compare_and_swap(current_next, alloc_end, Ordering::Relaxed);
                if next_now == current_next {
                    // next address was successfully updated, allocation succeeded
                    return Ok(
                        NonNull::new(alloc_start as *mut _).expect("Tried to alloc null ptr")
                    );
                }
            } else {
                return Err(AllocErr);
            }
        }
    }

    unsafe fn dealloc(&mut self, _ptr: NonNull<u8>, _layout: Layout) {
        // do nothing, leak memory
    }
}

pub struct GlobAlloc {
    alloc: Mutex<BumpAllocator>,
}
impl GlobAlloc {
    pub const fn new(alloc: BumpAllocator) -> Self {
        Self {
            alloc: Mutex::new(alloc),
        }
    }
}
unsafe impl GlobalAlloc for GlobAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let alloc = self.alloc.lock();
        (&*alloc)
            .alloc(layout)
            .expect("Could not allocate")
            .as_mut()
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        let alloc = self.alloc.lock();
        (&*alloc).dealloc(
            NonNull::new(ptr as *mut _).expect("Cannot deallocate null pointer"),
            layout,
        );
    }
}
<|endoftext|>


<commit_before>fn main() {
    build::main();
}

#[cfg(feature = "bundled")]
mod build {
    extern crate cc;
    use std::{env, fs};
    use std::path::Path;

    pub fn main() {
        if cfg!(feature = "sqlcipher") {
            panic!("Builds with bundled SQLCipher are not supported");
        }

        let mut in_dir = "sqlite3";
        let out_dir = env::var("OUT_DIR").unwrap();
        let out_path = Path::new(&out_dir).join("bindgen.rs");

        if cfg!(feature = "bundled_sqlcipher") {
            in_dir = "sqlcipher";
        }

        fs::copy(Path::new(&in_dir).join("bindgen_bundled_version.rs"), out_path)
            .expect("Could not copy bindings to output directory");

        let mut compiler = gcc::Config::new();

        compiler.flag("-DSQLITE_CORE")
            .flag("-DSQLITE_DEFAULT_FOREIGN_KEYS=1")
            .flag("-DSQLITE_ENABLE_API_ARMOR")
            .flag("-DSQLITE_ENABLE_COLUMN_METADATA")
            .flag("-DSQLITE_ENABLE_DBSTAT_VTAB")
            .flag("-DSQLITE_ENABLE_FTS3")
            .flag("-DSQLITE_ENABLE_FTS3_PARENTHESIS")
            .flag("-DSQLITE_ENABLE_FTS5")
            .flag("-DSQLITE_ENABLE_JSON1")
            .flag("-DSQLITE_ENABLE_LOAD_EXTENSION=1")
            .flag("-DSQLITE_ENABLE_MEMORY_MANAGEMENT")
            .flag("-DSQLITE_ENABLE_RTREE")
            .flag("-DSQLITE_ENABLE_STAT2")
            .flag("-DSQLITE_ENABLE_STAT4")
            .flag("-DSQLITE_HAVE_ISNAN")
            .flag("-DSQLITE_SOUNDEX")
            .flag("-DSQLITE_THREADSAFE=1")
            .flag("-DSQLITE_USE_URI")
            .flag("-DHAVE_USLEEP=1");

        if cfg!(feature = "bundled_sqlcipher") {
            compiler.file("sqlcipher/sqlite3.c")
                .flag("-DSQLITE_HAS_CODEC")
                .flag("-DSQLITE_TEMP_STORE=2");

            // Default to CommonCrypto on Apple systems unless the "openssl" feature is explicitly
            // given.
            if (cfg!(target_os = "macos") || cfg!(target_os = "ios")) && ! cfg!(feature = "openssl") {
                compiler.flag("-DSQLCIPHER_CRYPTO_CC");
                println!("cargo:rustc-link-lib=framework=CoreFoundation");
                println!("cargo:rustc-link-lib=framework=Security");

            } else if cfg!(feature = "tomcrypt") {
                compiler.flag("-DSQLCIPHER_CRYPTO_LIBTOMCRYPT");
                println!("cargo:rustc-link-lib=tomcrypt");

            } else {
                compiler.flag("-DSQLCIPHER_CRYPTO_OPENSSL");
                println!("cargo:rustc-link-lib=crypto");

                if let Ok(header) = env::var("OPENSSL_ROOT_DIR") {
                    let ssl_root = Path::new(&header);
                    compiler.flag(&format!("{}{}", "-I", ssl_root.join("include").to_str().unwrap()));
                    println!("cargo:rustc-link-search={}", ssl_root.join("lib").to_str().unwrap());
                }
            }
        } else {
            compiler.file("sqlite3/sqlite3.c");
        }

        compiler.compile("libsqlite3.a");
    }
}

#[cfg(not(feature = "bundled"))]
mod build {
    extern crate pkg_config;

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    extern crate vcpkg;

    use std::env;

    pub enum HeaderLocation {
        FromEnvironment,
        Wrapper,
        FromPath(String),
    }

    impl From<HeaderLocation> for String {
        fn from(header: HeaderLocation) -> String {
            match header {
                HeaderLocation::FromEnvironment => {
                    let prefix = env_prefix();
                    let mut header = env::var(format!("{}_INCLUDE_DIR", prefix))
                        .expect(&format!("{}_INCLUDE_DIR must be set if {}_LIB_DIR is set", prefix, prefix));
                    header.push_str("/sqlite3.h");
                    header
                }
                HeaderLocation::Wrapper => "wrapper.h".into(),
                HeaderLocation::FromPath(path) => path,
            }
        }
    }

    pub fn main() {
        let header = find_sqlite();
        bindings::write_to_out_dir(header);
    }

    // Prints the necessary cargo link commands and returns the path to the header.
    fn find_sqlite() -> HeaderLocation {
        let link_lib = link_lib();

        // Allow users to specify where to find SQLite.
        if let Ok(dir) = env::var(format!("{}_LIB_DIR", env_prefix())) {
            println!("cargo:rustc-link-lib={}", link_lib);
            println!("cargo:rustc-link-search={}", dir);
            return HeaderLocation::FromEnvironment;
        }

        if let Some(header) = try_vcpkg() {
            return header;
        }

        // See if pkg-config can do everything for us.
        match pkg_config::Config::new().print_system_libs(false).probe(link_lib) {
            Ok(mut lib) => {
                if let Some(mut header) = lib.include_paths.pop() {
                    header.push("sqlite3.h");
                    HeaderLocation::FromPath(header.to_string_lossy().into())
                } else {
                    HeaderLocation::Wrapper
                }
            }
            Err(_) => {
                // No env var set and pkg-config couldn't help; just output the link-lib
                // request and hope that the library exists on the system paths. We used to
                // output /usr/lib explicitly, but that can introduce other linking problems; see
                // https://github.com/jgallagher/rusqlite/issues/207.
                println!("cargo:rustc-link-lib={}", link_lib);
                HeaderLocation::Wrapper
            }
        }
    }

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        // See if vcpkg can find it.
        if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) {
            if let Some(mut header) = lib.include_paths.pop() {
                header.push("sqlite3.h");
                return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
            }
        }
        None
    }

    #[cfg(not(all(feature = "vcpkg", target_env = "msvc")))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        None
    }

    fn env_prefix() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "SQLCIPHER"
        } else {
            "SQLITE3"
        }
    }

    fn link_lib() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "sqlcipher"
        } else {
            "sqlite3"
        }
    }

    #[cfg(not(feature = "buildtime_bindgen"))]
    mod bindings {
        use super::HeaderLocation;

        use std::{env, fs};
        use std::path::Path;

        #[cfg_attr(rustfmt, rustfmt_skip)]
        static PREBUILT_BINDGEN_PATHS: &'static [&'static str] = &[
            "bindgen-bindings/bindgen_3.6.8.rs",

            #[cfg(feature = "min_sqlite_version_3_6_11")]
            "bindgen-bindings/bindgen_3.6.11.rs",

            #[cfg(feature = "min_sqlite_version_3_6_23")]
            "bindgen-bindings/bindgen_3.6.23.rs",

            #[cfg(feature = "min_sqlite_version_3_7_3")]
            "bindgen-bindings/bindgen_3.7.3.rs",

            #[cfg(feature = "min_sqlite_version_3_7_4")]
            "bindgen-bindings/bindgen_3.7.4.rs",

            #[cfg(feature = "min_sqlite_version_3_7_16")]
            "bindgen-bindings/bindgen_3.7.16.rs",
        ];

        pub fn write_to_out_dir(_header: HeaderLocation) {
            let out_dir = env::var("OUT_DIR").unwrap();
            let out_path = Path::new(&out_dir).join("bindgen.rs");
            let in_path = PREBUILT_BINDGEN_PATHS[PREBUILT_BINDGEN_PATHS.len() - 1];
            fs::copy(in_path, out_path).expect("Could not copy bindings to output directory");
        }
    }

    #[cfg(feature = "buildtime_bindgen")]
    mod bindings {
        extern crate bindgen;

        use self::bindgen::callbacks::{ParseCallbacks, IntKind};
        use super::HeaderLocation;

        use std::env;
        use std::io::Write;
        use std::fs::OpenOptions;
        use std::path::Path;

        #[derive(Debug)]
        struct SqliteTypeChooser;

        impl ParseCallbacks for SqliteTypeChooser {
            fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
                if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
                    Some(IntKind::I32)
                } else {
                    None
                }
            }
        }

        pub fn write_to_out_dir(header: HeaderLocation) {
            let header: String = header.into();
            let out_dir = env::var("OUT_DIR").unwrap();
            let mut output = Vec::new();
            bindgen::builder()
                .header(header.clone())
                .parse_callbacks(Box::new(SqliteTypeChooser))
                .generate()
                .expect(&format!("could not run bindgen on header {}", header))
                .write(Box::new(&mut output))
                .expect("could not write output of bindgen");
            let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");

            // rusqlite's functions feature ors in the SQLITE_DETERMINISTIC flag when it can. This flag
            // was added in SQLite 3.8.3, but oring it in in prior versions of SQLite is harmless. We
            // don't want to not build just because this flag is missing (e.g., if we're linking against
            // SQLite 3.7.x), so append the flag manually if it isn't present in bindgen's output.
            if !output.contains("pub const SQLITE_DETERMINISTIC") {
                output.push_str("\npub const SQLITE_DETERMINISTIC: i32 = 2048;\n");
            }

            let path = Path::new(&out_dir).join("bindgen.rs");

            let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(path.clone())
                .expect(&format!("Could not write to {:?}", path));

            file.write_all(output.as_bytes()).expect(&format!("Could not write to {:?}", path));
        }
    }
}
<commit_msg>feat: Support sqlcipher for windows<commit_after>fn main() {
    build::main();
}

#[cfg(feature = "bundled")]
mod build {
    extern crate cc;
    use std::{env, fs};
    use std::path::Path;

    pub fn main() {
        if cfg!(feature = "sqlcipher") {
            panic!("Builds with bundled SQLCipher are not supported");
        }

        let mut in_dir = "sqlite3";
        let out_dir = env::var("OUT_DIR").unwrap();
        let out_path = Path::new(&out_dir).join("bindgen.rs");

        if cfg!(feature = "bundled_sqlcipher") {
            in_dir = "sqlcipher";
        }

        fs::copy(Path::new(&in_dir).join("bindgen_bundled_version.rs"), out_path)
            .expect("Could not copy bindings to output directory");

        let mut compiler = gcc::Config::new();

        compiler.flag("-DSQLITE_CORE")
            .flag("-DSQLITE_DEFAULT_FOREIGN_KEYS=1")
            .flag("-DSQLITE_ENABLE_API_ARMOR")
            .flag("-DSQLITE_ENABLE_COLUMN_METADATA")
            .flag("-DSQLITE_ENABLE_DBSTAT_VTAB")
            .flag("-DSQLITE_ENABLE_FTS3")
            .flag("-DSQLITE_ENABLE_FTS3_PARENTHESIS")
            .flag("-DSQLITE_ENABLE_FTS5")
            .flag("-DSQLITE_ENABLE_JSON1")
            .flag("-DSQLITE_ENABLE_LOAD_EXTENSION=1")
            .flag("-DSQLITE_ENABLE_MEMORY_MANAGEMENT")
            .flag("-DSQLITE_ENABLE_RTREE")
            .flag("-DSQLITE_ENABLE_STAT2")
            .flag("-DSQLITE_ENABLE_STAT4")
            .flag("-DSQLITE_HAVE_ISNAN")
            .flag("-DSQLITE_SOUNDEX")
            .flag("-DSQLITE_THREADSAFE=1")
            .flag("-DSQLITE_USE_URI")
            .flag("-DHAVE_USLEEP=1");

        if cfg!(feature = "bundled_sqlcipher") {
            compiler.file("sqlcipher/sqlite3.c")
                .flag("-DSQLITE_HAS_CODEC")
                .flag("-DSQLITE_TEMP_STORE=2");

            let target = env::var("TARGET").unwrap();

            // Default to CommonCrypto on Apple systems unless the "openssl" feature is explicitly
            // given.
            if target.contains("apple") && !cfg!(feature = "openssl") {
                compiler.flag("-DSQLCIPHER_CRYPTO_CC");
                println!("cargo:rustc-link-lib=framework=CoreFoundation");
                println!("cargo:rustc-link-lib=framework=Security");
            } else if cfg!(feature = "tomcrypt") {
                compiler.flag("-DSQLCIPHER_CRYPTO_LIBTOMCRYPT");
                println!("cargo:rustc-link-lib=tomcrypt");
            } else {
                compiler.flag("-DSQLCIPHER_CRYPTO_OPENSSL");

                if let Some(header) = env::var_os("OPENSSL_DIR") {
                    let ssl_root = Path::new(&header);
                    compiler.flag(&format!("{}{}", "-I", ssl_root.join("include").to_str().unwrap()));
                    println!("cargo:rustc-link-search={}", ssl_root.join("lib").to_str().unwrap());
                    if target.contains("windows") {
                        println!("cargo:rustc-link-lib={}={}", "static", "ssl");
                        println!("cargo:rustc-link-lib={}={}", "static", "crypto");
                        println!("cargo:rustc-link-lib={}={}", "dylib", "gdi32");
                    } else {
                        println!("cargo:rustc-link-lib=crypto");
                        println!("cargo:rustc-link-lib=ssl");
                    }
                }
            }
        } else {
            compiler.file("sqlite3/sqlite3.c");
        }

        compiler.compile("libsqlite3.a");
    }
}

#[cfg(not(feature = "bundled"))]
mod build {
    extern crate pkg_config;

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    extern crate vcpkg;

    use std::env;

    pub enum HeaderLocation {
        FromEnvironment,
        Wrapper,
        FromPath(String),
    }

    impl From<HeaderLocation> for String {
        fn from(header: HeaderLocation) -> String {
            match header {
                HeaderLocation::FromEnvironment => {
                    let prefix = env_prefix();
                    let mut header = env::var(format!("{}_INCLUDE_DIR", prefix))
                        .expect(&format!("{}_INCLUDE_DIR must be set if {}_LIB_DIR is set", prefix, prefix));
                    header.push_str("/sqlite3.h");
                    header
                }
                HeaderLocation::Wrapper => "wrapper.h".into(),
                HeaderLocation::FromPath(path) => path,
            }
        }
    }

    pub fn main() {
        let header = find_sqlite();
        bindings::write_to_out_dir(header);
    }

    // Prints the necessary cargo link commands and returns the path to the header.
    fn find_sqlite() -> HeaderLocation {
        let link_lib = link_lib();

        // Allow users to specify where to find SQLite.
        if let Ok(dir) = env::var(format!("{}_LIB_DIR", env_prefix())) {
            println!("cargo:rustc-link-lib={}", link_lib);
            println!("cargo:rustc-link-search={}", dir);
            return HeaderLocation::FromEnvironment;
        }

        if let Some(header) = try_vcpkg() {
            return header;
        }

        // See if pkg-config can do everything for us.
        match pkg_config::Config::new().print_system_libs(false).probe(link_lib) {
            Ok(mut lib) => {
                if let Some(mut header) = lib.include_paths.pop() {
                    header.push("sqlite3.h");
                    HeaderLocation::FromPath(header.to_string_lossy().into())
                } else {
                    HeaderLocation::Wrapper
                }
            }
            Err(_) => {
                // No env var set and pkg-config couldn't help; just output the link-lib
                // request and hope that the library exists on the system paths. We used to
                // output /usr/lib explicitly, but that can introduce other linking problems; see
                // https://github.com/jgallagher/rusqlite/issues/207.
                println!("cargo:rustc-link-lib={}", link_lib);
                HeaderLocation::Wrapper
            }
        }
    }

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        // See if vcpkg can find it.
        if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) {
            if let Some(mut header) = lib.include_paths.pop() {
                header.push("sqlite3.h");
                return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
            }
        }
        None
    }

    #[cfg(not(all(feature = "vcpkg", target_env = "msvc")))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        None
    }

    fn env_prefix() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "SQLCIPHER"
        } else {
            "SQLITE3"
        }
    }

    fn link_lib() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "sqlcipher"
        } else {
            "sqlite3"
        }
    }

    #[cfg(not(feature = "buildtime_bindgen"))]
    mod bindings {
        use super::HeaderLocation;

        use std::{env, fs};
        use std::path::Path;

        #[cfg_attr(rustfmt, rustfmt_skip)]
        static PREBUILT_BINDGEN_PATHS: &'static [&'static str] = &[
            "bindgen-bindings/bindgen_3.6.8.rs",

            #[cfg(feature = "min_sqlite_version_3_6_11")]
            "bindgen-bindings/bindgen_3.6.11.rs",

            #[cfg(feature = "min_sqlite_version_3_6_23")]
            "bindgen-bindings/bindgen_3.6.23.rs",

            #[cfg(feature = "min_sqlite_version_3_7_3")]
            "bindgen-bindings/bindgen_3.7.3.rs",

            #[cfg(feature = "min_sqlite_version_3_7_4")]
            "bindgen-bindings/bindgen_3.7.4.rs",

            #[cfg(feature = "min_sqlite_version_3_7_16")]
            "bindgen-bindings/bindgen_3.7.16.rs",
        ];

        pub fn write_to_out_dir(_header: HeaderLocation) {
            let out_dir = env::var("OUT_DIR").unwrap();
            let out_path = Path::new(&out_dir).join("bindgen.rs");
            let in_path = PREBUILT_BINDGEN_PATHS[PREBUILT_BINDGEN_PATHS.len() - 1];
            fs::copy(in_path, out_path).expect("Could not copy bindings to output directory");
        }
    }

    #[cfg(feature = "buildtime_bindgen")]
    mod bindings {
        extern crate bindgen;

        use self::bindgen::callbacks::{ParseCallbacks, IntKind};
        use super::HeaderLocation;

        use std::env;
        use std::io::Write;
        use std::fs::OpenOptions;
        use std::path::Path;

        #[derive(Debug)]
        struct SqliteTypeChooser;

        impl ParseCallbacks for SqliteTypeChooser {
            fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
                if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
                    Some(IntKind::I32)
                } else {
                    None
                }
            }
        }

        pub fn write_to_out_dir(header: HeaderLocation) {
            let header: String = header.into();
            let out_dir = env::var("OUT_DIR").unwrap();
            let mut output = Vec::new();
            bindgen::builder()
                .header(header.clone())
                .parse_callbacks(Box::new(SqliteTypeChooser))
                .generate()
                .expect(&format!("could not run bindgen on header {}", header))
                .write(Box::new(&mut output))
                .expect("could not write output of bindgen");
            let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");

            // rusqlite's functions feature ors in the SQLITE_DETERMINISTIC flag when it can. This flag
            // was added in SQLite 3.8.3, but oring it in in prior versions of SQLite is harmless. We
            // don't want to not build just because this flag is missing (e.g., if we're linking against
            // SQLite 3.7.x), so append the flag manually if it isn't present in bindgen's output.
            if !output.contains("pub const SQLITE_DETERMINISTIC") {
                output.push_str("\npub const SQLITE_DETERMINISTIC: i32 = 2048;\n");
            }

            let path = Path::new(&out_dir).join("bindgen.rs");

            let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(path.clone())
                .expect(&format!("Could not write to {:?}", path));

            file.write_all(output.as_bytes()).expect(&format!("Could not write to {:?}", path));
        }
    }
}
<|endoftext|>