<commit_before>#[macro_use]
extern crate clap;

use std::io::prelude::*;
use std::fs::File;

#[derive(Debug)]
struct ReadError {
    reason: String,
}

impl ReadError {
    fn new(error: &str, position: usize) -> ReadError {
        ReadError {
            reason: format!("Error at position {}: {}", position, error),
        }
    }
}

fn read_usize(input: &[u8],
              position: usize)
              -> Result<(usize, usize), ReadError> {
    let mut end = 0;
    while (input[end] as char).is_digit(10) {
        end += 1;
    }
    let read = std::str::from_utf8(&input[..end])
        .map_err(|e| ReadError::new(&format!("Bad read: {}", e), position))?
        .parse()
        .map_err(|e| ReadError::new(&format!("Bad read: {}", e), position))?;
    Ok((read, end))
}

fn decompress(input: &[u8]) -> Result<Vec<u8>, ReadError> {
    let mut out = Vec::new();
    let mut idx = 0;
    while idx < input.len() {
        if input[idx] == '(' as u8 {
            idx += 1;
            if idx >= input.len() {
                return Err(ReadError::new("Unexpected end", idx));
            }
            let (rep_length, offset) = read_usize(&input[idx..], idx)?;
            idx += offset;
            if idx >= input.len() {
                return Err(ReadError::new("Unexpected end", idx));
            }
            if input[idx] as char != 'x' {
                return Err(ReadError::new(&format!("Expected 'x', got {}",
                                                   input[idx]),
                                          idx));
            }
            idx += 1;
            let (n_reps, offset) = read_usize(&input[idx..], idx)?;
            idx += offset;
            if idx >= input.len() {
                return Err(ReadError::new("Unexpected end", idx));
            }
            if input[idx] as char != ')' {
                return Err(ReadError::new(&format!("Expected ')', got {}",
                                                   input[idx]),
                                          idx));
            }
            idx += 1;
            if idx + rep_length > input.len() {
                return Err(ReadError::new("Unexpected end", idx));
            }
            for _ in 0..n_reps {
                out.extend_from_slice(&input[idx..idx + rep_length]);
            }
            idx += rep_length;
        } else {
            out.push(input[idx]);
            idx += 1;
        }
    }
    Ok(out)
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 09")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("file")
            .index(1)
            .short("f")
            .long("file")
            .help("file to decompress. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("file");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let compressed = parse_args()
        .unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let decompressed = match decompress(compressed.as_bytes()) {
        Ok(d) => d,
        Err(e) => panic!(e.reason),
    };
    println!("Decompressed length: {}",
             decompressed.iter()
                 .filter(|c| !(**c as char).is_whitespace())
                 .count());
}

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

    #[test]
    fn t1() {
        assert_eq!(&decompress(b"ADVENT").unwrap(), b"ADVENT")
    }

    #[test]
    fn t2() {
        assert_eq!(&decompress(b"A(1x5)BC").unwrap(), b"ABBBBBC")
    }

    #[test]
    fn t3() {
        assert_eq!(&decompress(b"(3x3)XYZ").unwrap(), b"XYZXYZXYZ")
    }

    #[test]
    fn t4() {
        assert_eq!(&decompress(b"A(2x2)BCD(2x2)EFG").unwrap(), b"ABCBCDEFEFG")
    }

    #[test]
    fn t5() {
        assert_eq!(&decompress(b"(6x1)(1x3)A").unwrap(), b"(1x3)A")
    }

    #[test]
    fn t6() {
        assert_eq!(&decompress(b"X(8x2)(3x3)ABCY").unwrap(),
                   b"X(3x3)ABC(3x3)ABCY")
    }
}
<commit_msg>Day 9 part 2<commit_after>#[macro_use]
extern crate clap;

use std::io::prelude::*;
use std::fs::File;
use std::error::Error;

#[derive(Debug, PartialEq, Eq)]
enum ParseExpansionError {
    BadChar { expected: char, got: char },
    BadInt(std::num::ParseIntError),
    NotEnoughInput,
}

impl std::fmt::Display for ParseExpansionError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            ParseExpansionError::BadChar { expected: ref e, got: ref g } => {
                write!(f, "Expected {}, got {}", e, g)
            }
            ParseExpansionError::BadInt(ref e) => write!(f, "{}", e),
            ParseExpansionError::NotEnoughInput => {
                write!(f, "Not enough input")
            }
        }
    }
}

