<commit_before>import std::time;
import std::time::tm;

type cookie = {
    name: str,
    value: str,
    mut path: option<str>,
    mut domain: option<str>,
    mut max_age: option<uint>,
    mut secure: bool,
    mut http_only: bool
};

fn cookie(name: str, value: str) -> cookie {
    {
        name: name,
        value: value,
        mut path: none,
        mut domain: none,
        mut max_age: none,
        mut secure: false,
        mut http_only: false
    }
}

impl cookie for cookie {
    fn to_header() -> result<str, str> {
        // FIXME: Move error checking to the constructor.

        if !cookie_parser::is_name(self.name) {
            ret err("invalid name");
        }

        let mut cookie = if self.value == "" {
            [self.name + "="]
        } else {
            if !cookie_parser::is_value(self.value) {
                ret err("invalid value");
            }

            [self.name + "=" + self.value]
        };

        alt self.domain {
          none {}
          some(domain) {
            if cookie_parser::is_domain(domain) {
                vec::push(cookie, "domain=" + domain);
            } else {
                ret err("invalid domain");
            }
          }
        }

        alt self.path {
          none {}
          some(path) {
            if cookie_parser::is_path(path) {
                vec::push(cookie, "path=" + path);
            } else {
                ret err("invalid path");
            }
          }
        }

        alt self.max_age {
          none {}
          some(max_age) {
            let tm = if max_age == 0u {
                std::time::at({ sec: 0_i64, nsec: 0_i32 })
            } else {
                let t = std::time::get_time();
                std::time::at_utc({ sec: t.sec + max_age as i64, nsec: 0_i32 })
            };

            // Not every browser supports max-age...
            //vec::push(cookie, "max-age=" + uint::str(max_age));

            vec::push(cookie, "expires=" + tm.rfc822());
          }
        }

        if self.secure    { vec::push(cookie, "Secure"); }
        if self.http_only { vec::push(cookie, "HttpOnly"); }

        ok(str::connect(cookie, "; "))
    }
}

fn parse_header(header: str) -> result<[cookie], str> {
    let header = header.trim();

    // Exit early if empty.
    if header == "" { ret err("empty cookie") }

    let mut cookies = [];

    for header.split_char(';').each { |line|
        let parts = str::splitn_char(line, '=', 1u);

        let (name, value) = if parts.len() == 1u {
            ret err("empty cookie value")
        } else {
            (parts[0u].trim(), parts[1u].trim())
        };

        if !cookie_parser::is_name(name) {
            ret err(#fmt("invalid cookie name: %?", name));
        }

        if !cookie_parser::is_value(value) {
            ret err(#fmt("invalid cookie value: %?", value));
        }

        vec::push(cookies, cookie(name, value));
    }

    ok(cookies)
}

fn parse_headers(headers: [str]) -> result<hashmap<str, cookie>, str> {
    let mut cookies = str_hash();

    for headers.each { |header|
        alt parse_header(header) {
          ok(cs) { cs.iter { |cookie| cookies.insert(cookie.name, cookie); } }
          err(e) { ret err(e); }
        }
    }

    ok(cookies)
}

#[doc = "
Helper functions for parsing cookies according to RFC 6265, Section 4.1.
"]
mod cookie_parser {
    fn is_name(name: str) -> bool {
        http_parser::is_token(name)
    }

    fn is_cookie_octet(ch: char) -> bool {
        if !char::is_ascii(ch) { ret false; }

        alt ch {
            '\x21' | '\x23' to '\x2b' | '\x2D' to '\x3A' | '\x3C' to '\x5B'
          | '\x5D' to '\x7E' { true }
          _ { false }
        }
    }

    fn is_value(value: str) -> bool {
        let mut pos = 0u;
        let len = value.len();

        // Exit early if we have an empty string.
        if len == 0u { ret true; }

        // Check if the value is surrounded by double quotes.
        let {ch, next} = str::char_range_at(value, pos);

        let quoted = if ch == '"' {
            pos = next;
            if pos == len { ret false; }

            true
        } else {
            false
        };

        while pos < len {
            let {ch, next} = str::char_range_at(value, pos);

            if quoted && ch == '"' {
                ret next == len;
            }

            if !is_cookie_octet(ch) { ret false; }

            pos = next;
        }

        !quoted && pos == len
    }

    fn is_domain(_domain: str) -> bool {
        // FIXME: Actually implement.
        true
    }

    fn is_path(path: str) -> bool {
        for path.each_char { |ch|
            if !char::is_ascii(ch) || http_parser::is_ctl(ch) || ch == ';' {
                ret false;
            }
        }

        true
    }
}

#[doc = "
Helper functions for parsing http according to RFC 2616, Section 2.2.
"]
mod http_parser {
    fn is_char(ch: char) -> bool {
        char::is_ascii(ch)
    }

    fn is_ctl(ch: char) -> bool {
        alt ch {
          '\x00' to '\x1f' | '\x7f' { true }
          _ { false }
        }
    }

    fn is_separator(ch: char) -> bool {
        alt ch {
            '(' | ')' | '<' | '>'  | '@'
          | ',' | ';' | ':' | '\\' | '"'
          | '/' | '[' | ']' | '?'  | '='
          | '{' | '}' | ' ' | '\t' { true }
          _ { false }
        }
    }

    fn is_token(token: str) -> bool {
        if token.len() == 0u { ret false; }

        for token.each_char { |ch|
            if !is_char(ch) || is_ctl(ch) || is_separator(ch) {
                ret false;
            }
        }

        true
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_is_cookie_octet() {
        assert  cookie_parser::is_cookie_octet('A');
        assert !cookie_parser::is_cookie_octet('"');
    }

    #[test]
    fn test_is_value() {
        assert !cookie_parser::is_value("");
        assert !cookie_parser::is_value("\"");
        assert !cookie_parser::is_value("\"a");
        assert !cookie_parser::is_value("foo bar");
        assert !cookie_parser::is_value("foo\"");
        assert !cookie_parser::is_value("\"foo");

        assert cookie_parser::is_value("\"\"");
        assert cookie_parser::is_value("foo");;
        assert cookie_parser::is_value("\"foo\"");;
    }
}
<commit_msg>Fix the cookie test.<commit_after>import std::time;
import std::time::tm;

type cookie = {
    name: str,
    value: str,
    mut path: option<str>,
    mut domain: option<str>,
    mut max_age: option<uint>,
    mut secure: bool,
    mut http_only: bool
};

fn cookie(name: str, value: str) -> cookie {
    {
        name: name,
        value: value,
        mut path: none,
        mut domain: none,
        mut max_age: none,
        mut secure: false,
        mut http_only: false
    }
}

impl cookie for cookie {
    fn to_header() -> result<str, str> {
        // FIXME: Move error checking to the constructor.

        if !cookie_parser::is_name(self.name) {
            ret err("invalid name");
        }

        let mut cookie = if self.value == "" {
            [self.name + "="]
        } else {
            if !cookie_parser::is_value(self.value) {
                ret err("invalid value");
            }

            [self.name + "=" + self.value]
        };

        alt self.domain {
          none {}
          some(domain) {
            if cookie_parser::is_domain(domain) {
                vec::push(cookie, "domain=" + domain);
            } else {
                ret err("invalid domain");
            }
          }
        }

        alt self.path {
          none {}
          some(path) {
            if cookie_parser::is_path(path) {
                vec::push(cookie, "path=" + path);
            } else {
                ret err("invalid path");
            }
          }
        }

        alt self.max_age {
          none {}
          some(max_age) {
            let tm = if max_age == 0u {
                std::time::at({ sec: 0_i64, nsec: 0_i32 })
            } else {
                let t = std::time::get_time();
                std::time::at_utc({ sec: t.sec + max_age as i64, nsec: 0_i32 })
            };

            // Not every browser supports max-age...
            //vec::push(cookie, "max-age=" + uint::str(max_age));

            vec::push(cookie, "expires=" + tm.rfc822());
          }
        }

        if self.secure    { vec::push(cookie, "Secure"); }
        if self.http_only { vec::push(cookie, "HttpOnly"); }

        ok(str::connect(cookie, "; "))
    }
}

fn parse_header(header: str) -> result<[cookie], str> {
    let header = header.trim();

    // Exit early if empty.
    if header == "" { ret err("empty cookie") }

    let mut cookies = [];

    for header.split_char(';').each { |line|
        let parts = str::splitn_char(line, '=', 1u);

        let (name, value) = if parts.len() == 1u {
            ret err("empty cookie value")
        } else {
            (parts[0u].trim(), parts[1u].trim())
        };

        if !cookie_parser::is_name(name) {
            ret err(#fmt("invalid cookie name: %?", name));
        }

        if !cookie_parser::is_value(value) {
            ret err(#fmt("invalid cookie value: %?", value));
        }

        vec::push(cookies, cookie(name, value));
    }

    ok(cookies)
}

fn parse_headers(headers: [str]) -> result<hashmap<str, cookie>, str> {
    let mut cookies = str_hash();

    for headers.each { |header|
        alt parse_header(header) {
          ok(cs) { cs.iter { |cookie| cookies.insert(cookie.name, cookie); } }
          err(e) { ret err(e); }
        }
    }

    ok(cookies)
}

#[doc = "
Helper functions for parsing cookies according to RFC 6265, Section 4.1.
"]
mod cookie_parser {
    fn is_name(name: str) -> bool {
        http_parser::is_token(name)
    }

    fn is_cookie_octet(ch: char) -> bool {
        if !char::is_ascii(ch) { ret false; }

        alt ch {
            '\x21' | '\x23' to '\x2b' | '\x2D' to '\x3A' | '\x3C' to '\x5B'
          | '\x5D' to '\x7E' { true }
          _ { false }
        }
    }

    fn is_value(value: str) -> bool {
        let mut pos = 0u;
        let len = value.len();

        // Exit early if we have an empty string.
        if len == 0u { ret true; }

        // Check if the value is surrounded by double quotes.
        let {ch, next} = str::char_range_at(value, pos);

        let quoted = if ch == '"' {
            pos = next;
            if pos == len { ret false; }

            true
        } else {
            false
        };

        while pos < len {
            let {ch, next} = str::char_range_at(value, pos);

            if quoted && ch == '"' {
                ret next == len;
            }

            if !is_cookie_octet(ch) { ret false; }

            pos = next;
        }

        !quoted && pos == len
    }

    fn is_domain(_domain: str) -> bool {
        // FIXME: Actually implement.
        true
    }

    fn is_path(path: str) -> bool {
        for path.each_char { |ch|
            if !char::is_ascii(ch) || http_parser::is_ctl(ch) || ch == ';' {
                ret false;
            }
        }

        true
    }
}

#[doc = "
Helper functions for parsing http according to RFC 2616, Section 2.2.
"]
mod http_parser {
    fn is_char(ch: char) -> bool {
        char::is_ascii(ch)
    }

    fn is_ctl(ch: char) -> bool {
        alt ch {
          '\x00' to '\x1f' | '\x7f' { true }
          _ { false }
        }
    }

    fn is_separator(ch: char) -> bool {
        alt ch {
            '(' | ')' | '<' | '>'  | '@'
          | ',' | ';' | ':' | '\\' | '"'
          | '/' | '[' | ']' | '?'  | '='
          | '{' | '}' | ' ' | '\t' { true }
          _ { false }
        }
    }

    fn is_token(token: str) -> bool {
        if token.len() == 0u { ret false; }

        for token.each_char { |ch|
            if !is_char(ch) || is_ctl(ch) || is_separator(ch) {
                ret false;
            }
        }

        true
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_is_cookie_octet() {
        assert  cookie_parser::is_cookie_octet('A');
        assert !cookie_parser::is_cookie_octet('"');
    }

    #[test]
    fn test_is_value() {
        assert !cookie_parser::is_value("\"");
        assert !cookie_parser::is_value("\"a");
        assert !cookie_parser::is_value("foo bar");
        assert !cookie_parser::is_value("foo\"");
        assert !cookie_parser::is_value("\"foo");

        assert cookie_parser::is_value("");
        assert cookie_parser::is_value("\"\"");
        assert cookie_parser::is_value("foo");;
        assert cookie_parser::is_value("\"foo\"");;
    }
}
<|endoftext|>


<commit_before>extern mod std;

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA224(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA256(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA384(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA512(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

enum HashEngine { MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }

struct Digest { digest: ~[u8] }

impl Digest {
    fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

    fn hexdigest(&self) -> ~str {
        let mut acc = ~"";
        for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
        acc
    }
}

fn hash(data: ~[u8], hash_func: &fn(*u8, libc::c_uint, *u8) -> *u8, len: uint) -> ~Digest {
    Digest::new(
      unsafe {
        vec::from_buf(
          hash_func(
            vec::raw::to_ptr(data),
            data.len() as libc::c_uint, ptr::null()
          ),
          len
        )
      }
    )
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA1, 20)
  }
}

fn sha224(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA224, 28)
  }
}

fn sha256(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA256, 32)
  }
}

fn sha384(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA384, 48)
  }
}

fn sha512(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA512, 64)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::MD5, 16)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac_md5(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, md5)
}

