<commit_before>//! Write benchmark information to the output repository

use errors::{Result, ResultExt, Error};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        if let Ok(file) = File::open(self.broken_commits_file()) {
            let file = BufReader::new(file);
            for line in file.lines() {
                let line = line?;
                let sha = &line[..line.find(":").unwrap()];
                have.insert(sha.to_string());
            }
        }

        let missing = commits
            .iter()
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;

        // dirty index
        if let Err(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn write_broken_commit(&self, commit: &GitCommit, err: Error) -> Result<()> {
        info!("writing broken commit {:?}: {:?}", commit, err);
        let mut broken = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(self.broken_commits_file())
            .chain_err(|| "can't create `broken-commits-log`")?;
        writeln!(broken, "{}: \"{:?}\"", commit.sha, err)?;
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<commit_msg>Don't process commits that are older than 29 days.<commit_after>//! Write benchmark information to the output repository

use errors::{Result, ResultExt, Error};

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::collections::HashSet;

use serde_json;
use collector::CommitData;
use chrono::{Utc, Duration};
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<()> {
        let mut command = Command::new("git");
        command.current_dir(&self.path);
        info!("git {:?}", args);
        command.args(args);
        let status = command
            .status()
            .chain_err(|| format!("could not spawn git {:?}", args))?;
        if !status.success() {
            bail!(
                "command `git {:?}` failed in `{}`",
                args,
                self.path.display()
            );
        }
        Ok(())
    }

    pub fn open(path: PathBuf, use_remote: bool) -> Result<Self> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        if !result.retries_file().exists() {
            // try not to nuke random repositories.
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).chain_err(|| "can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<()> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            let sha =
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()];
            have.insert(sha.to_string());
        }

        if let Ok(file) = File::open(self.broken_commits_file()) {
            let file = BufReader::new(file);
            for line in file.lines() {
                let line = line?;
                let sha = &line[..line.find(":").unwrap()];
                have.insert(sha.to_string());
            }
        }

        let missing = commits
            .iter()
            .filter(|c| {
                Utc::now().signed_duration_since(c.date) < Duration::days(29)
            })
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<()> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;

        // dirty index
        if let Err(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        info!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)?;
        Ok(data)
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<()> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date,
            commit.sha,
            data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<()> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .chain_err(|| {
                format!("can't create `{}`", self.retries_file().display())
            })?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| if line.len() == 40 {
                Ok(line.to_owned())
            } else {
                bail!("bad retry hash `{}`", line)
            })
            .collect::<Result<_>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<()> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .chain_err(|| "can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn write_broken_commit(&self, commit: &GitCommit, err: Error) -> Result<()> {
        info!("writing broken commit {:?}: {:?}", commit, err);
        let mut broken = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(self.broken_commits_file())
            .chain_err(|| "can't create `broken-commits-log`")?;
        writeln!(broken, "{}: \"{:?}\"", commit.sha, err)?;
        Ok(())
    }

    pub fn next_retry(&mut self) -> Option<String> {
        if self.retries.len() == 0 {
            None
        } else {
            Some(self.retries.remove(0))
        }
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    pub fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<|endoftext|>


<commit_before>#[allow(unused_imports)];

use core::option::{Option, Some, None};
use core::fail::out_of_memory;

use platform::{cpu, io, drivers};
use cpu::interrupt;

use self::memory::Allocator;

pub mod ptr;
pub mod memory;
pub mod sgash;
pub mod cstr;

#[cfg(target_word_size = "32")]
pub mod rt;
static START_ADDRESS : *mut u8 = 0x300_000 as *mut u8;
static MEMORY_ORDER : uint = 17;

pub static mut heap: memory::Alloc = memory::Alloc {
    base: START_ADDRESS as *mut u8,
    el_size: 0,
    parent: memory::BuddyAlloc {
        order: MEMORY_ORDER,
        tree: memory::Bitv { storage: START_ADDRESS as memory::BitvStorage }
    }
};

pub static mut int_table: Option<interrupt::Table> = None;

#[lang="start"]
#[no_mangle]
pub fn main() {
    let table = interrupt::Table::new();
    unsafe {
        int_table = Some(table);
    }
    cpu::init();

    table.load();
    drivers::init();
    unsafe {
        drivers::keydown = Some(sgash::parsekey);
        io::init(640, 480);
    }
}
<commit_msg>align at a multiple of 8<commit_after>#[allow(unused_imports)];

use core::option::{Option, Some, None};
use core::fail::out_of_memory;

use platform::{cpu, io, drivers};
use cpu::interrupt;

use self::memory::Allocator;

pub mod ptr;
pub mod memory;
pub mod sgash;
pub mod cstr;

#[cfg(target_word_size = "32")]
pub mod rt;
static START_ADDRESS : *mut u8 = 0x304_000 as *mut u8;
static MEMORY_ORDER : uint = 17;

pub static mut heap: memory::Alloc = memory::Alloc {
    base: START_ADDRESS as *mut u8,
    el_size: 0,
    parent: memory::BuddyAlloc {
        order: MEMORY_ORDER,
        tree: memory::Bitv { storage: START_ADDRESS as memory::BitvStorage }
    }
};

pub static mut int_table: Option<interrupt::Table> = None;

#[lang="start"]
#[no_mangle]
pub fn main() {
    let table = interrupt::Table::new();
    unsafe {
        int_table = Some(table);
    }
    cpu::init();

    table.load();
    drivers::init();
    unsafe {
        drivers::keydown = Some(sgash::parsekey);
        io::init(640, 480);
    }
}
<|endoftext|>


<commit_before>extern mod std;

use core::to_bytes::*;

use std::*;
use io::{ReaderUtil,WriterUtil};

enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

priv fn parse_data(len: uint, io: io::Reader) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      assert bytes.len() == len;
      Data(bytes)
    } else {
      Data(~[])
    };
  assert io.read_byte() == 13;
  assert io.read_byte() == 10;
  return res;
}

priv fn read_char(io: io::Reader) -> char {
  let ch = io.read_byte();
  if ch < 0 { fail }
  ch as char
}

priv fn parse_list(len: uint, io: io::Reader) -> Result {
  List(vec::from_fn(len, |_| { parse_response(io) }))
}

priv fn parse_int_line(io: io::Reader) -> int {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    let ch = read_char(io);
    match ch {
      '0' .. '9' => {
        digits += 1;
        i = (i * 10) + (ch as int - '0' as int);
        },
      '-' => {
        if negative { fail }
        negative = true
        },
      '\r' => {
        assert read_char(io) == '\n';
        break
        },
      '\n' => break,
      _ => fail
    }
  }

  if digits == 0 { fail }

  if negative { -i }
  else { i }
}

priv fn parse_n(io: io::Reader, f: fn(uint, io::Reader) -> Result) -> Result {
  match parse_int_line(io) {
    -1 => Nil,
    len if len >= 0 => f(len as uint, io),
    _ => fail
  }
}

priv fn parse_response(io: io::Reader) -> Result {
  match read_char(io) {
    '$' => parse_n(io, parse_data),
    '*' => parse_n(io, parse_list),
    '+' => Status(io.read_line()),
    '-' => Error(io.read_line()),
    ':' => Int(parse_int_line(io)),
    _   => fail
  }
}

priv fn cmd_to_str(cmd: ~[~str]) -> ~str {
  let mut res = ~"*";
  str::push_str(&mut res, cmd.len().to_str());
  str::push_str(&mut res, "\r\n");
  for cmd.each |s| {
    str::push_str(&mut res, str::concat(~[~"$", s.len().to_str(), ~"\r\n", *s, ~"\r\n"]));
  }
  res
}

fn send_query(cmd: ~[~str], sb: net::tcp::TcpSocketBuf) {
  let cmd = cmd_to_str(cmd);
  sb.write_str(cmd);
}