impl Error for ParseExpansionError {
    fn description(&self) -> &str {
        "Could not parse Expansion"
    }
    fn cause(&self) -> Option<&Error> {
        match *self {
            ParseExpansionError::BadInt(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<std::num::ParseIntError> for ParseExpansionError {
    fn from(err: std::num::ParseIntError) -> Self {
        ParseExpansionError::BadInt(err)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Expansion {
    width: usize,
    repetitions: usize,
}

fn read_expansion(input: &[u8])
                  -> Result<(Expansion, usize), ParseExpansionError> {
    use ParseExpansionError::*;
    // read '('
    if input.len() == 0 {
        return Err(NotEnoughInput);
    } else if input[0] != '(' as u8 {
        return Err(BadChar {
            expected: '(',
            got: input[0] as char,
        });
    }
    // read `width`
    let mut idx = 1;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let width = std::str::from_utf8(&input[1..idx]).unwrap().parse()?;
    // read 'x'
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != 'x' as u8 {
        return Err(BadChar {
            expected: 'x',
            got: input[idx] as char,
        });
    }
    // read `repetitions`
    idx += 1;
    let repititions_start = idx;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let repetitions =
        std::str::from_utf8(&input[repititions_start..idx]).unwrap().parse()?;
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != ')' as u8 {
        return Err(BadChar {
            expected: ')',
            got: input[idx] as char,
        });
    }
    Ok((Expansion {
        width: width,
        repetitions: repetitions,
    },
        idx + 1))
}

fn decompress_a(input: &[u8]) -> Vec<u8> {
    let mut out = Vec::new();
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            for _ in 0..repetitions {
                out.extend_from_slice(&input[idx..idx +
                                                  std::cmp::min(width,
                                                                input.len() -
                                                                idx)]);
            }
            idx += width;
        } else {
            out.push(input[idx]);
            idx += 1;
        }
    }
    out
}

fn decompressed_b_len(input: &[u8]) -> usize {
    let mut len = 0;
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            let sub_len =
                decompressed_b_len(&input[idx..idx +
                                               std::cmp::min(width,
                                                             input.len() -
                                                             idx)]);
            len += sub_len * repetitions;
            idx += width;
        } else {
            if !(input[idx] as char).is_whitespace() {
                len += 1;
            }
            idx += 1;
        }
    }
    len
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 09")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("file")
            .index(1)
            .short("f")
            .long("file")
            .help("file to decompress. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("file");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let compressed = parse_args()
        .unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let decompressed = decompress_a(compressed.as_bytes());
    println!("Decompressed length (first algorithm): {}",
             decompressed.iter()
                 .filter(|c| !(**c as char).is_whitespace())
                 .count());
    println!("Decompressed length (second algorithm): {}",
             decompressed_b_len(compressed.as_bytes()));
}

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

    #[test]
    fn decompress_a_1() {
        assert_eq!(&decompress_a(b"ADVENT"), b"ADVENT")
    }

    #[test]
    fn decompress_a_2() {
        assert_eq!(&decompress_a(b"A(1x5)BC"), b"ABBBBBC")
    }

    #[test]
    fn decompress_a_3() {
        assert_eq!(&decompress_a(b"(3x3)XYZ"), b"XYZXYZXYZ")
    }

    #[test]
    fn decompress_a_4() {
        assert_eq!(&decompress_a(b"A(2x2)BCD(2x2)EFG"), b"ABCBCDEFEFG")
    }

    #[test]
    fn decompress_a_5() {
        assert_eq!(&decompress_a(b"(6x1)(1x3)A"), b"(1x3)A")
    }

    #[test]
    fn decompress_a_6() {
        assert_eq!(&decompress_a(b"X(8x2)(3x3)ABCY"), b"X(3x3)ABC(3x3)ABCY")
    }

    #[test]
    fn decompress_a_not_enough_input() {
        assert_eq!(&decompress_a(b"(3x3)XY"), b"XYXYXY");
        assert_eq!(&decompress_a(b"(3x3)"), b"")
    }

    #[test]
    fn read_expansion_success() {
        assert_eq!(read_expansion(b"(123x456)foo"),
                   Ok((Expansion {
                       width: 123,
                       repetitions: 456,
                   },
                       9)))
    }

    #[test]
    fn read_expansion_not_enough_input() {
        assert_eq!(read_expansion(b""),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1"),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1x2"),
                   Err(ParseExpansionError::NotEnoughInput));
    }

    #[test]
    fn read_expansion_expected() {
        assert_eq!(read_expansion(b"1"),
                   Err(ParseExpansionError::BadChar {
                       expected: '(',
                       got: '1',
                   }));
        assert_eq!(read_expansion(b"(1,"),
                   Err(ParseExpansionError::BadChar {
                       expected: 'x',
                       got: ',',
                   }));
        assert_eq!(read_expansion(b"(1x2x"),
                   Err(ParseExpansionError::BadChar {
                       expected: ')',
                       got: 'x',
                   }));
    }

    #[test]
    fn read_expansion_bad_int() {
        let empty_int_error = "".parse::<usize>().unwrap_err();
        assert_eq!(read_expansion(b"(x456)"),
                   Err(ParseExpansionError::BadInt(empty_int_error.clone())));
        assert_eq!(read_expansion(b"(123x)"),
                   Err(ParseExpansionError::BadInt(empty_int_error)));
    }

    #[test]
    fn decompress_b_len_1() {
        assert_eq!(decompressed_b_len(b"(3x3)XYZ"), 9);
    }

    #[test]
    fn decompress_b_len_2() {
        assert_eq!(decompressed_b_len(b"X(8x2)(3x3)ABCY"), 20);
    }

    #[test]
    fn decompress_b_len_3() {
        assert_eq!(decompressed_b_len(b"(27x12)(20x12)(13x14)(7x10)(1x12)A"),
                   241920);
    }

    #[test]
    fn decompress_b_len_4() {
        assert_eq!(decompressed_b_len(
                b"(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"),
                   445);
    }
}
<|endoftext|>


<commit_before>use std::io::stdin;
use std::io::stdout;
use std::str;

use protobuf::descriptor::FileDescriptorProto;
use protobuf::plugin::*;
use protobuf::Message;
use protobuf_parse::ProtoPathBuf;

pub struct GenRequest<'a> {
    pub file_descriptors: &'a [FileDescriptorProto],
    pub files_to_generate: &'a [ProtoPathBuf],
    pub parameter: &'a str,
}

pub struct GenResult {
    pub name: String,
    pub content: Vec<u8>,
}

pub fn plugin_main<F>(gen: F) -> anyhow::Result<()>
where
    F: Fn(&GenRequest) -> anyhow::Result<Vec<GenResult>>,
{
    let req = CodeGeneratorRequest::parse_from_reader(&mut stdin()).unwrap();
    let result = gen(&GenRequest {
        file_descriptors: &req.proto_file,
        files_to_generate: &req
            .file_to_generate
            .iter()
            .map(|n| ProtoPathBuf::new(n.to_owned()))
            .collect::<anyhow::Result<Vec<_>>>()?,
        parameter: req.parameter(),
    })?;
    let mut resp = CodeGeneratorResponse::new();
    resp.file = result
        .iter()
        .map(|file| {
            let mut r = code_generator_response::File::new();
            r.set_name(file.name.to_string());
            r.set_content(str::from_utf8(file.content.as_ref()).unwrap().to_string());
            r
        })
        .collect();
    resp.write_to_writer(&mut stdout()).unwrap();
    Ok(())
}
<commit_msg>set supported features (#626)<commit_after>use std::io::stdin;
use std::io::stdout;
use std::str;

use protobuf::descriptor::FileDescriptorProto;
use protobuf::plugin::*;
use protobuf::Message;
use protobuf_parse::ProtoPathBuf;

pub struct GenRequest<'a> {
    pub file_descriptors: &'a [FileDescriptorProto],
    pub files_to_generate: &'a [ProtoPathBuf],
    pub parameter: &'a str,
}

pub struct GenResult {
    pub name: String,
    pub content: Vec<u8>,
}