fn hmac_sha1(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha1)
}

fn hmac_sha256(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha256)
}

fn hmac_sha512(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 128, sha512)
}

fn hmac(key: ~str, message: ~str, block_size: uint, hash_func: &fn(~[u8]) -> ~Digest) -> ~Digest {
  let computed_key: &str = match key.len() {
    _ if key.len() > block_size => hash_func(key.to_bytes()).hexdigest(), // TODO this should be .digest more likely
    _ if key.len() < block_size => key + str::from_bytes(vec::from_elem(block_size - key.len(), 0)),
    _ => key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  hash_func(o_key_pad + hash_func(i_key_pad + bin_message).digest)
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1() {
  assert_eq!(
    hmac_sha1(~"my key", ~"some data to hmac").hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac_sha256(~"my key", ~"some data to hmac").hexdigest(),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac_sha512(~"my key", ~"some data to hmac").hexdigest(),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5(~"my key", ~"some data to hmac").hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<commit_msg>Do dynamic lookup of hash engine, lots of refactoring.<commit_after>extern mod std;

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA224(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA256(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA384(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn SHA512(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

enum HashMethod { MD5, SHA1, SHA224, SHA256, SHA384, SHA512 }

struct HashEngine {
  engine:      (extern unsafe fn(*u8, libc::c_uint, *u8) -> *u8),
  digest_size: uint,
  block_size:  uint
}

impl HashEngine {
  fn by_name(engine: HashMethod) -> ~HashEngine {
    unsafe {
      match engine {
        MD5    => ~HashEngine{ engine: crypto::MD5,    digest_size: 16, block_size: 64  },
        SHA1   => ~HashEngine{ engine: crypto::SHA1,   digest_size: 20, block_size: 64  },
        SHA224 => ~HashEngine{ engine: crypto::SHA224, digest_size: 28, block_size: 64  },
        SHA256 => ~HashEngine{ engine: crypto::SHA256, digest_size: 32, block_size: 64  },
        SHA384 => ~HashEngine{ engine: crypto::SHA384, digest_size: 48, block_size: 64  },
        SHA512 => ~HashEngine{ engine: crypto::SHA512, digest_size: 64, block_size: 128 }
      }
    }
  }

  fn hash(&self, data: ~[u8]) -> ~Digest {
    let hash_func = self.engine;
    Digest::new(
      unsafe {
        vec::from_buf(
          hash_func(
            vec::raw::to_ptr(data),
            data.len() as libc::c_uint, ptr::null()
          ),
          self.digest_size
        )
      }
    )
  }
}

struct Digest { digest: ~[u8] }

impl Digest {
  fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

  fn hexdigest(&self) -> ~str {
    let mut acc = ~"";
    for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
    acc
  }
}

fn hash(engine_name: HashMethod, data: ~[u8]) -> ~Digest {
  let details   = HashEngine::by_name(engine_name);
  let hash_func = details.engine;

  Digest::new(
    unsafe {
      vec::from_buf(
        hash_func(
          vec::raw::to_ptr(data),
          data.len() as libc::c_uint, ptr::null()
        ),
        details.digest_size
      )
    }
  )
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(SHA1).hash(data)
  }
}

fn sha224(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(SHA224).hash(data)
  }
}

fn sha256(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(SHA256).hash(data)
  }
}

fn sha384(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(SHA384).hash(data)
  }
}

fn sha512(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(SHA512 ).hash(data)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    HashEngine::by_name(MD5).hash(data)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac_md5(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, md5)
}

fn hmac_sha1(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha1)
}

fn hmac_sha256(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha256)
}

fn hmac_sha512(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 128, sha512)
}

fn hmac(key: ~str, message: ~str, block_size: uint, hash_func: &fn(~[u8]) -> ~Digest) -> ~Digest {
  let computed_key: &str = match key.len() {
    _ if key.len() > block_size => hash_func(key.to_bytes()).hexdigest(), // TODO this should be .digest more likely
    _ if key.len() < block_size => key + str::from_bytes(vec::from_elem(block_size - key.len(), 0)),
    _ => key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  hash_func(o_key_pad + hash_func(i_key_pad + bin_message).digest)
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1() {
  assert_eq!(
    hmac_sha1(~"my key", ~"some data to hmac").hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac_sha256(~"my key", ~"some data to hmac").hexdigest(),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac_sha512(~"my key", ~"some data to hmac").hexdigest(),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5(~"my key", ~"some data to hmac").hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<|endoftext|>


<commit_before>extern crate rsoundio;

use std::os::raw::c_int;
use std::f32::consts;
use std::thread;
use std::time::Duration;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Dummy).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let mut frames: Vec<Vec<f32>> = vec![vec![], vec![]];
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let f = 4400f32;
    let sr = stream.get_sample_rate();
    let layout = stream.get_layout();
    let channels = layout.channel_count();
    let phi = 2.0 * f * consts::PI / (sr as f32);
    let l: Vec<f32> = (0..4800).map(|i| f32::sin(i as f32 * phi)).collect();
    let r = l.clone();
    frames = vec![l, r];
    let cb = |out: rsoundio::OutStream, min_frame_count: i32, max_frame_count: i32| {
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    };
    stream.register_write_callback(Box::new(cb));
    let ucb = |out: rsoundio::OutStream| println!("Underflow!");
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = |out: rsoundio::OutStream, err: rsoundio::ffi::SioError| println!("Error: {}", err);
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    sio.wait_events();
    println!("Received event!");
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}
<commit_msg>Use buffer with a power of two size<commit_after>extern crate rsoundio;

use std::os::raw::c_int;
use std::f32::consts;
use std::thread;
use std::time::Duration;

#[test]
fn test_outstream() {
    println!("test: OutStream");
    let sio = rsoundio::SoundIo::new();
    assert!(sio.connect_backend(rsoundio::ffi::SioBackend::Dummy).is_none());
    println!("current backend: {}", sio.current_backend().unwrap());
    sio.flush_events();
    let fmt;
    let dev_idx = sio.default_output_device_index().unwrap();
    let mut frames: Vec<Vec<f32>> = vec![vec![], vec![]];
    let dev = sio.get_output_device(dev_idx).unwrap();
    println!("device: {}, ref_count: {}", dev, dev.ref_count());
    let mut stream = dev.create_outstream().unwrap();
    assert!(stream.open().is_none());
    fmt = stream.current_format().unwrap();
    println!("current format: {}", fmt);
    let f = 4400f32;
    let sr = stream.get_sample_rate();
    let layout = stream.get_layout();
    let channels = layout.channel_count();
    let phi = 2.0 * f * consts::PI / (sr as f32);
    let l: Vec<f32> = (0..4096).map(|i| f32::sin(i as f32 * phi)).collect();
    let r = l.clone();
    frames = vec![l, r];
    let cb = |out: rsoundio::OutStream, min_frame_count: i32, max_frame_count: i32| {
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    };
    stream.register_write_callback(Box::new(cb));
    let ucb = |out: rsoundio::OutStream| println!("Underflow!");
    stream.register_underflow_callback(Box::new(ucb));
    let ecb = |out: rsoundio::OutStream, err: rsoundio::ffi::SioError| println!("Error: {}", err);
    stream.register_error_callback(Box::new(ecb));
    assert!(stream.start().is_none());
    sio.wait_events();
    println!("Received event!");
    assert!(stream.clear_buffer().is_none());
    assert!(stream.pause(true).is_none());
    assert!(stream.pause(false).is_none());
    println!("latency: {}", stream.get_latency().unwrap());
    stream.destroy();
}
<|endoftext|>


<commit_before>generate_error_imports!();

generate_error_types!(ListError, ListErrorKind,
    FormatError    => "FormatError",
    EntryError     => "EntryError",
    IterationError => "IterationError",
    CLIError       => "No CLI subcommand for listing entries"
);

<commit_msg>libimagentrylist: use generate_error_module!() macro and reexport generated types<commit_after>generate_error_module!(
    generate_error_types!(ListError, ListErrorKind,
        FormatError    => "FormatError",
        EntryError     => "EntryError",
        IterationError => "IterationError",
        CLIError       => "No CLI subcommand for listing entries"
    );
);

pub use self::error::ListError;
pub use self::error::ListErrorKind;

<|endoftext|>


<commit_before>use actix::prelude::*;
use godcoin::prelude::*;

mod common;
pub use common::*;

#[test]
fn basic_transfer() {
    System::run(|| {
        let minter = TestMinter::new();
        let to_addr = KeyPair::gen();

        let create_tx = |fee: &str, amount: Asset| {
            let mut tx = TransferTx {
                base: create_tx_header(TxType::TRANSFER, fee),
                from: (&minter.genesis_info().script).into(),
                to: (&to_addr.0).into(),
                amount,
                memo: vec![],
                script: minter.genesis_info().script.clone(),
            };
            tx.append_sign(&minter.genesis_info().wallet_keys[3]);
            tx.append_sign(&minter.genesis_info().wallet_keys[0]);
            TxVariant::TransferTx(tx)
        };

        let bal = get_asset("1.0000 GRAEL");
        let tx = create_tx("1.0000 GRAEL", bal);
        let fut = minter.request(MsgRequest::Broadcast(tx));
        System::current().arbiter().send(
            fut.and_then(move |res| {
                assert_eq!(res, MsgResponse::Broadcast());
                minter.produce_block().map(|_| minter)
            })
            .and_then(move |minter| {
                let chain = minter.chain();
                let cur_bal = chain.get_balance(&to_addr.0.into(), &[]);
                assert_eq!(cur_bal, Some(bal));

                System::current().stop();
                Ok(())
            }),
        );
    })
    .unwrap();
}
<commit_msg>Assert the from address in transfers have their balances subtracted<commit_after>use actix::prelude::*;
use godcoin::prelude::*;

mod common;
pub use common::*;

#[test]
fn basic_transfer() {
    System::run(|| {
        let minter = TestMinter::new();
        let from_addr = ScriptHash::from(&minter.genesis_info().script);
        let to_addr = KeyPair::gen();

        let create_tx = |fee: &str, amount: Asset| {
            let mut tx = TransferTx {
                base: create_tx_header(TxType::TRANSFER, fee),
                from: from_addr.clone(),
                to: (&to_addr.0).into(),
                amount,
                memo: vec![],
                script: minter.genesis_info().script.clone(),
            };
            tx.append_sign(&minter.genesis_info().wallet_keys[3]);
            tx.append_sign(&minter.genesis_info().wallet_keys[0]);
            TxVariant::TransferTx(tx)
        };

        let from_bal = minter.chain().get_balance(&from_addr, &[]).unwrap();
        let amount = get_asset("1.0000 GRAEL");
        let tx = create_tx("1.0000 GRAEL", amount);
        let fut = minter.request(MsgRequest::Broadcast(tx));
        System::current().arbiter().send(
            fut.and_then(move |res| {
                assert_eq!(res, MsgResponse::Broadcast());
                minter.produce_block().map(|_| minter)
            })
            .and_then(move |minter| {
                let chain = minter.chain();
                let cur_bal = chain.get_balance(&to_addr.0.into(), &[]);
                assert_eq!(cur_bal, Some(amount));

                // The fee transfers back to the minter wallet in the form of a reward tx so it
                // must not be subtracted during the assertion
                let cur_bal = chain.get_balance(&from_addr, &[]);
                assert_eq!(cur_bal, from_bal.sub(amount));

                System::current().stop();
                Ok(())
            }),
        );
    })
    .unwrap();
}
<|endoftext|>


<commit_before>//! Provides [Alphabet] and constants for alphabets commonly used in the wild.

use crate::PAD_BYTE;
#[cfg(any(feature = "std", test))]
use std::{convert, error, fmt};

const ALPHABET_SIZE: usize = 64;

/// An alphabet defines the 64 ASCII characters (symbols) used for base64.
///
/// Common alphabets are provided as constants, and custom alphabets
/// can be made via `from_str` or the `TryFrom<str>` implementation.
///
/// ```
/// let custom = base64::alphabet::Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").unwrap();
///
/// let engine = base64::engine::fast_portable::FastPortable::from(
///     &custom,
///     base64::engine::fast_portable::PAD);
/// ```
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Alphabet {
    pub(crate) symbols: [u8; ALPHABET_SIZE],
}

impl Alphabet {
    /// Performs no checks so that it can be const.
    /// Used only for known-valid strings.
    const fn from_str_unchecked(alphabet: &str) -> Alphabet {
        let mut symbols = [0_u8; ALPHABET_SIZE];
        let source_bytes = alphabet.as_bytes();

        // a way to copy that's allowed in const fn
        let mut index = 0;
        while index < ALPHABET_SIZE {
            symbols[index] = source_bytes[index];
            index += 1;
        }

        Alphabet { symbols }
    }

    /// Create an `Alphabet` from a string of 64 unique printable ASCII bytes.
    ///
    /// The `=` byte is not allowed as it is used for padding.
    ///
    /// The `const`-ness of this function isn't useful as of rust 1.54.0 since `const` `unwrap()`,
    /// etc, haven't shipped yet, but that's [on the roadmap](https://github.com/rust-lang/rust/issues/85194).
    pub const fn from_str(alphabet: &str) -> Result<Self, ParseAlphabetError> {
        let bytes = alphabet.as_bytes();
        if bytes.len() != ALPHABET_SIZE {
            return Err(ParseAlphabetError::InvalidLength);
        }

        {
            let mut index = 0;
            while index < ALPHABET_SIZE {
                let byte = bytes[index];

                // must be ascii printable. 127 (DEL) is commonly considered printable
                // for some reason but clearly unsuitable for base64.
                if !(byte >= 32_u8 && byte <= 126_u8) {
                    return Err(ParseAlphabetError::UnprintableByte(byte));
                }
                // = is assumed to be padding, so cannot be used as a symbol
                if byte == PAD_BYTE {
                    return Err(ParseAlphabetError::ReservedByte(byte));
                }

                // Check for duplicates while staying within what const allows.
                // It's n^2, but only over 64 hot bytes, and only once, so it's likely in the single digit
                // microsecond range.

                let mut probe_index = 0;
                while probe_index < ALPHABET_SIZE {
                    if probe_index == index {
                        probe_index += 1;
                        continue;
                    }

                    let probe_byte = bytes[probe_index];

                    if byte == probe_byte {
                        return Err(ParseAlphabetError::DuplicatedByte(byte));
                    }

                    probe_index += 1;
                }

                index += 1;
            }
        }

        Ok(Self::from_str_unchecked(alphabet))
    }
}

#[cfg(any(feature = "std", test))]
impl convert::TryFrom<&str> for Alphabet {
    type Error = ParseAlphabetError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Alphabet::from_str(value)
    }
}

/// Possible errors when constructing an [Alphabet] from a `str`.
#[derive(Debug, Eq, PartialEq)]
pub enum ParseAlphabetError {
    /// Alphabets must be 64 ASCII bytes
    InvalidLength,
    /// All bytes must be unique
    DuplicatedByte(u8),
    /// All bytes must be printable (in the range `[32, 126]`).
    UnprintableByte(u8),
    /// `=` cannot be used
    ReservedByte(u8),
}

#[cfg(any(feature = "std", test))]
impl fmt::Display for ParseAlphabetError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseAlphabetError::InvalidLength => write!(f, "Invalid length - must be 64 bytes"),
            ParseAlphabetError::DuplicatedByte(b) => write!(f, "Duplicated byte: {:#04x}", b),
            ParseAlphabetError::UnprintableByte(b) => write!(f, "Unprintable byte: {:#04x}", b),
            ParseAlphabetError::ReservedByte(b) => write!(f, "Reserved byte: {:#04x}", b),
        }
    }
}