fn recv_query(sb: net::tcp::TcpSocketBuf) -> Result {
  let res = parse_response(sb as io::Reader);
  //io::println(fmt!("%?", res));
  res
}

fn query(cmd: ~[~str], sb: net::tcp::TcpSocketBuf) -> Result {
  send_query(cmd, sb);
  recv_query(sb)
}

fn main() {
  let server_ip_addr = net::ip::v4::parse_addr("127.0.0.1");
  let server_port = 6379;
  let iotask = uv::global_loop::get();
  let connect_result = net::tcp::connect(server_ip_addr, server_port, iotask);
  let sock = result::unwrap(connect_result);
  let sb = net::tcp::socket_buf(sock);

  //query(~[~"SET", ~"def", ~"abc"], sb);

  //let cmd = cmd_to_str(~[~"GET", ~"def"]);

  for 10000.times {
    //let x = cmd.to_bytes(true);
    //net::tcp::write(&sock, x);

    //do str::as_buf(cmd) {
      //net::tcp::write(&sock, vec::from_buf(ptr, elts))
    //}
    //str::as_bytes(&~"blah", |bytes| {
      //let blah: ~[u8] = *bytes;
      //net::tcp::write(&sock, *bytes)
    //});

/*
    for 10_000.times {
      send_query(~[~"GET", ~"def"], sb);
    }
    for 10_000.times {
      recv_query(sb);
    }
*/
    for 1.times {
      send_query(~[~"GET", ~"def"], sb);
    }
    for 1.times {
      recv_query(sb);
    }

    //query(~[~"EXEC"], sb);
  }

/*
  let mut buf: ~[u8] = vec::from_elem(10_000, 0);

  loop {
    let read_result = net::tcp::read(&sock, 0u);
    if !read_result.is_err() {
      let s = vec::len(result::unwrap(read_result));
      io::println(fmt!("%u\n", s));
    }
    else {
      io::println("ERROR");
      break;
    }
    //if sb.read(buf, 10_000) < 10_000 { break }
    //io::println("read");
  }
*/
/*  query(~[~"MULTI"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"INCR", ~"def"], sb);
  query(~[~"GET", ~"def"], sb);
  query(~[~"EXEC"], sb);

  query(~[~"SET", ~"abc", ~"XXX"], sb);
  query(~[~"SET", ~"def", ~"123"], sb);
  query(~[~"GET", ~"abc"], sb);
  query(~[~"MGET", ~"abc", ~"def", ~"non"], sb);
*/
}
<commit_msg>Modify for upcoming Rust 0.9<commit_after>use std::io::buffered::BufferedStream;
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
use std::vec::bytes::push_bytes;

pub enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

fn read_char(io: &mut BufferedStream<TcpStream>) -> char {
  match io.read_byte() {
    Some(ch) => ch as char,
    None     => fail!()
  }
}

fn parse_data(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      assert!(bytes.len() == len);
      Data(bytes)
    } else {
      Data(~[])
    };
  assert!(io.read_byte() == Some(13));
  assert!(io.read_byte() == Some(10));
  return res;
}

fn parse_list(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  List(std::vec::from_fn(len, |_| { parse_response(io) }))
}

fn parse_int_line(io: &mut BufferedStream<TcpStream>) -> int {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    let ch = read_char(io);
    match ch {
      '0' .. '9' => {
        digits += 1;
        i = (i * 10) + (ch as int - '0' as int);
        },
      '-' => {
        if negative { fail!() }
        negative = true
        },
      '\r' => {
        assert!(read_char(io) == '\n');
        break
        },
      '\n' => break,
      _ => fail!()
    }
  }

  if digits == 0 { fail!() }

  if negative { -i }
  else { i }
}

fn parse_n(io: &mut BufferedStream<TcpStream>, f: |uint, &mut BufferedStream<TcpStream>| -> Result) -> Result {
  match parse_int_line(io) {
    -1 => Nil,
    len if len >= 0 => f(len as uint, io),
    _ => fail!()
  }
}

fn parse_status(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Status(line),
    None       => fail!()
  }
}

fn parse_error(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Error(line),
    None       => fail!()
  }
}

fn parse_response(io: &mut BufferedStream<TcpStream>) -> Result {
  match read_char(io) {
    '$' => parse_n(io, parse_data),
    '*' => parse_n(io, parse_list),
    '+' => parse_status(io),
    '-' => parse_error(io),
    ':' => Int(parse_int_line(io)),
    _   => fail!()
  }
}

fn prepare_cmd(cmd: ~[~str]) -> ~[u8] {
  let mut res: ~[u8] = ~[];
  push_bytes(&mut res, bytes!("*"));
  push_bytes(&mut res, cmd.len().to_str().into_bytes());
  push_bytes(&mut res, bytes!("\r\n"));
  for c in cmd.iter() {
    push_bytes(&mut res, bytes!("$"));
    push_bytes(&mut res, c.len().to_str().into_bytes());
    push_bytes(&mut res, bytes!("\r\n"));
    push_bytes(&mut res, c.as_bytes());
    push_bytes(&mut res, bytes!("\r\n"));
  }
  res
}

fn send_query(cmd: &[u8], io: &mut BufferedStream<TcpStream>) {
  io.write(cmd);
  io.flush();
}

fn recv_query(io: &mut BufferedStream<TcpStream>) -> Result {
  parse_response(io)
}

fn query(cmd: &[u8], io: &mut BufferedStream<TcpStream>) -> Result {
  send_query(cmd, io);
  let res = recv_query(io);
  res
}

fn main() {
  let addr = from_str::<SocketAddr>("127.0.0.1:6379").unwrap();
  let tcp_stream = TcpStream::connect(addr).unwrap();
  let mut reader = BufferedStream::new(tcp_stream);

  let cmd = prepare_cmd(~[~"SET", ~"def", ~"abc"]);

  for i in std::iter::range(1, 100_000) {
    query(cmd, &mut reader);
  }
}
<|endoftext|>


<commit_before>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn link_states(&mut self, id0: int, id1: int)
	{
		self.states[id0].add_transition(id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}

	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				//println(fmt!("on character %?, state=%? val=%?", c, curr[i], self.states[curr[i]].val));
				if self.states[curr[i]].val == c
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("adding %d", self.states[curr[i]].transitions[j]));
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '.'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("pushing %d", self.states[curr[i]].transitions[j]));
						curr.push(self.states[curr[i]].transitions[j]);
						l += 1;
					}
				}
				i += 1;
				//println(fmt!("curr=%? next=%? l=%? i=%?", curr,next,l, i));
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone,DeepClone, Eq)]
struct State
{
	val: char,
	accept: bool,
	transitions: ~[int]
}

impl State
{
	pub fn new(c: char, b: bool)	->	State
	{
		State { val: c, accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("value=%? matching=%? transitions={", self.val, self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, id: int)
	{
		self.transitions.push(id);
	}

	pub fn change_val(&mut self, c: char)
	{
		self.val = c;
	}
}

fn main()
{
	let test = std::os::args()[1];
	let strings = ~[~"", ~"a", ~"b", ~"aa", ~"bb", ~"ab", ~"ba", ~"aab", ~"aba", ~"baa", ~"abb", ~"bab", ~"bba", ~"bbb", ~"aaa", ~"abbb", ~"abba"];
	let mut nfa = NFA::new();
	let mut parenthesis: ~[int] = ~[];
	let head_state = State::new('%', false);
	nfa.add_state(head_state);
	let mut j = 0;
	let mut escaped = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		if c == '\\'
		{
			escaped = true;
		}
		else if c == '(' && !escaped
		{
			// note the place and make an 'in' state
			parenthesis.push(i);
			let state_in = State::new('%', false);
			nfa.add_state(state_in);
			j += 1;

			// link this and the previous
			nfa.link_states(j-1, j);
		}
		else if c == '*' && !escaped
		{
			// prev state j
			// state_in
			// state_curr
			// state_out
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);
			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;
			// prev state
			// state_in j
			// state_curr
			// state_out

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			// prev state
			// state_in
			// state_curr j
			// state_out
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			// prev state
			// state_in
			// state_curr
			// state_out j
			nfa.link_states(j-1, j);

			// link prev state to state_out
			nfa.link_states(j-3, j);

			// link state_out to state_in,
			// since it's a *
			nfa.link_states(j, j-2);
		}
		else if c == '+' && !escaped
		{
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);
			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			nfa.link_states(j-1, j);

			// link state_out to state_in
			nfa.link_states(j, j-2);
		}
		else if c == '?' && !escaped
		{
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);
			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			nfa.link_states(j-1, j);