pub fn plugin_main<F>(gen: F) -> anyhow::Result<()>
where
    F: Fn(&GenRequest) -> anyhow::Result<Vec<GenResult>>,
{
    let req = CodeGeneratorRequest::parse_from_reader(&mut stdin()).unwrap();
    let result = gen(&GenRequest {
        file_descriptors: &req.proto_file,
        files_to_generate: &req
            .file_to_generate
            .iter()
            .map(|n| ProtoPathBuf::new(n.to_owned()))
            .collect::<anyhow::Result<Vec<_>>>()?,
        parameter: req.parameter(),
    })?;
    let mut resp = CodeGeneratorResponse::new();
    resp.set_supported_features(code_generator_response::Feature::FEATURE_PROTO3_OPTIONAL as u64);
    resp.file = result
        .iter()
        .map(|file| {
            let mut r = code_generator_response::File::new();
            r.set_name(file.name.to_string());
            r.set_content(str::from_utf8(file.content.as_ref()).unwrap().to_string());
            r
        })
        .collect();
    resp.write_to_writer(&mut stdout()).unwrap();
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(unix, not(target_os = "ios"))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use rt::stack;
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let mut ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            // FIXME #13259:
            // It turns out that if we can't acquire a context with the
            // NTE_BAD_SIGNATURE error code, the documentation states:
            //
            //     The provider DLL signature could not be verified. Either the
            //     DLL or the digital signature has been tampered with.
            //
            // Sounds fishy, no? As it turns out, our signature can be bad
            // because our Thread Information Block (TIB) isn't exactly what it
            // expects. As to why, I have no idea. The only data we store in the
            // TIB is the stack limit for each thread, but apparently that's
            // enough to make the signature valid.
            //
            // Furthermore, this error only happens the *first* time we call
            // CryptAcquireContext, so we don't have to worry about future
            // calls.
            //
            // Anyway, the fix employed here is that if we see this error, we
            // pray that we're not close to the end of the stack, temporarily
            // set the stack limit to 0 (what the TIB originally was), acquire a
            // context, and then reset the stack limit.
            //
            // Again, I'm not sure why this is the fix, nor why we're getting
            // this error. All I can say is that this seems to allow libnative
            // to progress where it otherwise would be hindered. Who knew?
            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
                unsafe {
                    let limit = stack::get_sp_limit();
                    stack::record_sp_limit(0);
                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                               PROV_RSA_FULL,
                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
                    stack::record_sp_limit(limit);
                }
            }

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Disable runtime split stack support on Windows<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(unix, not(target_os = "ios"))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2015-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms
//! this ALWAYS GENERATED file contains the definitions for the interfaces
use shared::basetsd::UINT32;
use shared::guiddef::{LPCGUID, REFIID};
use shared::minwindef::{BYTE, DWORD, LPVOID};
use shared::mmreg::WAVEFORMATEX;
use shared::winerror::{FACILITY_AUDCLNT, SEVERITY_ERROR, SEVERITY_SUCCESS};
use shared::wtypesbase::SCODE;
use um::audiosessiontypes::AUDCLNT_SHAREMODE;
use um::strmif::REFERENCE_TIME;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HANDLE, HRESULT};
//1627
pub const AUDCLNT_E_NOT_INITIALIZED: HRESULT = AUDCLNT_ERR!(0x001);
pub const AUDCLNT_E_ALREADY_INITIALIZED: HRESULT = AUDCLNT_ERR!(0x002);
pub const AUDCLNT_E_WRONG_ENDPOINT_TYPE: HRESULT = AUDCLNT_ERR!(0x003);
pub const AUDCLNT_E_DEVICE_INVALIDATED: HRESULT = AUDCLNT_ERR!(0x004);
pub const AUDCLNT_E_NOT_STOPPED: HRESULT = AUDCLNT_ERR!(0x005);
pub const AUDCLNT_E_BUFFER_TOO_LARGE: HRESULT = AUDCLNT_ERR!(0x006);
pub const AUDCLNT_E_OUT_OF_ORDER: HRESULT = AUDCLNT_ERR!(0x007);
pub const AUDCLNT_E_UNSUPPORTED_FORMAT: HRESULT = AUDCLNT_ERR!(0x008);
pub const AUDCLNT_E_INVALID_SIZE: HRESULT = AUDCLNT_ERR!(0x009);
pub const AUDCLNT_E_DEVICE_IN_USE: HRESULT = AUDCLNT_ERR!(0x00a);
pub const AUDCLNT_E_BUFFER_OPERATION_PENDING: HRESULT = AUDCLNT_ERR!(0x00b);
pub const AUDCLNT_E_THREAD_NOT_REGISTERED: HRESULT = AUDCLNT_ERR!(0x00c);
pub const AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: HRESULT = AUDCLNT_ERR!(0x00e);
pub const AUDCLNT_E_ENDPOINT_CREATE_FAILED: HRESULT = AUDCLNT_ERR!(0x00f);
pub const AUDCLNT_E_SERVICE_NOT_RUNNING: HRESULT = AUDCLNT_ERR!(0x010);
pub const AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: HRESULT = AUDCLNT_ERR!(0x011);
pub const AUDCLNT_E_EXCLUSIVE_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x012);
pub const AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: HRESULT = AUDCLNT_ERR!(0x013);
pub const AUDCLNT_E_EVENTHANDLE_NOT_SET: HRESULT = AUDCLNT_ERR!(0x014);
pub const AUDCLNT_E_INCORRECT_BUFFER_SIZE: HRESULT = AUDCLNT_ERR!(0x015);
pub const AUDCLNT_E_BUFFER_SIZE_ERROR: HRESULT = AUDCLNT_ERR!(0x016);
pub const AUDCLNT_E_CPUUSAGE_EXCEEDED: HRESULT = AUDCLNT_ERR!(0x017);
pub const AUDCLNT_E_BUFFER_ERROR: HRESULT = AUDCLNT_ERR!(0x018);
pub const AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED: HRESULT = AUDCLNT_ERR!(0x019);
pub const AUDCLNT_E_INVALID_DEVICE_PERIOD: HRESULT = AUDCLNT_ERR!(0x020);
pub const AUDCLNT_E_INVALID_STREAM_FLAG: HRESULT = AUDCLNT_ERR!(0x021);
pub const AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE: HRESULT = AUDCLNT_ERR!(0x022);
pub const AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES: HRESULT = AUDCLNT_ERR!(0x023);
pub const AUDCLNT_E_OFFLOAD_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x024);
pub const AUDCLNT_E_NONOFFLOAD_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x025);
pub const AUDCLNT_E_RESOURCES_INVALIDATED: HRESULT = AUDCLNT_ERR!(0x026);
pub const AUDCLNT_E_RAW_MODE_UNSUPPORTED: HRESULT = AUDCLNT_ERR!(0x027);
pub const AUDCLNT_S_BUFFER_EMPTY: SCODE = AUDCLNT_SUCCESS!(0x001);
pub const AUDCLNT_S_THREAD_ALREADY_REGISTERED: SCODE = AUDCLNT_SUCCESS!(0x002);
pub const AUDCLNT_S_POSITION_STALLED: SCODE = AUDCLNT_SUCCESS!(0x003);
DEFINE_GUID!{IID_IAudioClient,
    0x1CB9AD4C, 0xDBFA, 0x4c32, 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}
DEFINE_GUID!{IID_IAudioRenderClient,
    0xF294ACFC, 0x3146, 0x4483, 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}