#[cfg(any(feature = "std", test))]
impl error::Error for ParseAlphabetError {}

/// The standard alphabet (uses `+` and `/`).
///
/// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3).
pub const STANDARD: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
);

/// The URL safe alphabet (uses `-` and `_`).
///
/// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4).
pub const URL_SAFE: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
);

/// The `crypt(3)` alphabet (uses `.` and `/` as the first two values).
///
/// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses.
pub const CRYPT: Alphabet = Alphabet::from_str_unchecked(
    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
);

/// The bcrypt alphabet.
pub const BCRYPT: Alphabet = Alphabet::from_str_unchecked(
    "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
);

/// The alphabet used in IMAP-modified UTF-7 (uses `+` and `,`).
///
/// See [RFC 3501](https://tools.ietf.org/html/rfc3501#section-5.1.3)
pub const IMAP_MUTF7: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,",
);

/// The alphabet used in BinHex 4.0 files.
///
/// See [BinHex 4.0 Definition](http://files.stairways.com/other/binhex-40-specs-info.txt)
pub const BIN_HEX: Alphabet = Alphabet::from_str_unchecked(
    "!\"#$%&'()*+,-0123456789@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdehijklmpqr",
);

#[cfg(test)]
mod tests {
    use crate::alphabet::*;
    use std::convert::TryFrom as _;