			// link prev state to state_out
			nfa.link_states(j-3, j);

			// link state_in to state_out,
			// since it's a ?
			nfa.link_states(j-2, j);
		}
		else if c == '.' && !escaped
		{
			let state = State::new(c, false);
			nfa.add_state(state);
			j += 1;
			// link with previous
			nfa.link_states(j-1, j);
		}
		else
		{
			let state = State::new(c, false);
			nfa.add_state(state);
			j += 1;
			// link with previous
			nfa.link_states(j-1, j);
			escaped = false;
		}
	}

	// add a tail state
	let tail_state = State::new('%', true);
	nfa.add_state(tail_state);
	// link with previous
	let l = nfa.len();
	nfa.link_states(l-2, l-1);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}
}
<commit_msg>() is broken. need to add in and out ids to the NFA struct so we can chain them together. can store them in a vector, i guess<commit_after>struct NFA
{
	states: ~[State],
}

impl NFA
{
	pub fn new()	->	NFA
	{
		NFA { states: ~[] }
	}

	pub fn add_state(&mut self, state: State)
	{
		self.states.push(state);
	}

	pub fn link_states(&mut self, id0: int, id1: int)
	{
		self.states[id0].add_transition(id1);
	}

	pub fn print(&self)
	{
		println("\nprinting states:");
		for i in range(0, self.states.len())
		{
			print(fmt!("%u: ", i));
			self.states[i].print();
		}
		println("");
	}

	pub fn pop(&mut self)	->	State
	{
		self.states.pop()
	}

	pub fn len(&self)	->	int
	{
		self.states.len() as int
	}

	pub fn check(&self, string: ~str, c: ~[int])		->	bool
	{
		let mut curr = c.clone();
		//println(fmt!("check: string=%? c=%?", string, c));
		if string.len() > 0
		{
			let c = string.char_at(0);
			let mut next = ~[];
			// look to see if any current states have c or an
			// epsilon transition as a value
			let mut l = curr.len();
			let mut i = 0;
			while i < l
			{
				//println(fmt!("on character %?, state=%? val=%?", c, curr[i], self.states[curr[i]].val));
				if self.states[curr[i]].val == c
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("adding %d", self.states[curr[i]].transitions[j]));
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '.'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
				else if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						//println(fmt!("pushing %d", self.states[curr[i]].transitions[j]));
						if !curr.contains(&self.states[curr[i]].transitions[j])
						{
							curr.push(self.states[curr[i]].transitions[j]);
							l += 1;
						}
					}
				}
				i += 1;
				//println(fmt!("curr=%? next=%? l=%? i=%?", curr,next,l, i));
			}
			if next.len() == 0 { return false; }
			return self.check(string.slice_from(1).to_owned(), next);
		}
		else
		{
			// see if we're in a matching state
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].accept
				{
					return true;
				}
			}
			// check to see if there are any epsilon transitions we
			// can make
			let mut next = ~[];
			for i in range(0, curr.len())
			{
				if self.states[curr[i]].val == '%'
				{
					for j in range(0, self.states[curr[i]].transitions.len())
					{
						next.push(self.states[curr[i]].transitions[j]);
					}
				}
			}
			//println(fmt!("curr=%? next=%?", curr, next));
			if next.len() > 0
			{
				return self.check(string, next);
			}
			return false;
		}
	}
}

#[deriving(Clone,DeepClone, Eq)]
struct State
{
	val: char,
	accept: bool,
	transitions: ~[int]
}

impl State
{
	pub fn new(c: char, b: bool)	->	State
	{
		State { val: c, accept: b, transitions: ~[] }
	}

	pub fn print(&self)
	{
		print(fmt!("value=%? matching=%? transitions={", self.val, self.accept));
		for i in range(0, self.transitions.len())
		{
			print(fmt!("%?,", self.transitions[i]));
		}
		println("}");
	}

	pub fn is_accept(&mut self, b: bool)
	{
		self.accept = b;
	}

	pub fn add_transition(&mut self, id: int)
	{
		self.transitions.push(id);
	}

	pub fn change_val(&mut self, c: char)
	{
		self.val = c;
	}
}

fn main()
{
	let test = std::os::args()[1];
	let strings = ~[~"", ~"a", ~"b", ~"aa", ~"bb", ~"ab", ~"ba", ~"aab", ~"aba", ~"baa", ~"abb", ~"bab", ~"bba", ~"bbb", ~"aaa", ~"abbb", ~"abba"];
	let mut nfa = NFA::new();
	let mut parenthesis: ~[int] = ~[];
	let head_state = State::new('%', false);
	nfa.add_state(head_state);
	let mut j = 0;
	let mut escaped = false;
	for i in range(1,(test.len()+1) as int)
	{
		let c = test.char_at((i-1) as uint);
		if c == '\\'
		{
			escaped = true;
		}
		else if c == '(' && !escaped
		{
			// note the place and make an 'in' state
			parenthesis.push(i);
			let state_in = State::new('%', false);
			nfa.add_state(state_in);
			j += 1;

			// link this and the previous
			nfa.link_states(j-1, j);
		}
		else if c == ')' && !escaped
		{
			let state_out = State::new('%', false);
			nfa.add_state(state_out);
			j += 1;

			// link to state_in
			nfa.link_states(j, parenthesis.pop()-1);

			// link to prev
			nfa.link_states(j-1, j);
		}
		else if c == '*' && !escaped
		{
			// prev state j
			// state_in
			// state_curr
			// state_out
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);
			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;
			// prev state
			// state_in j
			// state_curr
			// state_out

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			// prev state
			// state_in
			// state_curr j
			// state_out
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			// prev state
			// state_in
			// state_curr
			// state_out j
			nfa.link_states(j-1, j);

			nfa.link_states(j-3, j);

			// link state_out to state_in,
			// since it's a *
			nfa.link_states(j, j-2);
		}
		else if c == '+' && !escaped
		{
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);
			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			nfa.link_states(j-1, j);

			// link state_out to state_in
			nfa.link_states(j, j-2);
		}
		else if c == '?' && !escaped
		{
			let mut state_in = nfa.pop();
			j -= 1;
			let c = state_in.val;
			let state_curr = State::new(c, false);

			state_in.change_val('%');
			let state_out = State::new('%', false);

			// don't need to link
			nfa.add_state(state_in);
			j += 1;

			// link to state_in
			nfa.add_state(state_curr);
			j += 1;
			nfa.link_states(j-1, j);

			// link to state_curr
			nfa.add_state(state_out);
			j += 1;
			nfa.link_states(j-1, j);

			// link prev state to state_out
			nfa.link_states(j-3, j);

			// link state_in to state_out,
			// since it's a ?
			nfa.link_states(j-2, j);
		}
		else if c == '.' && !escaped
		{
			let state = State::new(c, false);
			nfa.add_state(state);
			j += 1;
			// link with previous
			nfa.link_states(j-1, j);
		}
		else
		{
			let state = State::new(c, false);
			nfa.add_state(state);
			j += 1;
			// link with previous
			nfa.link_states(j-1, j);
			escaped = false;
		}
	}

	// add a tail state
	let tail_state = State::new('%', true);
	nfa.add_state(tail_state);
	// link with previous
	let l = nfa.len();
	nfa.link_states(l-2, l-1);

	nfa.print();

	let curr = ~[0];
	println(fmt!("Regex is: %s", test));
	for i in range(0, strings.len())
	{
		println(fmt!("%? %?", strings[i], nfa.check(strings[i].clone(), curr.clone())));
	}
}
<|endoftext|>