RIDL!{#[uuid(0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2)]
interface IAudioClient(IAudioClientVtbl): IUnknown(IUnknownVtbl) {
    fn Initialize(
        ShareMode: AUDCLNT_SHAREMODE,
        StreamFlags: DWORD,
        hnsBufferDuration: REFERENCE_TIME,
        hnsPeriodicity: REFERENCE_TIME,
        pFormat: *const WAVEFORMATEX,
        AudioSessionGuid: LPCGUID,
    ) -> HRESULT,
    fn GetBufferSize(
        pNumBufferFrames: *mut UINT32,
    ) -> HRESULT,
    fn GetStreamLatency(
        phnsLatency: *mut REFERENCE_TIME,
    ) -> HRESULT,
    fn GetCurrentPadding(
        pNumPaddingFrames: *mut UINT32,
    ) -> HRESULT,
    fn IsFormatSupported(
        ShareMode: AUDCLNT_SHAREMODE,
        pFormat: *const WAVEFORMATEX,
        ppClosestMatch: *mut *mut WAVEFORMATEX,
    ) -> HRESULT,
    fn GetMixFormat(
        ppDeviceFormat: *mut *mut WAVEFORMATEX,
    ) -> HRESULT,
    fn GetDevicePeriod(
        phnsDefaultDevicePeriod: *mut REFERENCE_TIME,
        phnsMinimumDevicePeriod: *mut REFERENCE_TIME,
    ) -> HRESULT,
    fn Start() -> HRESULT,
    fn Stop() -> HRESULT,
    fn Reset() -> HRESULT,
    fn SetEventHandle(
        eventHandle: HANDLE,
    ) -> HRESULT,
    fn GetService(
        riid: REFIID,
        ppv: *mut LPVOID,
    ) -> HRESULT,
}}
RIDL!{#[uuid(0xf294acfc, 0x3146, 0x4483, 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2)]
interface IAudioRenderClient(IAudioRenderClientVtbl): IUnknown(IUnknownVtbl) {
    fn GetBuffer(
        NumFramesRequested: UINT32,
        ppData: *mut *mut BYTE,
    ) -> HRESULT,
    fn ReleaseBuffer(
        NumFramesWritten: UINT32,
        dwFlags: DWORD,
    ) -> HRESULT,
}}
<commit_msg>add IAudioCaptureClient to um/audioclient.rs (#436)<commit_after>// Copyright © 2015-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms
//! this ALWAYS GENERATED file contains the definitions for the interfaces
use shared::basetsd::{UINT32, UINT64};
use shared::guiddef::{LPCGUID, REFIID};
use shared::minwindef::{BYTE, DWORD, LPVOID};
use shared::mmreg::WAVEFORMATEX;
use shared::winerror::{FACILITY_AUDCLNT, SEVERITY_ERROR, SEVERITY_SUCCESS};
use shared::wtypesbase::SCODE;
use um::audiosessiontypes::AUDCLNT_SHAREMODE;
use um::strmif::REFERENCE_TIME;
use um::unknwnbase::{IUnknown, IUnknownVtbl};
use um::winnt::{HANDLE, HRESULT};
//1627
pub const AUDCLNT_E_NOT_INITIALIZED: HRESULT = AUDCLNT_ERR!(0x001);
pub const AUDCLNT_E_ALREADY_INITIALIZED: HRESULT = AUDCLNT_ERR!(0x002);
pub const AUDCLNT_E_WRONG_ENDPOINT_TYPE: HRESULT = AUDCLNT_ERR!(0x003);
pub const AUDCLNT_E_DEVICE_INVALIDATED: HRESULT = AUDCLNT_ERR!(0x004);
pub const AUDCLNT_E_NOT_STOPPED: HRESULT = AUDCLNT_ERR!(0x005);
pub const AUDCLNT_E_BUFFER_TOO_LARGE: HRESULT = AUDCLNT_ERR!(0x006);
pub const AUDCLNT_E_OUT_OF_ORDER: HRESULT = AUDCLNT_ERR!(0x007);
pub const AUDCLNT_E_UNSUPPORTED_FORMAT: HRESULT = AUDCLNT_ERR!(0x008);
pub const AUDCLNT_E_INVALID_SIZE: HRESULT = AUDCLNT_ERR!(0x009);
pub const AUDCLNT_E_DEVICE_IN_USE: HRESULT = AUDCLNT_ERR!(0x00a);
pub const AUDCLNT_E_BUFFER_OPERATION_PENDING: HRESULT = AUDCLNT_ERR!(0x00b);
pub const AUDCLNT_E_THREAD_NOT_REGISTERED: HRESULT = AUDCLNT_ERR!(0x00c);
pub const AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: HRESULT = AUDCLNT_ERR!(0x00e);
pub const AUDCLNT_E_ENDPOINT_CREATE_FAILED: HRESULT = AUDCLNT_ERR!(0x00f);
pub const AUDCLNT_E_SERVICE_NOT_RUNNING: HRESULT = AUDCLNT_ERR!(0x010);
pub const AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: HRESULT = AUDCLNT_ERR!(0x011);
pub const AUDCLNT_E_EXCLUSIVE_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x012);
pub const AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: HRESULT = AUDCLNT_ERR!(0x013);
pub const AUDCLNT_E_EVENTHANDLE_NOT_SET: HRESULT = AUDCLNT_ERR!(0x014);
pub const AUDCLNT_E_INCORRECT_BUFFER_SIZE: HRESULT = AUDCLNT_ERR!(0x015);
pub const AUDCLNT_E_BUFFER_SIZE_ERROR: HRESULT = AUDCLNT_ERR!(0x016);
pub const AUDCLNT_E_CPUUSAGE_EXCEEDED: HRESULT = AUDCLNT_ERR!(0x017);
pub const AUDCLNT_E_BUFFER_ERROR: HRESULT = AUDCLNT_ERR!(0x018);
pub const AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED: HRESULT = AUDCLNT_ERR!(0x019);
pub const AUDCLNT_E_INVALID_DEVICE_PERIOD: HRESULT = AUDCLNT_ERR!(0x020);
pub const AUDCLNT_E_INVALID_STREAM_FLAG: HRESULT = AUDCLNT_ERR!(0x021);
pub const AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE: HRESULT = AUDCLNT_ERR!(0x022);
pub const AUDCLNT_E_OUT_OF_OFFLOAD_RESOURCES: HRESULT = AUDCLNT_ERR!(0x023);
pub const AUDCLNT_E_OFFLOAD_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x024);
pub const AUDCLNT_E_NONOFFLOAD_MODE_ONLY: HRESULT = AUDCLNT_ERR!(0x025);
pub const AUDCLNT_E_RESOURCES_INVALIDATED: HRESULT = AUDCLNT_ERR!(0x026);
pub const AUDCLNT_E_RAW_MODE_UNSUPPORTED: HRESULT = AUDCLNT_ERR!(0x027);
pub const AUDCLNT_S_BUFFER_EMPTY: SCODE = AUDCLNT_SUCCESS!(0x001);
pub const AUDCLNT_S_THREAD_ALREADY_REGISTERED: SCODE = AUDCLNT_SUCCESS!(0x002);
pub const AUDCLNT_S_POSITION_STALLED: SCODE = AUDCLNT_SUCCESS!(0x003);
DEFINE_GUID!{IID_IAudioClient,
    0x1CB9AD4C, 0xDBFA, 0x4c32, 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}
DEFINE_GUID!{IID_IAudioRenderClient,
    0xF294ACFC, 0x3146, 0x4483, 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}
DEFINE_GUID!{IID_IAudioCaptureClient,
    0xc8adbd64, 0xe71e, 0x48a0, 0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17}