    #[test]
    fn detects_duplicate_start() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'A'),
            Alphabet::from_str("AACDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_duplicate_end() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'/'),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789//")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_duplicate_middle() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'Z'),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZZbcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_length() {
        assert_eq!(
            ParseAlphabetError::InvalidLength,
            Alphabet::from_str(
                "xxxxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZZbcdefghijklmnopqrstuvwxyz0123456789+/",
            )
            .unwrap_err()
        );
    }

    #[test]
    fn detects_padding() {
        assert_eq!(
            ParseAlphabetError::ReservedByte(b'='),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_unprintable() {
        // form feed
        assert_eq!(
            ParseAlphabetError::UnprintableByte(0xc),
            Alphabet::from_str(
                "\x0cBCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            )
            .unwrap_err()
        );
    }

    #[test]
    fn same_as_unchecked() {
        assert_eq!(
            STANDARD,
            Alphabet::try_from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap()
        )
    }
}
<commit_msg>Use core for a few trait impls rather than std<commit_after>//! Provides [Alphabet] and constants for alphabets commonly used in the wild.

use crate::PAD_BYTE;
use core::{convert, fmt};
#[cfg(any(feature = "std", test))]
use std::error;

const ALPHABET_SIZE: usize = 64;

/// An alphabet defines the 64 ASCII characters (symbols) used for base64.
///
/// Common alphabets are provided as constants, and custom alphabets
/// can be made via `from_str` or the `TryFrom<str>` implementation.
///
/// ```
/// let custom = base64::alphabet::Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").unwrap();
///
/// let engine = base64::engine::fast_portable::FastPortable::from(
///     &custom,
///     base64::engine::fast_portable::PAD);
/// ```
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Alphabet {
    pub(crate) symbols: [u8; ALPHABET_SIZE],
}

impl Alphabet {
    /// Performs no checks so that it can be const.
    /// Used only for known-valid strings.
    const fn from_str_unchecked(alphabet: &str) -> Alphabet {
        let mut symbols = [0_u8; ALPHABET_SIZE];
        let source_bytes = alphabet.as_bytes();

        // a way to copy that's allowed in const fn
        let mut index = 0;
        while index < ALPHABET_SIZE {
            symbols[index] = source_bytes[index];
            index += 1;
        }

        Alphabet { symbols }
    }

    /// Create an `Alphabet` from a string of 64 unique printable ASCII bytes.
    ///
    /// The `=` byte is not allowed as it is used for padding.
    pub const fn from_str(alphabet: &str) -> Result<Self, ParseAlphabetError> {
        let bytes = alphabet.as_bytes();
        if bytes.len() != ALPHABET_SIZE {
            return Err(ParseAlphabetError::InvalidLength);
        }

        {
            let mut index = 0;
            while index < ALPHABET_SIZE {
                let byte = bytes[index];

                // must be ascii printable. 127 (DEL) is commonly considered printable
                // for some reason but clearly unsuitable for base64.
                if !(byte >= 32_u8 && byte <= 126_u8) {
                    return Err(ParseAlphabetError::UnprintableByte(byte));
                }
                // = is assumed to be padding, so cannot be used as a symbol
                if byte == PAD_BYTE {
                    return Err(ParseAlphabetError::ReservedByte(byte));
                }

                // Check for duplicates while staying within what const allows.
                // It's n^2, but only over 64 hot bytes, and only once, so it's likely in the single digit
                // microsecond range.

                let mut probe_index = 0;
                while probe_index < ALPHABET_SIZE {
                    if probe_index == index {
                        probe_index += 1;
                        continue;
                    }

                    let probe_byte = bytes[probe_index];

                    if byte == probe_byte {
                        return Err(ParseAlphabetError::DuplicatedByte(byte));
                    }

                    probe_index += 1;
                }

                index += 1;
            }
        }

        Ok(Self::from_str_unchecked(alphabet))
    }
}

impl convert::TryFrom<&str> for Alphabet {
    type Error = ParseAlphabetError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Alphabet::from_str(value)
    }
}

/// Possible errors when constructing an [Alphabet] from a `str`.
#[derive(Debug, Eq, PartialEq)]
pub enum ParseAlphabetError {
    /// Alphabets must be 64 ASCII bytes
    InvalidLength,
    /// All bytes must be unique
    DuplicatedByte(u8),
    /// All bytes must be printable (in the range `[32, 126]`).
    UnprintableByte(u8),
    /// `=` cannot be used
    ReservedByte(u8),
}

impl fmt::Display for ParseAlphabetError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseAlphabetError::InvalidLength => write!(f, "Invalid length - must be 64 bytes"),
            ParseAlphabetError::DuplicatedByte(b) => write!(f, "Duplicated byte: {:#04x}", b),
            ParseAlphabetError::UnprintableByte(b) => write!(f, "Unprintable byte: {:#04x}", b),
            ParseAlphabetError::ReservedByte(b) => write!(f, "Reserved byte: {:#04x}", b),
        }
    }
}

#[cfg(any(feature = "std", test))]
impl error::Error for ParseAlphabetError {}

/// The standard alphabet (uses `+` and `/`).
///
/// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3).
pub const STANDARD: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
);

/// The URL safe alphabet (uses `-` and `_`).
///
/// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4).
pub const URL_SAFE: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
);

/// The `crypt(3)` alphabet (uses `.` and `/` as the first two values).
///
/// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses.
pub const CRYPT: Alphabet = Alphabet::from_str_unchecked(
    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
);

/// The bcrypt alphabet.
pub const BCRYPT: Alphabet = Alphabet::from_str_unchecked(
    "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
);

/// The alphabet used in IMAP-modified UTF-7 (uses `+` and `,`).
///
/// See [RFC 3501](https://tools.ietf.org/html/rfc3501#section-5.1.3)
pub const IMAP_MUTF7: Alphabet = Alphabet::from_str_unchecked(
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,",
);