<commit_before>use super::table::{Table, PML4Level};
use cpu::control_regs::cr3::{read, write};
pub use cpu::control_regs::cr3::*;

/// Returns the current Page Meta-Level 4 table
///
/// # Unsafe Because:
/// + Reading from control registers while not in kernel mode will cause
///   a general protection fault.
#[cfg(target_arch = "x86_64")]
#[inline]
// TODO: this needs to return a reference
pub unsafe fn current_pml4() -> Table<PML4Level> {
    use core::mem::transmute;
    //*read().as_mut_ptr::<Table<PML4Level>>()
    unimplemented!()
}

/// Sets the current Page Meta-Level 4 Table
///
/// # Unsafe Because:
/// + Control registers should generally not be modified during normal
///   operation.
#[cfg(target_arch = "x86_64")]
pub unsafe fn set_pml4(pml4: Table<PML4Level>) {
    write(pml4.frame().base_addr())
}
<commit_msg>[paging] add implementation to current_pml4 function<commit_after>use super::table::{Table, PML4Level};
use cpu::control_regs::cr3::{read, write};
pub use cpu::control_regs::cr3::*;

/// Returns the current Page Meta-Level 4 table
///
/// # Unsafe Because:
/// + Reading from control registers while not in kernel mode will cause
///   a general protection fault.
#[cfg(target_arch = "x86_64")]
#[inline]
pub unsafe fn current_pml4() -> *mut Table<PML4Level> {
    read().as_mut_ptr::<Table<PML4Level>>()
}

/// Sets the current Page Meta-Level 4 Table
///
/// # Unsafe Because:
/// + Control registers should generally not be modified during normal
///   operation.
#[cfg(target_arch = "x86_64")]
pub unsafe fn set_pml4(pml4: Table<PML4Level>) {
    write(pml4.frame().base_addr())
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![experimental]

use registry::{Registry, Ns};
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub struct GlobalGenerator;

impl super::Generator for GlobalGenerator {
    fn write(&self, ecx: &ExtCtxt, registry: &Registry, ns: Ns) -> Vec<P<ast::Item>> {
        let mut result = Vec::new();
        result.push(write_header(ecx));
        result.push(write_metaloadfn(ecx));
        result.push(write_type_aliases(ecx, &ns));
        result.extend(write_enums(ecx, registry).into_iter());
        result.extend(write_fns(ecx, registry).into_iter());
        result.extend(write_fnptr_struct_def(ecx).into_iter());
        result.push(write_ptrs(ecx, registry));
        result.extend(write_fn_mods(ecx, registry, &ns).into_iter());
        result.push(write_failing_fns(ecx, registry));
        result.extend(write_load_fn(ecx, registry).into_iter());
        result
    }
}

/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
///  bindings.
fn write_header(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        mod __gl_imports {
            extern crate gl_common;
            extern crate libc;
            pub use std::mem;
        }
    )).unwrap()
}

/// Creates the metaloadfn function for fallbacks
fn write_metaloadfn(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        fn metaloadfn(loadfn: |&str| -> *const __gl_imports::libc::c_void,
                      symbol: &str,
                      fallbacks: &[&str]) -> *const __gl_imports::libc::c_void {
            let mut ptr = loadfn(symbol);
            if ptr.is_null() {
                for &sym in fallbacks.iter() {
                    ptr = loadfn(sym);
                    if !ptr.is_null() { break; }
                }
            }
            ptr
        }
    )).unwrap()
}

/// Creates a `types` module which contains all the type aliases.
///
/// See also `generators::gen_type_aliases`.
fn write_type_aliases(ecx: &ExtCtxt, ns: &Ns) -> P<ast::Item> {
    let aliases = super::gen_type_aliases(ecx, ns);

    (quote_item!(ecx,
        #[stable]
        pub mod types {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]

            $aliases
        }
    )).unwrap()
}

/// Creates all the `<enum>` elements at the root of the bindings.
fn write_enums(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.enum_iter().map(|e| {
        super::gen_enum_item(ecx, e, "types::")
    }).collect()
}

/// Creates the functions corresponding to the GL commands.
///
/// The function calls the corresponding function pointer stored in the `storage` module created
///  by `write_ptrs`.
fn write_fns(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        use syntax::ext::quote::rt::ToSource;

        let doc = match registry.aliases.get(&c.proto.ident) {
            Some(v) => format!("/** Fallbacks: {} */", v.connect(", ")),
            None => "".to_string()
        };

        ecx.parse_item(
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variables)] #[allow(dead_code)]
                #[inline] #[unstable] {doc} pub unsafe fn {name}({typed_params}) -> {return_suffix} {{ \
                    __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
                        (storage::{name}.f)({idents}) \
                }}",
                name = c.proto.ident,
                doc = doc,
                typed_params = super::gen_parameters(ecx, c).into_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).into_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        )
    }).collect()
}

/// Creates a `FnPtr` structure which contains the store for a single binding.
fn write_fnptr_struct_def(ecx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let mut result = Vec::new();

    result.push((quote_item!(ecx,
        pub struct FnPtr {
            /// The function pointer that will be used when calling the function.
            f: *const __gl_imports::libc::c_void,
            /// True if the pointer points to a real function, false if points to a `panic!` fn.
            is_loaded: bool,
        }
    )).unwrap());

    result.push((quote_item!(ecx,
        impl FnPtr {
            /// Creates a `FnPtr` from a load attempt.
            pub fn new(ptr: *const __gl_imports::libc::c_void, failing_fn: *const __gl_imports::libc::c_void) -> FnPtr {
                if ptr.is_null() {
                    FnPtr { f: failing_fn, is_loaded: false }
                } else {
                    FnPtr { f: ptr, is_loaded: true }
                }
            }
        }
    )).unwrap());

    result
}

/// Creates a `storage` module which contains a static `FnPtr` per GL command in the registry.
fn write_ptrs(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let storages = registry.cmd_iter().map(|c| {
        ecx.parse_item(format!(
            "pub static mut {name}: FnPtr = FnPtr {{
                f: failing::{name} as *const libc::c_void,
                is_loaded: false
            }};",
            name = c.proto.ident
        ))
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod storage {
            #![allow(non_snake_case)]
            use super::__gl_imports::libc;
            use super::failing;
            use super::FnPtr;

            $storages
        }
    )).unwrap()
}