RIDL!{#[uuid(0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2)]
interface IAudioClient(IAudioClientVtbl): IUnknown(IUnknownVtbl) {
    fn Initialize(
        ShareMode: AUDCLNT_SHAREMODE,
        StreamFlags: DWORD,
        hnsBufferDuration: REFERENCE_TIME,
        hnsPeriodicity: REFERENCE_TIME,
        pFormat: *const WAVEFORMATEX,
        AudioSessionGuid: LPCGUID,
    ) -> HRESULT,
    fn GetBufferSize(
        pNumBufferFrames: *mut UINT32,
    ) -> HRESULT,
    fn GetStreamLatency(
        phnsLatency: *mut REFERENCE_TIME,
    ) -> HRESULT,
    fn GetCurrentPadding(
        pNumPaddingFrames: *mut UINT32,
    ) -> HRESULT,
    fn IsFormatSupported(
        ShareMode: AUDCLNT_SHAREMODE,
        pFormat: *const WAVEFORMATEX,
        ppClosestMatch: *mut *mut WAVEFORMATEX,
    ) -> HRESULT,
    fn GetMixFormat(
        ppDeviceFormat: *mut *mut WAVEFORMATEX,
    ) -> HRESULT,
    fn GetDevicePeriod(
        phnsDefaultDevicePeriod: *mut REFERENCE_TIME,
        phnsMinimumDevicePeriod: *mut REFERENCE_TIME,
    ) -> HRESULT,
    fn Start() -> HRESULT,
    fn Stop() -> HRESULT,
    fn Reset() -> HRESULT,
    fn SetEventHandle(
        eventHandle: HANDLE,
    ) -> HRESULT,
    fn GetService(
        riid: REFIID,
        ppv: *mut LPVOID,
    ) -> HRESULT,
}}
RIDL!{#[uuid(0xf294acfc, 0x3146, 0x4483, 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2)]
interface IAudioRenderClient(IAudioRenderClientVtbl): IUnknown(IUnknownVtbl) {
    fn GetBuffer(
        NumFramesRequested: UINT32,
        ppData: *mut *mut BYTE,
    ) -> HRESULT,
    fn ReleaseBuffer(
        NumFramesWritten: UINT32,
        dwFlags: DWORD,
    ) -> HRESULT,
}}
RIDL!{#[uuid(0xc8adbd64, 0xe71e, 0x48a0, 0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17)]
interface IAudioCaptureClient(IAudioCaptureClientVtbl): IUnknown(IUnknownVtbl) {
    fn GetBuffer(
        ppData: *mut *mut BYTE,
        pNumFramesToRead: *mut UINT32,
        pdwFlags: *mut DWORD,
        pu64DevicePosition: *mut UINT64,
        pu64QPCPosition: *mut UINT64,
    ) -> HRESULT,
    fn ReleaseBuffer(
        NumFramesRead: UINT32,
    ) -> HRESULT,
    fn GetNextPacketSize(
        pNumFramesInNextPacket: *mut UINT32,
    ) -> HRESULT,
}}
<|endoftext|>


<commit_before>use core::ptr::Unique;
use spin::Mutex;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    /// Contructor
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[CharCell; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }
    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }
    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        // TODO: boundary check
        self.row = row;
        self.col = col;
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    raw_mode: bool,
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }
    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let mut buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col] = CharCell {
                    character: b' ',
                    color: clear_color,
                };
            }
        }
    }
    /// Write string to terminal's stdout
    pub fn write_str(&mut self, string: &str) {
        let sb = string.as_bytes();
        for index in 0..sb.len() {
            self.write_byte(sb[index]);
        }
    }
    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }

            self.get_buffer().chars[self.cursor.row][self.cursor.col] = CharCell {
                character: byte,
                color: self.output_color,
            };
            self.cursor.next();
        }
    }
    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        if self.cursor.newline() {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        for row in 0..(SCREEN_HEIGHT-1) {
            self.get_buffer().chars[row] = self.get_buffer().chars[row+1];
        }
        self.get_buffer().chars[SCREEN_HEIGHT-1] = [CharCell {character: b' ', color: self.output_color}; SCREEN_WIDTH];
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.get_mut()}
    }
}
/// Format macros
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    raw_mode: false,
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new(0xb8000 as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().write_fmt(format_args!($($arg)*)).unwrap();
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
<commit_msg>Move vga buffers location to constant<commit_after>use core::ptr::Unique;
use spin::Mutex;

const SCREEN_HEIGHT: usize = 25;
const SCREEN_WIDTH: usize = 80;
const VGA_BUFFER_ADDRESS: usize = 0xb8000;

/// A VGA color
#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Magenta    = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    Pink       = 13,
    Yellow     = 14,
    White      = 15,
}

/// Color of single cell, back- and foreground
#[derive(Clone, Copy)]
pub struct CellColor(u8);

impl CellColor {
    /// Contructor
    pub const fn new(foreground: Color, background: Color) -> CellColor {
        CellColor((background as u8) << 4 | (foreground as u8))
    }
}

/// Character cell: one character and color in screen
#[derive(Clone, Copy)]
#[repr(C)]
pub struct CharCell {
    pub character: u8,
    pub color: CellColor,
}

/// A Virtual tty buffer
pub struct Buffer {
    pub chars: [[CharCell; SCREEN_WIDTH]; SCREEN_HEIGHT],
}

/// Cursor
pub struct Cursor {
    /// Current row
    pub row: usize,
    /// Current column
    pub col: usize,
}

impl Cursor {
    /// Next character
    pub fn next(&mut self) {
        if self.col < SCREEN_WIDTH {
            self.col+=1;
        }
    }
    /// New line
    /// # Returns
    /// true if terminal should be scrolled
    pub fn newline(&mut self) -> bool {
        self.col = 0;
        if self.row < SCREEN_HEIGHT-1 {
            self.row += 1;
            false
        }
        else {
            true
        }
    }
    /// Set position
    pub fn set_position(&mut self, row: usize, col: usize) {
        // TODO: boundary check
        self.row = row;
        self.col = col;
    }
}

/// Terminal: an interface to hardware terminal
pub struct Terminal {
    raw_mode: bool,
    output_color: CellColor,
    cursor: Cursor,
    buffer: Unique<Buffer>,
}

impl Terminal {
    /// Init terminal
    pub fn reset(&mut self) {
        self.output_color = CellColor::new(Color::White, Color::Black);
        self.clear();
    }
    /// Clear screen
    pub fn clear(&mut self) {
        self.cursor.set_position(0, 0);
        let clear_color = self.output_color;
        let mut buffer = self.get_buffer();
        for col in 0..SCREEN_WIDTH {
            for row in 0..SCREEN_HEIGHT {
                buffer.chars[row][col] = CharCell {
                    character: b' ',
                    color: clear_color,
                };
            }
        }
    }
    /// Write string to terminal's stdout
    pub fn write_str(&mut self, string: &str) {
        let sb = string.as_bytes();
        for index in 0..sb.len() {
            self.write_byte(sb[index]);
        }
    }
    /// Write single byte to terminal's stdout
    pub fn write_byte(&mut self, byte: u8) {
        if byte == b'\n' {
            self.newline();
        }
        else {
            if self.cursor.col >= SCREEN_WIDTH {
                self.newline();
            }

            self.get_buffer().chars[self.cursor.row][self.cursor.col] = CharCell {
                character: byte,
                color: self.output_color,
            };
            self.cursor.next();
        }
    }
    /// Set color
    pub fn set_color(&mut self, color: CellColor) {
        self.output_color = color;
    }