/// The alphabet used in BinHex 4.0 files.
///
/// See [BinHex 4.0 Definition](http://files.stairways.com/other/binhex-40-specs-info.txt)
pub const BIN_HEX: Alphabet = Alphabet::from_str_unchecked(
    "!\"#$%&'()*+,-0123456789@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdehijklmpqr",
);

#[cfg(test)]
mod tests {
    use crate::alphabet::*;
    use std::convert::TryFrom as _;

    #[test]
    fn detects_duplicate_start() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'A'),
            Alphabet::from_str("AACDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_duplicate_end() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'/'),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789//")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_duplicate_middle() {
        assert_eq!(
            ParseAlphabetError::DuplicatedByte(b'Z'),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZZbcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_length() {
        assert_eq!(
            ParseAlphabetError::InvalidLength,
            Alphabet::from_str(
                "xxxxxxxxxABCDEFGHIJKLMNOPQRSTUVWXYZZbcdefghijklmnopqrstuvwxyz0123456789+/",
            )
            .unwrap_err()
        );
    }

    #[test]
    fn detects_padding() {
        assert_eq!(
            ParseAlphabetError::ReservedByte(b'='),
            Alphabet::from_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=")
                .unwrap_err()
        );
    }

    #[test]
    fn detects_unprintable() {
        // form feed
        assert_eq!(
            ParseAlphabetError::UnprintableByte(0xc),
            Alphabet::from_str(
                "\x0cBCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            )
            .unwrap_err()
        );
    }

    #[test]
    fn same_as_unchecked() {
        assert_eq!(
            STANDARD,
            Alphabet::try_from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
                .unwrap()
        )
    }
}
<|endoftext|>


<commit_before>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}
<commit_msg>Added clear_rgba<commit_after>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_clear_rgba(&self) -> bool { false }

    /// Clears background with a color.
    fn clear_rgba(&mut self, _r: f64, _g: f64, _b: f64, _a: f64) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use std::time::{SystemTime, UNIX_EPOCH};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{date} */ r#"
NAME
    date - prints the system time

SYNOPSIS
    date [ -h | --help]

DESCRIPTION
    Prints the system time and date

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

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

    for arg in env::args().skip(1){
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        }
    }

    let time = SystemTime::now();
    let duration = time.duration_since(UNIX_EPOCH).try(&mut stderr);

    stdout.write(&format!("{}\n", duration.as_secs()).as_bytes()).try(&mut stderr);
}
<commit_msg>Format times (#82)<commit_after>#![deny(warnings)]

extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use std::time::{SystemTime, UNIX_EPOCH};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{date} */ r#"
NAME
    date - prints the system time

SYNOPSIS
    date [ -h | --help]

DESCRIPTION
    Prints the system time and date

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

// Sweet algorithm from http://ptspts.blogspot.com/2009/11/how-to-convert-unix-timestamp-to-civil.html
// TODO: Apply timezone offset
fn format_time(mut ts: i64) -> String {
    let s = ts%86400;
    ts /= 86400;
    let h = s/3600;
    let m = s/60%60;
    let s = s%60;
    let x = (ts*4+102032)/146097+15;
    let b = ts+2442113+x-(x/4);
    let mut c = (b*20-2442)/7305;
    let d = b-365*c-c/4;
    let mut e = d*1000/30601;
    let f = d-e*30-e*601/1000;
    if e < 14 {
        c -= 4716;
        e -= 1;
    } else {
        c -= 4715;
        e -= 13;
    }
    format!("{}-{}-{} {}:{}:{}", c, e, f, h, m, s)
}

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

    let mut tz_offset = 0;
    for arg in env::args().skip(1){
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        } else if let Ok(offset) = arg.parse::<i64>() {
            tz_offset = offset;
        }
    }

    let tz_name = if tz_offset == 0 {
        format!("UTC")
    } else if tz_offset > 0 {
        format!("UTC+{:>02}", tz_offset)
    } else {
        format!("UTC-{:>02}", -tz_offset)
    };

    let time = SystemTime::now();
    let duration = time.duration_since(UNIX_EPOCH).try(&mut stderr);
    let mut ts = duration.as_secs() as i64;
    ts += tz_offset * 3600;

    stdout.write(format!("{} {}\n", format_time(ts), tz_name).as_bytes()).try(&mut stderr);
}
<|endoftext|>


<commit_before>extern crate game_of_life;
#[macro_use]
extern crate glium;

use glium::{DisplayBuild, Program, Surface, VertexBuffer};
use glium::backend::Facade;
use glium::glutin::ElementState::Pressed;
use glium::glutin::{Event, WindowBuilder, VirtualKeyCode};
use glium::index;
use glium::uniforms::EmptyUniforms;

use game_of_life::simulation::{GameOfLife, Grid};

const FRAMES_PER_CYCLE: u32 = 20;
const GRID_HEIGHT: usize = 20;
const GRID_WIDTH: usize = 20;
const X_OFFSET: usize = 10;
const Y_OFFSET: usize = 2;

fn main() {
    let display = WindowBuilder::new().build_glium().unwrap();

    let mut grid = Grid::new(GRID_HEIGHT, GRID_WIDTH);
    for point in &[(X_OFFSET + 1, Y_OFFSET + 1),
                   (X_OFFSET, Y_OFFSET + 2),
                   (X_OFFSET + 1, Y_OFFSET + 2),
                   (X_OFFSET + 2, Y_OFFSET + 2),
                   (X_OFFSET, Y_OFFSET + 3),
                   (X_OFFSET + 2, Y_OFFSET + 3),
                   (X_OFFSET + 1, Y_OFFSET + 4)] {
        grid[*point] = true;
    }

    let program = {
        let vertex_shader_src = include_str!("../assets/vs.glsl");
        let fragment_shader_src = include_str!("../assets/fs.glsl");

        Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap()
    };

    let mut passed_frames = 0;
    loop {
        let (alive_cells, alive_indices) = render_grid(&display, &grid);

        // listing the events produced by the window and waiting to be received
        for ev in display.poll_events() {
            match ev {
                Event::Closed |
                Event::KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) => return,
                _ => (),
            }
        }

        let mut target = display.draw();
        target.clear_color(0.9, 0.9, 0.9, 1.0);
        target.draw(&alive_cells,
                  &alive_indices,
                  &program,
                  &EmptyUniforms,
                  &Default::default())
            .unwrap();
        target.finish().unwrap();

        passed_frames += 1;
        if passed_frames > FRAMES_PER_CYCLE {
            grid = grid.simulate();
            passed_frames = 0;
        }
    }
}

/// Convert coordinates from a `Gridn` to screen coordinates, assuming OpenGL's default coordinate
/// system.
fn convert_coordinates(grid: &Grid, (x, y): (f32, f32)) -> [f32; 2] {
    [x / grid.cols() as f32 * 2.0 - 1.0, y / grid.rows() as f32 * -2.0 + 1.0]
}

/// Prepare the grid for redering.
fn render_grid<F: Facade>(display: &F, grid: &Grid) -> (VertexBuffer<Vertex>, index::NoIndices) {
    let alive_cells = {
        let mut triangles = Vec::new();

        for x in 0..grid.cols() {
            for y in 0..grid.rows() {
                if grid[(x, y)] {
                    let x = x as f32;
                    let y = y as f32;

                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x + 1.0, y)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y + 1.0)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y + 1.0)) });
                    triangles.push(Vertex {
                        v_position: convert_coordinates(grid, (x + 1.0, y + 1.0)),
                    });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x + 1.0, y)) });
                }
            }
        }

        VertexBuffer::new(display, &triangles).unwrap()
    };

    (alive_cells, index::NoIndices(index::PrimitiveType::TrianglesList))
}

#[derive(Copy, Clone)]
struct Vertex {
    v_position: [f32; 2],
}

implement_vertex!(Vertex, v_position);
<commit_msg>Remove boilerplate comment<commit_after>extern crate game_of_life;
#[macro_use]
extern crate glium;

use glium::{DisplayBuild, Program, Surface, VertexBuffer};
use glium::backend::Facade;
use glium::glutin::ElementState::Pressed;
use glium::glutin::{Event, WindowBuilder, VirtualKeyCode};
use glium::index;
use glium::uniforms::EmptyUniforms;

use game_of_life::simulation::{GameOfLife, Grid};

const FRAMES_PER_CYCLE: u32 = 20;
const GRID_HEIGHT: usize = 20;
const GRID_WIDTH: usize = 20;
const X_OFFSET: usize = 10;
const Y_OFFSET: usize = 2;