/// Creates one module for each GL command.
///
/// Each module contains `is_loaded` and `load_with` which interact with the `storage` module
///  created by `write_ptrs`.
fn write_fn_mods(ecx: &ExtCtxt, registry: &Registry, ns: &Ns) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        let fallbacks = match registry.aliases.get(&c.proto.ident) {
            Some(v) => {
                let names = v.iter().map(|name| format!("\"{}\"", super::gen_symbol_name(ns, name.as_slice()))).collect::<Vec<_>>();
                format!("[{}]", names.connect(", "))
            }, None => "[]".to_string(),
        };
        let fallbacks = ecx.parse_expr(fallbacks);
        let fnname = ecx.ident_of(c.proto.ident.as_slice());
        let symbol = super::gen_symbol_name(ns, c.proto.ident.as_slice());
        let symbol = symbol.as_slice();

        (quote_item!(ecx,
            #[unstable]
            #[allow(non_snake_case)]
            pub mod $fnname {
                use super::{failing, storage, metaloadfn};
                use super::FnPtr;

                #[inline]
                #[allow(dead_code)]
                pub fn is_loaded() -> bool {
                    unsafe { storage::$fnname.is_loaded }
                }

                #[allow(dead_code)]
                pub fn load_with(loadfn: |symbol: &str| -> *const super::__gl_imports::libc::c_void) {
                    unsafe {
                        storage::$fnname = FnPtr::new(metaloadfn(loadfn, $symbol, $fallbacks),
                            failing::$fnname as *const super::__gl_imports::libc::c_void)
                    }
                }
            }
        )).unwrap()
    }).collect()

    // TODO: this is a reliquate from an old code, I have no idea what it does
    // for c in self.registry.cmd_iter() {
    //     self.write_line(format!(
    //         "pub mod {name} {{ \
    //             #[inline] \
    //             pub fn is_loaded() -> bool {{ \
    //                 unsafe {{ ::storage::{name}.is_loaded }} \
    //             }} \
    //         }}",
    //         name = c.proto.ident,
    //     ).as_slice());
    // }
}

/// Creates a `failing` module which contains one function per GL command.
///
/// These functions are the mocks that are called if the real function could not be loaded.
fn write_failing_fns(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    use syntax::ext::quote::rt::ToSource;

    let functions = registry.cmd_iter().map(|c| {
        ecx.parse_item(format!(
            "#[allow(non_snake_case)] #[allow(unused_variables)] #[allow(dead_code)]
            pub extern \"system\" fn {name}({params}) -> {return_suffix} {{ \
                panic!(\"`{name}` was not loaded\") \
            }}",
            name = c.proto.ident,
            params = super::gen_parameters(ecx, c).into_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
            return_suffix = super::gen_return_type(ecx, c).to_source()
        ))
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod failing {
            use super::types;
            use super::__gl_imports;

            $functions
        }
    )).unwrap()
}

/// Creates the `load_with` function.
///
/// The function calls `load_with` in each module created by `write_fn_mods`.
fn write_load_fn(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    let loadings = registry.cmd_iter().map(|c| {
        let cmd_name = ecx.ident_of(c.proto.ident.as_slice());
        quote_stmt!(ecx, $cmd_name::load_with(|s| loadfn(s));)
    }).collect::<Vec<P<ast::Stmt>>>();

    let a = (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function. This allows for the
        /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
        /// ~~~ignore
        /// gl::load_with(|s| glfw.get_proc_address(s));
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load_with(loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) {
            $loadings
        }
    )).unwrap();

    let b = (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function.
        ///
        /// ~~~ignore
        /// gl::load(&glfw);
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load<T: __gl_imports::gl_common::GlFunctionsSource>(loader: &T) {
            load_with(|name| loader.get_proc_addr(name));
        }
    )).unwrap();

    vec![a, b]
}
<commit_msg>fixed for changes to slice coercion<commit_after>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![experimental]

use registry::{Registry, Ns};
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub struct GlobalGenerator;

impl super::Generator for GlobalGenerator {
    fn write(&self, ecx: &ExtCtxt, registry: &Registry, ns: Ns) -> Vec<P<ast::Item>> {
        let mut result = Vec::new();
        result.push(write_header(ecx));
        result.push(write_metaloadfn(ecx));
        result.push(write_type_aliases(ecx, &ns));
        result.extend(write_enums(ecx, registry).into_iter());
        result.extend(write_fns(ecx, registry).into_iter());
        result.extend(write_fnptr_struct_def(ecx).into_iter());
        result.push(write_ptrs(ecx, registry));
        result.extend(write_fn_mods(ecx, registry, &ns).into_iter());
        result.push(write_failing_fns(ecx, registry));
        result.extend(write_load_fn(ecx, registry).into_iter());
        result
    }
}

/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
///  bindings.
fn write_header(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        mod __gl_imports {
            extern crate gl_common;
            extern crate libc;
            pub use std::mem;
        }
    )).unwrap()
}

/// Creates the metaloadfn function for fallbacks
fn write_metaloadfn(ecx: &ExtCtxt) -> P<ast::Item> {
    (quote_item!(ecx,
        fn metaloadfn(loadfn: |&str| -> *const __gl_imports::libc::c_void,
                      symbol: &str,
                      fallbacks: &[&str]) -> *const __gl_imports::libc::c_void {
            let mut ptr = loadfn(symbol);
            if ptr.is_null() {
                for &sym in fallbacks.iter() {
                    ptr = loadfn(sym);
                    if !ptr.is_null() { break; }
                }
            }
            ptr
        }
    )).unwrap()
}

/// Creates a `types` module which contains all the type aliases.
///
/// See also `generators::gen_type_aliases`.
fn write_type_aliases(ecx: &ExtCtxt, ns: &Ns) -> P<ast::Item> {
    let aliases = super::gen_type_aliases(ecx, ns);

    (quote_item!(ecx,
        #[stable]
        pub mod types {
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]

            $aliases
        }
    )).unwrap()
}

/// Creates all the `<enum>` elements at the root of the bindings.
fn write_enums(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.enum_iter().map(|e| {
        super::gen_enum_item(ecx, e, "types::")
    }).collect()
}

/// Creates the functions corresponding to the GL commands.
///
/// The function calls the corresponding function pointer stored in the `storage` module created
///  by `write_ptrs`.
fn write_fns(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        use syntax::ext::quote::rt::ToSource;

        let doc = match registry.aliases.get(&c.proto.ident) {
            Some(v) => format!("/** Fallbacks: {} */", v.connect(", ")),
            None => "".to_string()
        };

        ecx.parse_item(
            format!(
                "#[allow(non_snake_case)] #[allow(unused_variables)] #[allow(dead_code)]
                #[inline] #[unstable] {doc} pub unsafe fn {name}({typed_params}) -> {return_suffix} {{ \
                    __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
                        (storage::{name}.f)({idents}) \
                }}",
                name = c.proto.ident,
                doc = doc,
                typed_params = super::gen_parameters(ecx, c).into_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
                return_suffix = super::gen_return_type(ecx, c).to_source(),
                idents = super::gen_parameters(ecx, c).into_iter().map(|p| p.pat.to_source()).collect::<Vec<String>>().connect(", "),
            )
        )
    }).collect()
}

/// Creates a `FnPtr` structure which contains the store for a single binding.
fn write_fnptr_struct_def(ecx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let mut result = Vec::new();

    result.push((quote_item!(ecx,
        pub struct FnPtr {
            /// The function pointer that will be used when calling the function.
            f: *const __gl_imports::libc::c_void,
            /// True if the pointer points to a real function, false if points to a `panic!` fn.
            is_loaded: bool,
        }
    )).unwrap());

    result.push((quote_item!(ecx,
        impl FnPtr {
            /// Creates a `FnPtr` from a load attempt.
            pub fn new(ptr: *const __gl_imports::libc::c_void, failing_fn: *const __gl_imports::libc::c_void) -> FnPtr {
                if ptr.is_null() {
                    FnPtr { f: failing_fn, is_loaded: false }
                } else {
                    FnPtr { f: ptr, is_loaded: true }
                }
            }
        }
    )).unwrap());

    result
}

/// Creates a `storage` module which contains a static `FnPtr` per GL command in the registry.
fn write_ptrs(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    let storages = registry.cmd_iter().map(|c| {
        ecx.parse_item(format!(
            "pub static mut {name}: FnPtr = FnPtr {{
                f: failing::{name} as *const libc::c_void,
                is_loaded: false
            }};",
            name = c.proto.ident
        ))
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod storage {
            #![allow(non_snake_case)]
            use super::__gl_imports::libc;
            use super::failing;
            use super::FnPtr;

            $storages
        }
    )).unwrap()
}