    /// Newline
    pub fn newline(&mut self) {
        if self.cursor.newline() {
            self.scroll_line();
        }
    }

    /// Scroll up one line
    fn scroll_line(&mut self) {
        for row in 0..(SCREEN_HEIGHT-1) {
            self.get_buffer().chars[row] = self.get_buffer().chars[row+1];
        }
        self.get_buffer().chars[SCREEN_HEIGHT-1] = [CharCell {character: b' ', color: self.output_color}; SCREEN_WIDTH];
    }

    /// Get pointer to memory buffer
    fn get_buffer(&mut self) -> &mut Buffer {
        unsafe {self.buffer.get_mut()}
    }
}
/// Format macros
impl ::core::fmt::Write for Terminal {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        for byte in s.bytes() {
            self.write_byte(byte)
        }
        Ok(())  // Success. Always.
    }
}

// Create static pointer mutex with spinlock to make TERMINAL thread-safe
pub static TERMINAL: Mutex<Terminal> = Mutex::new(Terminal {
    raw_mode: false,
    output_color: CellColor::new(Color::White, Color::Black),
    cursor: Cursor {row: 0, col: 0},
    buffer: unsafe { Unique::new(VGA_BUFFER_ADDRESS as *mut _) },
});

/// "Raw" output macros
macro_rules! rprint {
    ($($arg:tt)*) => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().write_fmt(format_args!($($arg)*)).unwrap();
    });
}
macro_rules! rprintln {
    ($fmt:expr) => (rprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (rprint!(concat!($fmt, "\n"), $($arg)*));
}
macro_rules! rreset {
    () => ({
        use core::fmt::Write;
        $crate::vga_buffer::TERMINAL.lock().reset();
    });
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword(
    "visibility",
    "visible hidden",
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    extra_gecko_values="collapse",
    gecko_ffi_name="mVisible",
    animation_value_type="ComputedValue",
    spec="https://drafts.csswg.org/css-box/#propdef-visibility",
    gecko_enum_prefix="StyleVisibility",
)}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword(
    "writing-mode",
    "horizontal-tb vertical-rl vertical-lr",
    engines="gecko servo-2013 servo-2020",
    extra_gecko_values="sideways-rl sideways-lr",
    gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                         rl=horizontal-tb rl-tb=horizontal-tb \
                         tb=vertical-rl   tb-rl=vertical-rl",
    servo_2013_pref="layout.writing-mode.enabled",
    servo_2020_pref="layout.writing-mode.enabled",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "direction",
    "ltr rtl",
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
    gecko_enum_prefix="StyleDirection",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "text-orientation",
    "mixed upright sideways",
    engines="gecko",
    gecko_aliases="sideways-right=sideways",
    gecko_enum_prefix="StyleTextOrientation",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation",
)}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword(
    "color-adjust",
    "economy exact",
    engines="gecko",
    gecko_enum_prefix="StyleColorAdjust",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-color/#propdef-color-adjust",
)}

// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword(
    "image-rendering",
    "auto crisp-edges",
    engines="gecko servo-2013 servo-2020",
    extra_gecko_values="optimizespeed optimizequality",
    extra_servo_2013_values="pixelated",
    extra_servo_2020_values="pixelated",
    gecko_aliases="-moz-crisp-edges=crisp-edges",
    gecko_enum_prefix="StyleImageRendering",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-rendering",
)}

${helpers.single_keyword(
    "image-orientation",
    "none from-image",
    engines="gecko",
    gecko_enum_prefix="StyleImageOrientation",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation",
)}
<commit_msg>style: Change initial value of image-orientation to from-image.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("InheritedBox", inherited=True, gecko_name="Visibility") %>

// TODO: collapse. Well, do tables first.
${helpers.single_keyword(
    "visibility",
    "visible hidden",
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    extra_gecko_values="collapse",
    gecko_ffi_name="mVisible",
    animation_value_type="ComputedValue",
    spec="https://drafts.csswg.org/css-box/#propdef-visibility",
    gecko_enum_prefix="StyleVisibility",
)}

// CSS Writing Modes Level 3
// https://drafts.csswg.org/css-writing-modes-3
${helpers.single_keyword(
    "writing-mode",
    "horizontal-tb vertical-rl vertical-lr",
    engines="gecko servo-2013 servo-2020",
    extra_gecko_values="sideways-rl sideways-lr",
    gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                         rl=horizontal-tb rl-tb=horizontal-tb \
                         tb=vertical-rl   tb-rl=vertical-rl",
    servo_2013_pref="layout.writing-mode.enabled",
    servo_2020_pref="layout.writing-mode.enabled",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "direction",
    "ltr rtl",
    engines="gecko servo-2013 servo-2020",
    servo_2020_pref="layout.2020.unimplemented",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
    gecko_enum_prefix="StyleDirection",
    servo_restyle_damage="rebuild_and_reflow",
)}

${helpers.single_keyword(
    "text-orientation",
    "mixed upright sideways",
    engines="gecko",
    gecko_aliases="sideways-right=sideways",
    gecko_enum_prefix="StyleTextOrientation",
    animation_value_type="none",
    spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation",
)}

// CSS Color Module Level 4
// https://drafts.csswg.org/css-color/
${helpers.single_keyword(
    "color-adjust",
    "economy exact",
    engines="gecko",
    gecko_enum_prefix="StyleColorAdjust",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-color/#propdef-color-adjust",
)}

// According to to CSS-IMAGES-3, `optimizespeed` and `optimizequality` are synonyms for `auto`
// And, firefox doesn't support `pixelated` yet (https://bugzilla.mozilla.org/show_bug.cgi?id=856337)
${helpers.single_keyword(
    "image-rendering",
    "auto crisp-edges",
    engines="gecko servo-2013 servo-2020",
    extra_gecko_values="optimizespeed optimizequality",
    extra_servo_2013_values="pixelated",
    extra_servo_2020_values="pixelated",
    gecko_aliases="-moz-crisp-edges=crisp-edges",
    gecko_enum_prefix="StyleImageRendering",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-rendering",
)}

${helpers.single_keyword(
    "image-orientation",
    "from-image none",
    engines="gecko",
    gecko_enum_prefix="StyleImageOrientation",
    animation_value_type="discrete",
    spec="https://drafts.csswg.org/css-images/#propdef-image-orientation",
)}
<|endoftext|>