fn main() {
    let display = WindowBuilder::new().build_glium().unwrap();

    let mut grid = Grid::new(GRID_HEIGHT, GRID_WIDTH);
    for point in &[(X_OFFSET + 1, Y_OFFSET + 1),
                   (X_OFFSET, Y_OFFSET + 2),
                   (X_OFFSET + 1, Y_OFFSET + 2),
                   (X_OFFSET + 2, Y_OFFSET + 2),
                   (X_OFFSET, Y_OFFSET + 3),
                   (X_OFFSET + 2, Y_OFFSET + 3),
                   (X_OFFSET + 1, Y_OFFSET + 4)] {
        grid[*point] = true;
    }

    let program = {
        let vertex_shader_src = include_str!("../assets/vs.glsl");
        let fragment_shader_src = include_str!("../assets/fs.glsl");

        Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap()
    };

    let mut passed_frames = 0;
    loop {
        let (alive_cells, alive_indices) = render_grid(&display, &grid);

        for ev in display.poll_events() {
            match ev {
                Event::Closed |
                Event::KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) => return,
                _ => (),
            }
        }

        let mut target = display.draw();
        target.clear_color(0.9, 0.9, 0.9, 1.0);
        target.draw(&alive_cells,
                  &alive_indices,
                  &program,
                  &EmptyUniforms,
                  &Default::default())
            .unwrap();
        target.finish().unwrap();

        passed_frames += 1;
        if passed_frames > FRAMES_PER_CYCLE {
            grid = grid.simulate();
            passed_frames = 0;
        }
    }
}

/// Convert coordinates from a `Gridn` to screen coordinates, assuming OpenGL's default coordinate
/// system.
fn convert_coordinates(grid: &Grid, (x, y): (f32, f32)) -> [f32; 2] {
    [x / grid.cols() as f32 * 2.0 - 1.0, y / grid.rows() as f32 * -2.0 + 1.0]
}

/// Prepare the grid for redering.
fn render_grid<F: Facade>(display: &F, grid: &Grid) -> (VertexBuffer<Vertex>, index::NoIndices) {
    let alive_cells = {
        let mut triangles = Vec::new();

        for x in 0..grid.cols() {
            for y in 0..grid.rows() {
                if grid[(x, y)] {
                    let x = x as f32;
                    let y = y as f32;

                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x + 1.0, y)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y + 1.0)) });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x, y + 1.0)) });
                    triangles.push(Vertex {
                        v_position: convert_coordinates(grid, (x + 1.0, y + 1.0)),
                    });
                    triangles.push(Vertex { v_position: convert_coordinates(grid, (x + 1.0, y)) });
                }
            }
        }

        VertexBuffer::new(display, &triangles).unwrap()
    };

    (alive_cells, index::NoIndices(index::PrimitiveType::TrianglesList))
}

#[derive(Copy, Clone)]
struct Vertex {
    v_position: [f32; 2],
}

implement_vertex!(Vertex, v_position);
<|endoftext|>


<commit_before>
extern crate mprovision;
extern crate docopt;
#[macro_use(version)]
extern crate version;
extern crate chrono;

use std::io::{self, Write};
use std::process;
use std::path::Path;
use docopt::Docopt;

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision search <text> [<directory>]
  mprovision remove <uuid> [<directory>]
  mprovision show-xml <uuid> [<directory>]
  mprovision show-expired --days <days> [<directory>]
  mprovision remove-expired [<directory>]
  mprovision (-h | --help)
  mprovision --version

Options:
  -h --help     Show this help message.
  --version     Show version.
";

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(format!("mprovision {}", version!()))).parse())
        .unwrap_or_else(|e| e.exit());

    match Command::from_args(&args).execute() {
        Ok(_) => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        }
    }
}

struct Command<'a> {
    args: &'a ::docopt::ArgvMap,
}

impl<'a> Command<'a> {
    fn from_args(args: &'a ::docopt::ArgvMap) -> Self {
        Command { args: args }
    }

    fn execute(&self) -> Result<(), String> {
        if self.args.get_bool("search") {
            search(self.args)
        } else if self.args.get_bool("remove") {
            remove(self.args)
        } else if self.args.get_bool("show-xml") {
            show_xml(self.args)
        } else if self.args.get_bool("show-expired") {
            show_expired(self.args)
        } else if self.args.get_bool("remove-expired") {
            remove_expired(self.args)
        } else {
            Err("Command is not implemented".to_string())
        }
    }
}