/// Creates one module for each GL command.
///
/// Each module contains `is_loaded` and `load_with` which interact with the `storage` module
///  created by `write_ptrs`.
fn write_fn_mods(ecx: &ExtCtxt, registry: &Registry, ns: &Ns) -> Vec<P<ast::Item>> {
    registry.cmd_iter().map(|c| {
        let fallbacks = match registry.aliases.get(&c.proto.ident) {
            Some(v) => {
                let names = v.iter().map(|name| format!("\"{}\"", super::gen_symbol_name(ns, name.as_slice()))).collect::<Vec<_>>();
                format!("&[{}]", names.connect(", "))
            }, None => "&[]".to_string(),
        };
        let fallbacks = ecx.parse_expr(fallbacks);
        let fnname = ecx.ident_of(c.proto.ident.as_slice());
        let symbol = super::gen_symbol_name(ns, c.proto.ident.as_slice());
        let symbol = symbol.as_slice();

        (quote_item!(ecx,
            #[unstable]
            #[allow(non_snake_case)]
            pub mod $fnname {
                use super::{failing, storage, metaloadfn};
                use super::FnPtr;

                #[inline]
                #[allow(dead_code)]
                pub fn is_loaded() -> bool {
                    unsafe { storage::$fnname.is_loaded }
                }

                #[allow(dead_code)]
                pub fn load_with(loadfn: |symbol: &str| -> *const super::__gl_imports::libc::c_void) {
                    unsafe {
                        storage::$fnname = FnPtr::new(metaloadfn(loadfn, $symbol, $fallbacks),
                            failing::$fnname as *const super::__gl_imports::libc::c_void)
                    }
                }
            }
        )).unwrap()
    }).collect()

    // TODO: this is a reliquate from an old code, I have no idea what it does
    // for c in self.registry.cmd_iter() {
    //     self.write_line(format!(
    //         "pub mod {name} {{ \
    //             #[inline] \
    //             pub fn is_loaded() -> bool {{ \
    //                 unsafe {{ ::storage::{name}.is_loaded }} \
    //             }} \
    //         }}",
    //         name = c.proto.ident,
    //     ).as_slice());
    // }
}

/// Creates a `failing` module which contains one function per GL command.
///
/// These functions are the mocks that are called if the real function could not be loaded.
fn write_failing_fns(ecx: &ExtCtxt, registry: &Registry) -> P<ast::Item> {
    use syntax::ext::quote::rt::ToSource;

    let functions = registry.cmd_iter().map(|c| {
        ecx.parse_item(format!(
            "#[allow(non_snake_case)] #[allow(unused_variables)] #[allow(dead_code)]
            pub extern \"system\" fn {name}({params}) -> {return_suffix} {{ \
                panic!(\"`{name}` was not loaded\") \
            }}",
            name = c.proto.ident,
            params = super::gen_parameters(ecx, c).into_iter().map(|p| p.to_source()).collect::<Vec<String>>().connect(", "),
            return_suffix = super::gen_return_type(ecx, c).to_source()
        ))
    }).collect::<Vec<P<ast::Item>>>();

    (quote_item!(ecx,
        mod failing {
            use super::types;
            use super::__gl_imports;

            $functions
        }
    )).unwrap()
}

/// Creates the `load_with` function.
///
/// The function calls `load_with` in each module created by `write_fn_mods`.
fn write_load_fn(ecx: &ExtCtxt, registry: &Registry) -> Vec<P<ast::Item>> {
    let loadings = registry.cmd_iter().map(|c| {
        let cmd_name = ecx.ident_of(c.proto.ident.as_slice());
        quote_stmt!(ecx, $cmd_name::load_with(|s| loadfn(s));)
    }).collect::<Vec<P<ast::Stmt>>>();

    let a = (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function. This allows for the
        /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
        /// ~~~ignore
        /// gl::load_with(|s| glfw.get_proc_address(s));
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load_with(loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) {
            $loadings
        }
    )).unwrap();

    let b = (quote_item!(ecx,
        /// Load each OpenGL symbol using a custom load function.
        ///
        /// ~~~ignore
        /// gl::load(&glfw);
        /// ~~~
        #[unstable]
        #[allow(dead_code)]
        pub fn load<T: __gl_imports::gl_common::GlFunctionsSource>(loader: &T) {
            load_with(|name| loader.get_proc_addr(name));
        }
    )).unwrap();

    vec![a, b]
}
<|endoftext|>


<commit_before>use serde_derive::{Deserialize, Serialize};
use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};

use crate::{
    ast::{InputValue, Selection, ToInputValue},
    executor::{Executor, Registry},
    parser::{LexerError, ParseError, ScalarToken, Token},
    schema::meta::MetaType,
    types::base::GraphQLType,
    value::{ParseScalarResult, ScalarRefValue, ScalarValue, Value},
};

/// An ID as defined by the GraphQL specification
///
/// Represented as a string, but can be converted _to_ from an integer as well.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ID(String);

impl From<String> for ID {
    fn from(s: String) -> ID {
        ID(s)
    }
}

impl ID {
    /// Construct a new ID from anything implementing `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        ID(value.into())
    }
}

impl Deref for ID {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

graphql_scalar!(ID as "ID" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(self.0.clone())
    }

    from_input_value(v: &InputValue) -> Option<ID> {
        match *v {
            InputValue::Scalar(ref s) => {
                s.as_string().or_else(|| s.as_int().map(|i| i.to_string()))
                    .map(ID)
            }
            _ => None
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::String(value) | ScalarToken::Int(value) => {
                Ok(S::from(value.to_owned()))
            }
            _ => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
});

graphql_scalar!(String as "String" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(self.clone())
    }