<commit_before>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

/// Various control flags modifying the basic operation of the CPU.
#[derive(Debug)]
pub struct Cr0;

bitflags! {
    /// Configuration flags of the Cr0 register.
    pub struct Cr0Flags: u64 {
        /// Enables protected mode.
        const PROTECTED_MODE_ENABLE = 1 << 0;
        /// Enables monitoring of the coprocessor, typical for x87 instructions.
        ///
        /// Controls together with the `TASK_SWITCHED` flag whether a `wait` or `fwait`
        /// instruction should cause a device-not-available exception.
        const MONITOR_COPROCESSOR = 1 << 1;
        /// Force all x87 and MMX instructions to cause an exception.
        const EMULATE_COPROCESSOR = 1 << 2;
        /// Automatically set to 1 on _hardware_ task switch.
        ///
        /// This flags allows lazily saving x87/MMX/SSE instructions on hardware context switches.
        const TASK_SWITCHED = 1 << 3;
        /// Enables the native error reporting mechanism for x87 FPU errors.
        const NUMERIC_ERROR = 1 << 5;
        /// Controls whether supervisor-level writes to read-only pages are inhibited.
        ///
        /// When set, it is not possible to write to read-only pages from ring 0.
        const WRITE_PROTECT = 1 << 16;
        /// Enables automatic alignment checking.
        const ALIGNMENT_MASK = 1 << 18;
        /// Ignored. Used to control write-back/write-through cache strategy on older CPUs.
        const NOT_WRITE_THROUGH = 1 << 29;
        /// Disables internal caches (only for some cases).
        const CACHE_DISABLE = 1 << 30;
        /// Enables page translation.
        const PAGING = 1 << 31;
    }
}

/// Contains the physical address of the level 4 page table.
#[derive(Debug)]
pub struct Cr3;

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}

#[cfg(target_arch = "x86_64")]
mod x86_64 {
    use super::*;
    use structures::paging::PhysFrame;
    use PhysAddr;

    impl Cr0 {
        /// Read the current set of CR0 flags.
        pub fn read() -> Cr0Flags {
            Cr0Flags::from_bits_truncate(Self::read_raw())
        }

        /// Read the current raw CR0 value.
        pub fn read_raw() -> u64 {
            let value: u64;
            unsafe {
                asm!("mov %cr0, $0" : "=r" (value));
            }
            value
        }

        /// Write CR0 flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn write(flags: Cr0Flags) {
            let old_value = Self::read_raw();
            let reserved = old_value & !(Cr0Flags::all().bits());
            let new_value = reserved | flags.bits();

            Self::write_raw(new_value);
        }

        /// Write raw CR0 flags.
        ///
        /// Does _not_ preserve any values, including reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn write_raw(value: u64) {
            asm!("mov $0, %cr0" :: "r" (value) : "memory")
        }

        /// Updates CR0 flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn update<F>(f: F)
        where
            F: FnOnce(&mut Cr0Flags),
        {
            let mut flags = Self::read();
            f(&mut flags);
            Self::write(flags);
        }
    }

    impl Cr3 {
        /// Read the current P4 table address from the CR3 register.
        pub fn read() -> (PhysFrame, Cr3Flags) {
            let value: u64;
            unsafe {
                asm!("mov %cr3, $0" : "=r" (value));
            }
            let flags = Cr3Flags::from_bits_truncate(value);
            let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
            let frame = PhysFrame::containing_address(addr);
            (frame, flags)
        }

        /// Write a new P4 table address into the CR3 register.
        ///
        /// ## Safety
        /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
        /// changing the page mapping.
        pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
            let addr = frame.start_address();
            let value = addr.as_u64() | flags.bits();
            asm!("mov $0, %cr3" :: "r" (value) : "memory")
        }
    }
}
<commit_msg>Add a Cr2 struct for retrieving the page fault linear address<commit_after>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

/// Various control flags modifying the basic operation of the CPU.
#[derive(Debug)]
pub struct Cr0;

bitflags! {
    /// Configuration flags of the Cr0 register.
    pub struct Cr0Flags: u64 {
        /// Enables protected mode.
        const PROTECTED_MODE_ENABLE = 1 << 0;
        /// Enables monitoring of the coprocessor, typical for x87 instructions.
        ///
        /// Controls together with the `TASK_SWITCHED` flag whether a `wait` or `fwait`
        /// instruction should cause a device-not-available exception.
        const MONITOR_COPROCESSOR = 1 << 1;
        /// Force all x87 and MMX instructions to cause an exception.
        const EMULATE_COPROCESSOR = 1 << 2;
        /// Automatically set to 1 on _hardware_ task switch.
        ///
        /// This flags allows lazily saving x87/MMX/SSE instructions on hardware context switches.
        const TASK_SWITCHED = 1 << 3;
        /// Enables the native error reporting mechanism for x87 FPU errors.
        const NUMERIC_ERROR = 1 << 5;
        /// Controls whether supervisor-level writes to read-only pages are inhibited.
        ///
        /// When set, it is not possible to write to read-only pages from ring 0.
        const WRITE_PROTECT = 1 << 16;
        /// Enables automatic alignment checking.
        const ALIGNMENT_MASK = 1 << 18;
        /// Ignored. Used to control write-back/write-through cache strategy on older CPUs.
        const NOT_WRITE_THROUGH = 1 << 29;
        /// Disables internal caches (only for some cases).
        const CACHE_DISABLE = 1 << 30;
        /// Enables page translation.
        const PAGING = 1 << 31;
    }
}

/// Contains the Page Fault Linear Address (PFLA).
///
/// When page fault occurs, the CPU sets this register to the accessed address.
#[derive(Debug)]
pub struct Cr2;

/// Contains the physical address of the level 4 page table.
#[derive(Debug)]
pub struct Cr3;

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}

#[cfg(target_arch = "x86_64")]
mod x86_64 {
    use super::*;
    use structures::paging::PhysFrame;
    use {PhysAddr, VirtAddr};

    impl Cr0 {
        /// Read the current set of CR0 flags.
        pub fn read() -> Cr0Flags {
            Cr0Flags::from_bits_truncate(Self::read_raw())
        }

        /// Read the current raw CR0 value.
        pub fn read_raw() -> u64 {
            let value: u64;
            unsafe {
                asm!("mov %cr0, $0" : "=r" (value));
            }
            value
        }

        /// Write CR0 flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn write(flags: Cr0Flags) {
            let old_value = Self::read_raw();
            let reserved = old_value & !(Cr0Flags::all().bits());
            let new_value = reserved | flags.bits();

            Self::write_raw(new_value);
        }