fn search(args: &::docopt::ArgvMap) -> Result<(), String> {
    let text = args.get_str("<text>");
    if text.is_empty() {
        return Err("<text> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::search(dir, text))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("Nothing found for '{}'", text);
            } else {
                for profile in &info.profiles {
                    println!("{}\n", profile.description());
                }
                println!("Found {} of {}", info.profiles.len(), info.total);
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn remove(args: &::docopt::ArgvMap) -> Result<(), String> {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err("<uuid> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::remove(dir, uuid))
        .and_then(|_| Ok(println!("'{}' was removed", uuid)))
        .map_err(|e| e.to_string())
}

fn show_xml(args: &::docopt::ArgvMap) -> Result<(), String> {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err("<uuid> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::xml(dir, uuid))
        .and_then(|xml| Ok(println!("{}", xml)))
        .map_err(|e| e.to_string())
}

fn show_expired(args: &::docopt::ArgvMap) -> Result<(), String> {
    use chrono::*;

    let mut date = UTC::now();
    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
        if days < 0 || days > 365 {
            return Err("<days> should be between 0 and 365".to_owned());
        }
        date = date + Duration::days(days);
    }

    mprovision::with_dir(directory(args),
                         |dir| mprovision::expired_profiles(dir, date))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("All provisioning profiles are valid");
            } else {
                for profile in &info.profiles {
                    println!("{}\n", profile.description());
                }
                println!("Found {} of {}", info.profiles.len(), info.total);
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn remove_expired(args: &::docopt::ArgvMap) -> Result<(), String> {
    use chrono::*;

    mprovision::with_dir(directory(args),
                         |dir| mprovision::expired_profiles(dir, UTC::now()))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("All provisioning profiles are valid");
            } else {
                let mut errors_counter = 0;
                let mut removals_counter = 0;
                for profile in info.profiles {
                    match std::fs::remove_file(&profile.path) {
                        Ok(_) => {
                            removals_counter += 1;
                            println!("'{}' was removed", profile.uuid)
                        }
                        Err(e) => {
                            errors_counter += 1;
                            println!("Error while trying to remove '{}'", profile.uuid);
                            println!("{}", e);
                        }
                    }
                }
                println!("Removed {} of {}", removals_counter, info.total);
                if errors_counter > 0 {
                    println!("Errors: {}", errors_counter);
                }
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn directory(args: &::docopt::ArgvMap) -> Option<&Path> {
    let dir_name = args.get_str("<directory>");
    if dir_name.is_empty() {
        None
    } else {
        Some(dir_name.as_ref())
    }
}
<commit_msg>Slightly reformat output whith profiles.<commit_after>
extern crate mprovision;
extern crate docopt;
#[macro_use(version)]
extern crate version;
extern crate chrono;

use std::io::{self, Write};
use std::process;
use std::path::Path;
use docopt::Docopt;

const USAGE: &'static str = "
mprovision
A tool that helps iOS developers to manage mobileprovision files.

Usage:
  mprovision search <text> [<directory>]
  mprovision remove <uuid> [<directory>]
  mprovision show-xml <uuid> [<directory>]
  mprovision show-expired --days <days> [<directory>]
  mprovision remove-expired [<directory>]
  mprovision (-h | --help)
  mprovision --version

Options:
  -h --help     Show this help message.
  --version     Show version.
";

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|d| d.version(Some(format!("mprovision {}", version!()))).parse())
        .unwrap_or_else(|e| e.exit());

    match Command::from_args(&args).execute() {
        Ok(_) => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        }
    }
}

struct Command<'a> {
    args: &'a ::docopt::ArgvMap,
}

impl<'a> Command<'a> {
    fn from_args(args: &'a ::docopt::ArgvMap) -> Self {
        Command { args: args }
    }

    fn execute(&self) -> Result<(), String> {
        if self.args.get_bool("search") {
            search(self.args)
        } else if self.args.get_bool("remove") {
            remove(self.args)
        } else if self.args.get_bool("show-xml") {
            show_xml(self.args)
        } else if self.args.get_bool("show-expired") {
            show_expired(self.args)
        } else if self.args.get_bool("remove-expired") {
            remove_expired(self.args)
        } else {
            Err("Command is not implemented".to_string())
        }
    }
}

fn search(args: &::docopt::ArgvMap) -> Result<(), String> {
    let text = args.get_str("<text>");
    if text.is_empty() {
        return Err("<text> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::search(dir, text))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("Nothing found for '{}'", text);
            } else {
                for profile in &info.profiles {
                    println!("\n{}", profile.description());
                }
                println!("\nFound {} of {}", info.profiles.len(), info.total);
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn remove(args: &::docopt::ArgvMap) -> Result<(), String> {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err("<uuid> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::remove(dir, uuid))
        .and_then(|_| Ok(println!("'{}' was removed", uuid)))
        .map_err(|e| e.to_string())
}

fn show_xml(args: &::docopt::ArgvMap) -> Result<(), String> {
    let uuid = args.get_str("<uuid>");
    if uuid.is_empty() {
        return Err("<uuid> should not be empty.".to_owned());
    }

    mprovision::with_dir(directory(args), |dir| mprovision::xml(dir, uuid))
        .and_then(|xml| Ok(println!("{}", xml)))
        .map_err(|e| e.to_string())
}

fn show_expired(args: &::docopt::ArgvMap) -> Result<(), String> {
    use chrono::*;

    let mut date = UTC::now();
    if let Some(days) = args.get_str("<days>").parse::<i64>().ok() {
        if days < 0 || days > 365 {
            return Err("<days> should be between 0 and 365".to_owned());
        }
        date = date + Duration::days(days);
    }

    mprovision::with_dir(directory(args),
                         |dir| mprovision::expired_profiles(dir, date))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("All provisioning profiles are valid");
            } else {
                for profile in &info.profiles {
                    println!("\n{}", profile.description());
                }
                println!("\nFound {} of {}", info.profiles.len(), info.total);
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn remove_expired(args: &::docopt::ArgvMap) -> Result<(), String> {
    use chrono::*;

    mprovision::with_dir(directory(args),
                         |dir| mprovision::expired_profiles(dir, UTC::now()))
        .and_then(|info| {
            if info.profiles.is_empty() {
                println!("All provisioning profiles are valid");
            } else {
                let mut errors_counter = 0;
                let mut removals_counter = 0;
                for profile in info.profiles {
                    match std::fs::remove_file(&profile.path) {
                        Ok(_) => {
                            removals_counter += 1;
                            println!("'{}' was removed", profile.uuid)
                        }
                        Err(e) => {
                            errors_counter += 1;
                            println!("Error while trying to remove '{}'", profile.uuid);
                            println!("{}", e);
                        }
                    }
                }
                println!("Removed {} of {}", removals_counter, info.total);
                if errors_counter > 0 {
                    println!("Errors: {}", errors_counter);
                }
            }
            Ok(())
        })
        .map_err(|e| e.to_string())
}

fn directory(args: &::docopt::ArgvMap) -> Option<&Path> {
    let dir_name = args.get_str("<directory>");
    if dir_name.is_empty() {
        None
    } else {
        Some(dir_name.as_ref())
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate rustc_middle;
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_errors;

use std::convert::TryFrom;
use std::env;
use std::str::FromStr;

use hex::FromHexError;
use log::debug;

use rustc_session::{CtfeBacktrace, config::ErrorOutputType};
use rustc_errors::emitter::{HumanReadableErrorType, ColorConfig};
use rustc_driver::Compilation;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_analysis<'tcx>(
        &mut self,
        compiler: &rustc_interface::interface::Compiler,
        queries: &'tcx rustc_interface::Queries<'tcx>,
    ) -> Compilation {
        compiler.session().abort_if_errors();

        queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            init_late_loggers(tcx);
            let (entry_def_id, _) = if let Some((entry_def, x)) = tcx.entry_fn(LOCAL_CRATE) {
                (entry_def, x)
            } else {
                let output_ty = ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto));
                rustc_session::early_error(output_ty, "miri can only run programs that have a main function");
            };
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            // Adjust working directory for interpretation.
            if let Some(cwd) = env::var_os("MIRI_CWD") {
                env::set_current_dir(cwd).unwrap();
            }

            if let Some(return_code) = miri::eval_main(tcx, entry_def_id.to_def_id(), config) {
                std::process::exit(
                    i32::try_from(return_code).expect("Return value was too large!"),
                );
            }
        });

        compiler.session().abort_if_errors();

        Compilation::Stop
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var_os("RUSTC_LOG").is_some() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers(tcx: TyCtxt<'_>) {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.)
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var_os("RUSTC_LOG").is_none() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var(
                    "RUSTC_LOG",
                    &format!("rustc_middle::mir::interpret={0},rustc_mir::interpret={0}", var),
                );
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
    // Do this late, so we ideally only apply this to Miri's errors.
    if let Some(val) = env::var_os("MIRI_BACKTRACE") {
        let ctfe_backtrace = match &*val.to_string_lossy() {
            "immediate" => CtfeBacktrace::Immediate,
            "0" => CtfeBacktrace::Disabled,
            _ => CtfeBacktrace::Capture,
        };
        *tcx.sess.ctfe_backtrace.borrow_mut() = ctfe_backtrace;
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> Option<String> {
    if option_env!("RUSTC_STAGE").is_some() {
        // This is being built as part of rustc, and gets shipped with rustup.
        // We can rely on the sysroot computation in librustc_session.
        return None;
    }
    // For builds outside rustc, we need to ensure that we got a sysroot
    // that gets used as a default.  The sysroot computation in librustc_session would
    // end up somewhere in the build dir (see `get_or_default_sysroot`).
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    Some(match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
            .to_owned(),
    })
}

/// Execute a compiler with the given CLI arguments and callbacks.
fn run_compiler(mut args: Vec<String>, callbacks: &mut (dyn rustc_driver::Callbacks + Send)) -> ! {
    // Make sure we use the right default sysroot. The default sysroot is wrong,
    // because `get_or_default_sysroot` in `librustc_session` bases that on `current_exe`.
    //
    // Make sure we always call `compile_time_sysroot` as that also does some sanity-checks
    // of the environment we were built in.
    // FIXME: Ideally we'd turn a bad build env into a compile-time error via CTFE or so.
    if let Some(sysroot) = compile_time_sysroot() {
        let sysroot_flag = "--sysroot";
        if !args.iter().any(|e| e == sysroot_flag) {
            // We need to overwrite the default that librustc_session would compute.
            args.push(sysroot_flag.to_owned());
            args.push(sysroot);
        }
    }

    // Some options have different defaults in Miri than in plain rustc; apply those by making
    // them the first arguments after the binary name (but later arguments can overwrite them).
    args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string));

    // Invoke compiler, and handle return code.
    let exit_code = rustc_driver::catch_with_exit_code(move || {
        rustc_driver::RunCompiler::new(&args, callbacks).run()
    });
    std::process::exit(exit_code)
}

fn main() {
    rustc_driver::install_ice_hook();

    // If the environment asks us to actually be rustc, then do that.
    if env::var_os("MIRI_BE_RUSTC").is_some() {
        rustc_driver::init_rustc_env_logger();
        // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
        let mut callbacks = rustc_driver::TimePassesCallbacks::default();
        run_compiler(env::args().collect(), &mut callbacks)
    }

    // Init loggers the Miri way.
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut miri_config = miri::MiriConfig::default();
    let mut rustc_args = vec![];
    let mut after_dashdash = false;
    for arg in env::args() {
        if rustc_args.is_empty() {
            // Very first arg: binary name.
            rustc_args.push(arg);
        } else if after_dashdash {
            // Everything that comes after `--` is forwarded to the interpreted crate.
            miri_config.args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    miri_config.validate = false;
                }
                "-Zmiri-disable-stacked-borrows" => {
                    miri_config.stacked_borrows = false;
                }
                "-Zmiri-disable-data-race-detector" => {
                    miri_config.data_race_detector = false;
                }
                "-Zmiri-disable-alignment-check" => {
                    miri_config.check_alignment = miri::AlignmentCheck::None;
                }
                "-Zmiri-symbolic-alignment-check" => {
                    miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
                }
                "-Zmiri-disable-isolation" => {
                    miri_config.communicate = true;
                }
                "-Zmiri-ignore-leaks" => {
                    miri_config.ignore_leaks = true;
                }
                "-Zmiri-track-raw-pointers" => {
                    miri_config.track_raw = true;
                }
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if miri_config.seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.strip_prefix("-Zmiri-seed=").unwrap())
                        .unwrap_or_else(|err| match err {
                            FromHexError::InvalidHexCharacter { .. } => panic!(
                                "-Zmiri-seed should only contain valid hex digits [0-9a-fA-F]"
                            ),
                            FromHexError::OddLength =>
                                panic!("-Zmiri-seed should have an even number of digits"),
                            err => panic!("unknown error decoding -Zmiri-seed as hex: {:?}", err),
                        });
                    if seed_raw.len() > 8 {
                        panic!(format!(
                            "-Zmiri-seed must be at most 8 bytes, was {}",
                            seed_raw.len()
                        ));
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    miri_config.seed = Some(u64::from_be_bytes(bytes));
                }
                arg if arg.starts_with("-Zmiri-env-exclude=") => {
                    miri_config.excluded_env_vars
                        .push(arg.strip_prefix("-Zmiri-env-exclude=").unwrap().to_owned());
                }
                arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-pointer-tag=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-pointer-tag requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::PtrId::new(id) {
                        miri_config.tracked_pointer_tag = Some(id);
                    } else {
                        panic!("-Zmiri-track-pointer-tag requires a nonzero argument");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-call-id=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-call-id=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-call-id requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::CallId::new(id) {
                        miri_config.tracked_call_id = Some(id);
                    } else {
                        panic!("-Zmiri-track-call-id requires a nonzero argument");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-alloc-id=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-alloc-id requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    miri_config.tracked_alloc_id = Some(miri::AllocId(id));
                }
                arg if arg.starts_with("-Zmiri-compare-exchange-weak-failure-rate=") => {
                    let rate = match arg.strip_prefix("-Zmiri-compare-exchange-weak-failure-rate=").unwrap().parse::<f64>() {
                        Ok(rate) if rate >= 0.0 && rate <= 1.0 => rate,
                        Ok(_) => panic!("-Zmiri-compare-exchange-weak-failure-rate must be between `0.0` and `1.0`"),
                        Err(err) => panic!("-Zmiri-compare-exchange-weak-failure-rate requires a `f64` between `0.0` and `1.0`: {}", err),
                    };
                    miri_config.cmpxchg_weak_failure_rate = rate;
                }
                _ => {
                    // Forward to rustc.
                    rustc_args.push(arg);
                }
            }
        }
    }

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("crate arguments: {:?}", miri_config.args);
    run_compiler(rustc_args, &mut MiriCompilerCalls { miri_config })
}
<commit_msg>Remove unnecessary `format!()` in `panic!()`.<commit_after>#![feature(rustc_private)]

extern crate rustc_middle;
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_errors;

use std::convert::TryFrom;
use std::env;
use std::str::FromStr;

use hex::FromHexError;
use log::debug;

use rustc_session::{CtfeBacktrace, config::ErrorOutputType};
use rustc_errors::emitter::{HumanReadableErrorType, ColorConfig};
use rustc_driver::Compilation;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_analysis<'tcx>(
        &mut self,
        compiler: &rustc_interface::interface::Compiler,
        queries: &'tcx rustc_interface::Queries<'tcx>,
    ) -> Compilation {
        compiler.session().abort_if_errors();

        queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            init_late_loggers(tcx);
            let (entry_def_id, _) = if let Some((entry_def, x)) = tcx.entry_fn(LOCAL_CRATE) {
                (entry_def, x)
            } else {
                let output_ty = ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto));
                rustc_session::early_error(output_ty, "miri can only run programs that have a main function");
            };
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            // Adjust working directory for interpretation.
            if let Some(cwd) = env::var_os("MIRI_CWD") {
                env::set_current_dir(cwd).unwrap();
            }

            if let Some(return_code) = miri::eval_main(tcx, entry_def_id.to_def_id(), config) {
                std::process::exit(
                    i32::try_from(return_code).expect("Return value was too large!"),
                );
            }
        });

        compiler.session().abort_if_errors();

        Compilation::Stop
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var_os("RUSTC_LOG").is_some() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers(tcx: TyCtxt<'_>) {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.)
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var_os("RUSTC_LOG").is_none() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var(
                    "RUSTC_LOG",
                    &format!("rustc_middle::mir::interpret={0},rustc_mir::interpret={0}", var),
                );
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
    // Do this late, so we ideally only apply this to Miri's errors.
    if let Some(val) = env::var_os("MIRI_BACKTRACE") {
        let ctfe_backtrace = match &*val.to_string_lossy() {
            "immediate" => CtfeBacktrace::Immediate,
            "0" => CtfeBacktrace::Disabled,
            _ => CtfeBacktrace::Capture,
        };
        *tcx.sess.ctfe_backtrace.borrow_mut() = ctfe_backtrace;
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> Option<String> {
    if option_env!("RUSTC_STAGE").is_some() {
        // This is being built as part of rustc, and gets shipped with rustup.
        // We can rely on the sysroot computation in librustc_session.
        return None;
    }
    // For builds outside rustc, we need to ensure that we got a sysroot
    // that gets used as a default.  The sysroot computation in librustc_session would
    // end up somewhere in the build dir (see `get_or_default_sysroot`).
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    Some(match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
            .to_owned(),
    })
}

/// Execute a compiler with the given CLI arguments and callbacks.
fn run_compiler(mut args: Vec<String>, callbacks: &mut (dyn rustc_driver::Callbacks + Send)) -> ! {
    // Make sure we use the right default sysroot. The default sysroot is wrong,
    // because `get_or_default_sysroot` in `librustc_session` bases that on `current_exe`.
    //
    // Make sure we always call `compile_time_sysroot` as that also does some sanity-checks
    // of the environment we were built in.
    // FIXME: Ideally we'd turn a bad build env into a compile-time error via CTFE or so.
    if let Some(sysroot) = compile_time_sysroot() {
        let sysroot_flag = "--sysroot";
        if !args.iter().any(|e| e == sysroot_flag) {
            // We need to overwrite the default that librustc_session would compute.
            args.push(sysroot_flag.to_owned());
            args.push(sysroot);
        }
    }

    // Some options have different defaults in Miri than in plain rustc; apply those by making
    // them the first arguments after the binary name (but later arguments can overwrite them).
    args.splice(1..1, miri::MIRI_DEFAULT_ARGS.iter().map(ToString::to_string));

    // Invoke compiler, and handle return code.
    let exit_code = rustc_driver::catch_with_exit_code(move || {
        rustc_driver::RunCompiler::new(&args, callbacks).run()
    });
    std::process::exit(exit_code)
}

fn main() {
    rustc_driver::install_ice_hook();

    // If the environment asks us to actually be rustc, then do that.
    if env::var_os("MIRI_BE_RUSTC").is_some() {
        rustc_driver::init_rustc_env_logger();
        // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
        let mut callbacks = rustc_driver::TimePassesCallbacks::default();
        run_compiler(env::args().collect(), &mut callbacks)
    }

    // Init loggers the Miri way.
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut miri_config = miri::MiriConfig::default();
    let mut rustc_args = vec![];
    let mut after_dashdash = false;
    for arg in env::args() {
        if rustc_args.is_empty() {
            // Very first arg: binary name.
            rustc_args.push(arg);
        } else if after_dashdash {
            // Everything that comes after `--` is forwarded to the interpreted crate.
            miri_config.args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    miri_config.validate = false;
                }
                "-Zmiri-disable-stacked-borrows" => {
                    miri_config.stacked_borrows = false;
                }
                "-Zmiri-disable-data-race-detector" => {
                    miri_config.data_race_detector = false;
                }
                "-Zmiri-disable-alignment-check" => {
                    miri_config.check_alignment = miri::AlignmentCheck::None;
                }
                "-Zmiri-symbolic-alignment-check" => {
                    miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
                }
                "-Zmiri-disable-isolation" => {
                    miri_config.communicate = true;
                }
                "-Zmiri-ignore-leaks" => {
                    miri_config.ignore_leaks = true;
                }
                "-Zmiri-track-raw-pointers" => {
                    miri_config.track_raw = true;
                }
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if miri_config.seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.strip_prefix("-Zmiri-seed=").unwrap())
                        .unwrap_or_else(|err| match err {
                            FromHexError::InvalidHexCharacter { .. } => panic!(
                                "-Zmiri-seed should only contain valid hex digits [0-9a-fA-F]"
                            ),
                            FromHexError::OddLength =>
                                panic!("-Zmiri-seed should have an even number of digits"),
                            err => panic!("unknown error decoding -Zmiri-seed as hex: {:?}", err),
                        });
                    if seed_raw.len() > 8 {
                        panic!(
                            "-Zmiri-seed must be at most 8 bytes, was {}",
                            seed_raw.len()
                        );
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    miri_config.seed = Some(u64::from_be_bytes(bytes));
                }
                arg if arg.starts_with("-Zmiri-env-exclude=") => {
                    miri_config.excluded_env_vars
                        .push(arg.strip_prefix("-Zmiri-env-exclude=").unwrap().to_owned());
                }
                arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-pointer-tag=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-pointer-tag requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::PtrId::new(id) {
                        miri_config.tracked_pointer_tag = Some(id);
                    } else {
                        panic!("-Zmiri-track-pointer-tag requires a nonzero argument");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-call-id=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-call-id=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-call-id requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::CallId::new(id) {
                        miri_config.tracked_call_id = Some(id);
                    } else {
                        panic!("-Zmiri-track-call-id requires a nonzero argument");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-alloc-id=").unwrap().parse() {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-alloc-id requires a valid `u64` argument: {}",
                            err
                        ),
                    };
                    miri_config.tracked_alloc_id = Some(miri::AllocId(id));
                }
                arg if arg.starts_with("-Zmiri-compare-exchange-weak-failure-rate=") => {
                    let rate = match arg.strip_prefix("-Zmiri-compare-exchange-weak-failure-rate=").unwrap().parse::<f64>() {
                        Ok(rate) if rate >= 0.0 && rate <= 1.0 => rate,
                        Ok(_) => panic!("-Zmiri-compare-exchange-weak-failure-rate must be between `0.0` and `1.0`"),
                        Err(err) => panic!("-Zmiri-compare-exchange-weak-failure-rate requires a `f64` between `0.0` and `1.0`: {}", err),
                    };
                    miri_config.cmpxchg_weak_failure_rate = rate;
                }
                _ => {
                    // Forward to rustc.
                    rustc_args.push(arg);
                }
            }
        }
    }

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("crate arguments: {:?}", miri_config.args);
    run_compiler(rustc_args, &mut MiriCompilerCalls { miri_config })
}
<|endoftext|>