    from_input_value(v: &InputValue) -> Option<String> {
        match *v {
            InputValue::Scalar(ref s) => s.as_string(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::String(value) = value {
            let mut ret = String::with_capacity(value.len());
            let mut char_iter = value.chars();
            while let Some(ch) = char_iter.next() {
                match ch {
                    '\\' => {
                        match char_iter.next() {
                            Some('"') => {ret.push('"');}
                            Some('/') => {ret.push('/');}
                            Some('n') => {ret.push('\n');}
                            Some('r') => {ret.push('\r');}
                            Some('t') => {ret.push('\t');}
                            Some('\\') => {ret.push('\\');}
                            Some('f') => {ret.push('\u{000c}');}
                            Some('b') => {ret.push('\u{0008}');}
                            Some('u') => {
                                ret.push(parse_unicode_codepoint(&mut char_iter)?);
                            }
                            Some(s) => return Err(ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\{}", s)))),
                            None => return Err(ParseError::LexerError(LexerError::UnterminatedString)),
                        }
                    },
                    ch => {ret.push(ch);}
                }
            }
            Ok(ret.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
});

fn parse_unicode_codepoint<'a, I>(char_iter: &mut I) -> Result<char, ParseError<'a>>
where
    I: Iterator<Item = char>,
{
    let escaped_code_point = char_iter
        .next()
        .ok_or_else(|| {
            ParseError::LexerError(LexerError::UnknownEscapeSequence(String::from("\\u")))
        })
        .and_then(|c1| {
            char_iter
                .next()
                .map(|c2| format!("{}{}", c1, c2))
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{}", c1)))
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })?;
    let code_point = u32::from_str_radix(&escaped_code_point, 16).map_err(|_| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })?;
    char::from_u32(code_point).ok_or_else(|| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })
}

impl<'a, S> GraphQLType<S> for &'a str
where
    S: ScalarValue,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    type Context = ();
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("String")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
        for<'b> &'b S: ScalarRefValue<'b>,
    {
        registry.build_scalar_type::<String>(&()).into_meta()
    }

    fn resolve(
        &self,
        _: &(),
        _: Option<&[Selection<S>]>,
        _: &Executor<Self::Context, S>,
    ) -> Value<S> {
        Value::scalar(String::from(*self))
    }
}

#[cfg(feature = "async")]
impl<'e, S> crate::GraphQLTypeAsync<S> for &'e str
where
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::Value<S>> {
        use futures::future;
        future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
    }
}

impl<'a, S> ToInputValue<S> for &'a str
where
    S: ScalarValue,
{
    fn to_input_value(&self) -> InputValue<S> {
        InputValue::scalar(String::from(*self))
    }
}

graphql_scalar!(bool as "Boolean" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<bool> {
        match *v {
            InputValue::Scalar(ref b) => b.as_boolean(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S > {
        // Bools are parsed on it's own. This should not hit this code path
        Err(ParseError::UnexpectedToken(Token::Scalar(value)))
    }
});

graphql_scalar!(i32 as "Int" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<i32> {
        match *v {
            InputValue::Scalar(ref i) => i.as_int(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::Int(v) = value {
            v.parse()
             .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
             .map(|s: i32| s.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
});

graphql_scalar!(f64 as "Float" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<f64> {
        match *v {
            InputValue::Scalar(ref s) => s.as_float(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::Int(v) | ScalarToken::Float(v) => {
                v.parse()
                 .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                 .map(|s: f64| s.into())
            }
            ScalarToken::String(_) => {
                Err(ParseError::UnexpectedToken(Token::Scalar(value)))
            }
        }
    }
});

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the mutation, no mutation will be
/// generated for the schema.
#[derive(Debug)]
pub struct EmptyMutation<T> {
    phantom: PhantomData<T>,
}

impl<T> EmptyMutation<T> {
    /// Construct a new empty mutation
    pub fn new() -> EmptyMutation<T> {
        EmptyMutation {
            phantom: PhantomData,
        }
    }
}

impl<S, T> GraphQLType<S> for EmptyMutation<T>
where
    S: ScalarValue,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptyMutation")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
        for<'b> &'b S: ScalarRefValue<'b>,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

#[cfg(feature = "async")]
impl<S, T> crate::GraphQLTypeAsync<S> for EmptyMutation<T>
where
    S: ScalarValue + Send + Sync,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
}

#[cfg(test)]
mod tests {
    use super::ID;
    use crate::{
        parser::ScalarToken,
        value::{DefaultScalarValue, ParseScalarValue},
    };

    #[test]
    fn test_id_from_string() {
        let actual = ID::from(String::from("foo"));
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_new() {
        let actual = ID::new("foo");
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_deref() {
        let id = ID(String::from("foo"));
        assert_eq!(id.len(), 3);
    }

    #[test]
    fn parse_strings() {
        fn parse_string(s: &str, expected: &str) {
            let s =
                <String as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::String(s));
            assert!(s.is_ok(), "A parsing error occurred: {:?}", s);
            let s: Option<String> = s.unwrap().into();
            assert!(s.is_some(), "No string returned");
            assert_eq!(s.unwrap(), expected);
        }

        parse_string("simple", "simple");
        parse_string(" white space ", " white space ");
        parse_string(r#"quote \""#, "quote \"");
        parse_string(r#"escaped \n\r\b\t\f"#, "escaped \n\r\u{0008}\t\u{000c}");
        parse_string(r#"slashes \\ \/"#, "slashes \\ /");
        parse_string(
            r#"unicode \u1234\u5678\u90AB\uCDEF"#,
            "unicode \u{1234}\u{5678}\u{90ab}\u{cdef}",
        );
    }
}
<commit_msg>Make EmptyMutation `Send`<commit_after>use serde_derive::{Deserialize, Serialize};
use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};

use crate::{
    ast::{InputValue, Selection, ToInputValue},
    executor::{Executor, Registry},
    parser::{LexerError, ParseError, ScalarToken, Token},
    schema::meta::MetaType,
    types::base::GraphQLType,
    value::{ParseScalarResult, ScalarRefValue, ScalarValue, Value},
};

/// An ID as defined by the GraphQL specification
///
/// Represented as a string, but can be converted _to_ from an integer as well.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ID(String);

impl From<String> for ID {
    fn from(s: String) -> ID {
        ID(s)
    }
}

impl ID {
    /// Construct a new ID from anything implementing `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        ID(value.into())
    }
}

impl Deref for ID {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

graphql_scalar!(ID as "ID" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(self.0.clone())
    }

    from_input_value(v: &InputValue) -> Option<ID> {
        match *v {
            InputValue::Scalar(ref s) => {
                s.as_string().or_else(|| s.as_int().map(|i| i.to_string()))
                    .map(ID)
            }
            _ => None
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::String(value) | ScalarToken::Int(value) => {
                Ok(S::from(value.to_owned()))
            }
            _ => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
});

graphql_scalar!(String as "String" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(self.clone())
    }

    from_input_value(v: &InputValue) -> Option<String> {
        match *v {
            InputValue::Scalar(ref s) => s.as_string(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::String(value) = value {
            let mut ret = String::with_capacity(value.len());
            let mut char_iter = value.chars();
            while let Some(ch) = char_iter.next() {
                match ch {
                    '\\' => {
                        match char_iter.next() {
                            Some('"') => {ret.push('"');}
                            Some('/') => {ret.push('/');}
                            Some('n') => {ret.push('\n');}
                            Some('r') => {ret.push('\r');}
                            Some('t') => {ret.push('\t');}
                            Some('\\') => {ret.push('\\');}
                            Some('f') => {ret.push('\u{000c}');}
                            Some('b') => {ret.push('\u{0008}');}
                            Some('u') => {
                                ret.push(parse_unicode_codepoint(&mut char_iter)?);
                            }
                            Some(s) => return Err(ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\{}", s)))),
                            None => return Err(ParseError::LexerError(LexerError::UnterminatedString)),
                        }
                    },
                    ch => {ret.push(ch);}
                }
            }
            Ok(ret.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
});

fn parse_unicode_codepoint<'a, I>(char_iter: &mut I) -> Result<char, ParseError<'a>>
where
    I: Iterator<Item = char>,
{
    let escaped_code_point = char_iter
        .next()
        .ok_or_else(|| {
            ParseError::LexerError(LexerError::UnknownEscapeSequence(String::from("\\u")))
        })
        .and_then(|c1| {
            char_iter
                .next()
                .map(|c2| format!("{}{}", c1, c2))
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{}", c1)))
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })?;
    let code_point = u32::from_str_radix(&escaped_code_point, 16).map_err(|_| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })?;
    char::from_u32(code_point).ok_or_else(|| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })
}

impl<'a, S> GraphQLType<S> for &'a str
where
    S: ScalarValue,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    type Context = ();
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("String")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
        for<'b> &'b S: ScalarRefValue<'b>,
    {
        registry.build_scalar_type::<String>(&()).into_meta()
    }

    fn resolve(
        &self,
        _: &(),
        _: Option<&[Selection<S>]>,
        _: &Executor<Self::Context, S>,
    ) -> Value<S> {
        Value::scalar(String::from(*self))
    }
}

#[cfg(feature = "async")]
impl<'e, S> crate::GraphQLTypeAsync<S> for &'e str
where
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::Value<S>> {
        use futures::future;
        future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
    }
}

impl<'a, S> ToInputValue<S> for &'a str
where
    S: ScalarValue,
{
    fn to_input_value(&self) -> InputValue<S> {
        InputValue::scalar(String::from(*self))
    }
}

graphql_scalar!(bool as "Boolean" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<bool> {
        match *v {
            InputValue::Scalar(ref b) => b.as_boolean(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S > {
        // Bools are parsed on it's own. This should not hit this code path
        Err(ParseError::UnexpectedToken(Token::Scalar(value)))
    }
});

graphql_scalar!(i32 as "Int" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<i32> {
        match *v {
            InputValue::Scalar(ref i) => i.as_int(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::Int(v) = value {
            v.parse()
             .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
             .map(|s: i32| s.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
});

graphql_scalar!(f64 as "Float" where Scalar = <S>{
    resolve(&self) -> Value {
        Value::scalar(*self)
    }

    from_input_value(v: &InputValue) -> Option<f64> {
        match *v {
            InputValue::Scalar(ref s) => s.as_float(),
            _ => None,
        }
    }

    from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::Int(v) | ScalarToken::Float(v) => {
                v.parse()
                 .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                 .map(|s: f64| s.into())
            }
            ScalarToken::String(_) => {
                Err(ParseError::UnexpectedToken(Token::Scalar(value)))
            }
        }
    }
});

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the mutation, no mutation will be
/// generated for the schema.
#[derive(Debug)]
pub struct EmptyMutation<T> {
    phantom: PhantomData<T>,
}

impl<T> EmptyMutation<T> {
    /// Construct a new empty mutation
    pub fn new() -> EmptyMutation<T> {
        EmptyMutation {
            phantom: PhantomData,
        }
    }
}

// This is safe due to never using `T`.
unsafe impl<T> Send for EmptyMutation<T> {}

impl<S, T> GraphQLType<S> for EmptyMutation<T>
where
    S: ScalarValue,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptyMutation")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
        for<'b> &'b S: ScalarRefValue<'b>,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

#[cfg(feature = "async")]
impl<S, T> crate::GraphQLTypeAsync<S> for EmptyMutation<T>
where
    S: ScalarValue + Send + Sync,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
}

#[cfg(test)]
mod tests {
    use super::{EmptyMutation, ID};
    use crate::{
        parser::ScalarToken,
        value::{DefaultScalarValue, ParseScalarValue},
    };

    #[test]
    fn test_id_from_string() {
        let actual = ID::from(String::from("foo"));
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_new() {
        let actual = ID::new("foo");
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_deref() {
        let id = ID(String::from("foo"));
        assert_eq!(id.len(), 3);
    }

    #[test]
    fn parse_strings() {
        fn parse_string(s: &str, expected: &str) {
            let s =
                <String as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::String(s));
            assert!(s.is_ok(), "A parsing error occurred: {:?}", s);
            let s: Option<String> = s.unwrap().into();
            assert!(s.is_some(), "No string returned");
            assert_eq!(s.unwrap(), expected);
        }

        parse_string("simple", "simple");
        parse_string(" white space ", " white space ");
        parse_string(r#"quote \""#, "quote \"");
        parse_string(r#"escaped \n\r\b\t\f"#, "escaped \n\r\u{0008}\t\u{000c}");
        parse_string(r#"slashes \\ \/"#, "slashes \\ /");
        parse_string(
            r#"unicode \u1234\u5678\u90AB\uCDEF"#,
            "unicode \u{1234}\u{5678}\u{90ab}\u{cdef}",
        );
    }

    #[test]
    fn empty_mutation_is_send() {
        fn check_if_send<T: Send>() {}
        check_if_send::<EmptyMutation<()>>();
    }
}
<|endoftext|>


<commit_before>use crate::proto::grpc_status::GrpcStatus;
use crate::Metadata;
use httpbis::BytesDeque;
use httpbis::Header;
use httpbis::Headers;

pub(crate) static HEADER_GRPC_STATUS: &'static str = "grpc-status";
pub(crate) static HEADER_GRPC_MESSAGE: &'static str = "grpc-message";

pub(crate) fn headers_500(grpc_status: GrpcStatus, message: String) -> Headers {
    Headers::from_vec(vec![
        Header::new(":status", "500"),
        Header::new(HEADER_GRPC_STATUS, format!("{}", grpc_status as i32)),
        Header::new(HEADER_GRPC_MESSAGE, message),
    ])
}

pub(crate) fn headers_200(metadata: Metadata) -> Headers {
    let mut headers = Headers::from_vec(vec![
        // TODO: do not allocate
        Header::new(":status", "200"),
        Header::new("content-type", "application/grpc"),
        Header::new(HEADER_GRPC_STATUS, "0"),
    ]);
    headers.extend(metadata.into_headers());
    headers
}

/// Create HTTP response for gRPC error
pub(crate) fn grpc_error_message(message: &str) -> httpbis::SimpleHttpMessage {
    let headers = Headers::from_vec(vec![
        Header::new(":status", "200"),
        // TODO: alloc
        Header::new(
            HEADER_GRPC_STATUS,
            format!("{}", GrpcStatus::Internal.code()),
        ),
        Header::new(HEADER_GRPC_MESSAGE, message.to_owned()),
    ]);
    httpbis::SimpleHttpMessage {
        headers,
        body: BytesDeque::new(),
    }
}

// Trailers -> Status [Status-Message] *Custom-Metadata
pub(crate) fn trailers(
    grpc_status: GrpcStatus,
    message: Option<String>,
    metadata: Metadata,
) -> Headers {
    let mut headers = Headers::from_vec(vec![Header::new(
        HEADER_GRPC_STATUS,
        format!("{}", grpc_status as i32),
    )]);
    if let Some(message) = message {
        headers.add_header(Header::new(HEADER_GRPC_MESSAGE, message));
    }
    headers.extend(metadata.into_headers());
    headers
}
<commit_msg>add content-type in headers_500 function<commit_after>use crate::proto::grpc_status::GrpcStatus;
use crate::Metadata;
use httpbis::BytesDeque;
use httpbis::Header;
use httpbis::Headers;

pub(crate) static HEADER_GRPC_STATUS: &'static str = "grpc-status";
pub(crate) static HEADER_GRPC_MESSAGE: &'static str = "grpc-message";

pub(crate) fn headers_500(grpc_status: GrpcStatus, message: String) -> Headers {
    Headers::from_vec(vec![
        Header::new(":status", "500"),
        Header::new("content-type", "application/grpc"),
        Header::new(HEADER_GRPC_STATUS, format!("{}", grpc_status as i32)),
        Header::new(HEADER_GRPC_MESSAGE, message),
    ])
}

pub(crate) fn headers_200(metadata: Metadata) -> Headers {
    let mut headers = Headers::from_vec(vec![
        // TODO: do not allocate
        Header::new(":status", "200"),
        Header::new("content-type", "application/grpc"),
        Header::new(HEADER_GRPC_STATUS, "0"),
    ]);
    headers.extend(metadata.into_headers());
    headers
}

/// Create HTTP response for gRPC error
pub(crate) fn grpc_error_message(message: &str) -> httpbis::SimpleHttpMessage {
    let headers = Headers::from_vec(vec![
        Header::new(":status", "200"),
        // TODO: alloc
        Header::new(
            HEADER_GRPC_STATUS,
            format!("{}", GrpcStatus::Internal.code()),
        ),
        Header::new(HEADER_GRPC_MESSAGE, message.to_owned()),
    ]);
    httpbis::SimpleHttpMessage {
        headers,
        body: BytesDeque::new(),
    }
}

// Trailers -> Status [Status-Message] *Custom-Metadata
pub(crate) fn trailers(
    grpc_status: GrpcStatus,
    message: Option<String>,
    metadata: Metadata,
) -> Headers {
    let mut headers = Headers::from_vec(vec![Header::new(
        HEADER_GRPC_STATUS,
        format!("{}", grpc_status as i32),
    )]);
    if let Some(message) = message {
        headers.add_header(Header::new(HEADER_GRPC_MESSAGE, message));
    }
    headers.extend(metadata.into_headers());
    headers
}
<|endoftext|>