        /// Write raw CR0 flags.
        ///
        /// Does _not_ preserve any values, including reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn write_raw(value: u64) {
            asm!("mov $0, %cr0" :: "r" (value) : "memory")
        }

        /// Updates CR0 flags.
        ///
        /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
        /// safety by e.g. disabling paging.
        pub unsafe fn update<F>(f: F)
        where
            F: FnOnce(&mut Cr0Flags),
        {
            let mut flags = Self::read();
            f(&mut flags);
            Self::write(flags);
        }
    }

    impl Cr2 {
        /// Read the current page fault linear address from the CR3 register.
        pub fn read() -> VirtAddr {
            let value: u64;
            unsafe {
                asm!("mov %cr2, $0" : "=r" (value));
            }
            VirtAddr::new(value)
        }
    }

    impl Cr3 {
        /// Read the current P4 table address from the CR3 register.
        pub fn read() -> (PhysFrame, Cr3Flags) {
            let value: u64;
            unsafe {
                asm!("mov %cr3, $0" : "=r" (value));
            }
            let flags = Cr3Flags::from_bits_truncate(value);
            let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
            let frame = PhysFrame::containing_address(addr);
            (frame, flags)
        }

        /// Write a new P4 table address into the CR3 register.
        ///
        /// ## Safety
        /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
        /// changing the page mapping.
        pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
            let addr = frame.start_address();
            let value = addr.as_u64() | flags.bits();
            asm!("mov $0, %cr3" :: "r" (value) : "memory")
        }
    }
}
<|endoftext|>


<commit_before>//! When specifying SSR rule, you generally want to map one *kind* of thing to
//! the same kind of thing: path to path, expression to expression, type to
//! type.
//!
//! The problem is, while this *kind* is generally obvious to the human, the ide
//! needs to determine it somehow. We do this in a stupid way -- by pasting SSR
//! rule into different contexts and checking what works.

use parser::SyntaxKind;
use syntax::{ast, AstNode, SyntaxNode};

pub(crate) fn ty(s: &str) -> Result<SyntaxNode, ()> {
    let template = "type T = {};";
    let input = template.replace("{}", s);
    let parse = syntax::SourceFile::parse(&input);
    if !parse.errors().is_empty() {
        return Err(());
    }
    let node = parse.tree().syntax().descendants().find_map(ast::Type::cast).ok_or(())?;
    Ok(node.syntax().clone())
}

pub(crate) fn item(s: &str) -> Result<SyntaxNode, ()> {
    let template = "{}";
    let input = template.replace("{}", s);
    let parse = syntax::SourceFile::parse(&input);
    if !parse.errors().is_empty() {
        return Err(());
    }
    let node = parse.tree().syntax().descendants().find_map(ast::Item::cast).ok_or(())?;
    Ok(node.syntax().clone())
}
<commit_msg>verify during parse<commit_after>//! When specifying SSR rule, you generally want to map one *kind* of thing to
//! the same kind of thing: path to path, expression to expression, type to
//! type.
//!
//! The problem is, while this *kind* is generally obvious to the human, the ide
//! needs to determine it somehow. We do this in a stupid way -- by pasting SSR
//! rule into different contexts and checking what works.

use syntax::{ast, AstNode, SyntaxNode};

pub(crate) fn ty(s: &str) -> Result<SyntaxNode, ()> {
    let template = "type T = {};";
    let input = template.replace("{}", s);
    let parse = syntax::SourceFile::parse(&input);
    if !parse.errors().is_empty() {
        return Err(());
    }
    let node = parse.tree().syntax().descendants().find_map(ast::Type::cast).ok_or(())?;
    if node.to_string() != s {
        return Err(());
    }
    Ok(node.syntax().clone())
}

pub(crate) fn item(s: &str) -> Result<SyntaxNode, ()> {
    let template = "{}";
    let input = template.replace("{}", s);
    let parse = syntax::SourceFile::parse(&input);
    if !parse.errors().is_empty() {
        return Err(());
    }
    let node = parse.tree().syntax().descendants().find_map(ast::Item::cast).ok_or(())?;
    if node.to_string() != s {
        return Err(());
    }
    Ok(node.syntax().clone())
}
<|endoftext|>


<commit_before>extern crate cmake;
extern crate gcc;
extern crate pkg_config;

use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    if env::var("LIBCUBEB_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libcubeb").is_ok() {
            return;
        }
    }

    if !Path::new("libcubeb/.git").exists() {
        let _ = Command::new("git")
            .args(&["submodule", "update", "--init", "--recursive"])
            .status();
    }

    let target = env::var("TARGET").unwrap();
    //    let host = env::var("HOST").unwrap();
    let windows = target.contains("windows");
    let darwin = target.contains("darwin");
    let mut cfg = cmake::Config::new("libcubeb");

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    env::remove_var("DESTDIR");
    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
        .define("BUILD_TESTS", "OFF")
        .build();

    if windows {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-search=native={}", dst.display());
        println!("cargo:rustc-link-lib=dylib=avrt");
        println!("cargo:rustc-link-lib=dylib=ole32");
        println!("cargo:rustc-link-lib=dylib=user32");
        println!("cargo:rustc-link-lib=dylib=winmm");
    } else if darwin {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        println!("cargo:rustc-link-lib=framework=CoreServices");
        println!("cargo:rustc-link-lib=dylib=c++");
        println!("cargo:rustc-link-search=native={}", dst.display());
    } else {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-lib=dylib=stdc++");
        println!("cargo:rustc-link-search=native={}", dst.display());

        pkg_config::find_library("alsa").unwrap();
        pkg_config::find_library("libpulse").unwrap();
        pkg_config::find_library("jack").unwrap();
    }
}
<commit_msg>cubeb-api: Fix linker path after libcubeb submodule update.<commit_after>extern crate cmake;
extern crate gcc;
extern crate pkg_config;

use std::env;
use std::fs;
use std::path::Path;
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    if env::var("LIBCUBEB_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libcubeb").is_ok() {
            return;
        }
    }

    if !Path::new("libcubeb/.git").exists() {
        let _ = Command::new("git")
            .args(&["submodule", "update", "--init", "--recursive"])
            .status();
    }

    let target = env::var("TARGET").unwrap();
    //    let host = env::var("HOST").unwrap();
    let windows = target.contains("windows");
    let darwin = target.contains("darwin");
    let mut cfg = cmake::Config::new("libcubeb");

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    env::remove_var("DESTDIR");
    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
        .define("BUILD_TESTS", "OFF")
        .build();

    if windows {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-lib=dylib=avrt");
        println!("cargo:rustc-link-lib=dylib=ole32");
        println!("cargo:rustc-link-lib=dylib=user32");
        println!("cargo:rustc-link-lib=dylib=winmm");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
    } else if darwin {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        println!("cargo:rustc-link-lib=framework=CoreServices");
        println!("cargo:rustc-link-lib=dylib=c++");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
    } else {
        println!("cargo:rustc-link-lib=static=cubeb");
        println!("cargo:rustc-link-lib=dylib=stdc++");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());

        pkg_config::find_library("alsa").unwrap();
        pkg_config::find_library("libpulse").unwrap();
        pkg_config::find_library("jack").unwrap();
    }
}
<|endoftext|>