<commit_before>#![crate_id = "seax-svm"]
#![crate_type="lib"]
#![feature(box_syntax)]
#![allow(dead_code)]

/// Contains the Seax Virtual Machine (SVM) and miscellaneous
/// support code.
pub mod svm {
    use svm::slist::List;
    use svm::slist::Stack;
    use std::iter::IteratorExt;

    /// Singly-linked list and stack implementations.
    pub mod slist {

        use svm::slist::List::{Cons,Nil};
        use std::fmt::Show;

        /// A stack implementation wrapping a List<T>
        pub struct Stack<T> {
            /// The head item of the list.
            head: Box<List<T>>
        }

        impl<T> Stack<T> {
            /// Push an item to the top of the stack, returning a new stack
            pub fn push(self, it: T) -> Stack<T> {
                Stack { head: Box::new(self.head.prepend(it)) }
            }

            /// Peak at the top item of the stack.
            ///
            /// Returns Some<T> if there is an item on top of the stack,
            /// and None if the stack is empty.
            pub fn peek(&self) -> Option<&T> {
                match *self.head {
                    Nil => None,
                    Cons(ref it,_) => Some(it)
                }
            }

            /// Returns an empty stack.
            pub fn empty() -> Stack<T> {
                Stack { head: box Nil }
            }

            /// Wraps a list into a stack.
            pub fn new(l: List<T>) -> Stack<T> {
                Stack { head: box l }
            }
        }

        /// Singly-linked cons list.
        ///
        /// This is used internally to represent list primitives in the machine.
        pub enum List<T> {
            Cons(T, Box<List<T>>),
            Nil,
        }

        /// Public implementation for List.
        impl<T> List<T> {

            /// Creates a new empty list
            pub fn new() -> List<T> {
                Nil
            }

            /// Prepends the given item to the list
            pub fn prepend(self, it: T) -> List<T> {
                Cons(it, box self)
            }

            /// Returns the length of the list
            pub fn length (&self) -> i32 {
                match *self {
                    Cons(_, ref tail) => 1 + tail.length(),
                    Nil => 0
                }
            }
        }

        impl<T> List<T> where T: Show {
            /// Return a string representation of the list
            fn to_string(&self) -> String {
                match *self {
                    Cons(ref head, ref tail) => format!("({:?}, {})", head, tail.to_string()),
                    Nil => format!("nil")
                }
            }

        }

       macro_rules! list(
            ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
            ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
            () => ( @Empty )
        );

        #[cfg(test)]
        mod tests {
            use super::{List, Stack};
            use super::List::{Cons,Nil};

            #[test]
            fn test_list_length() {
                let l: List<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
                assert_eq!(l.length(), 3);
            }

            #[test]
            fn test_list_to_string() {
                let l: List<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
                assert_eq!(l.to_string(), "(1i32, (2i32, (3i32, nil)))");
            }

            #[test]
            fn test_stack_peek() {
                let s: Stack<i32> = Stack::new(Cons(1, Box::new(Cons(2, Box::new(Nil)))));
                assert_eq!(s.peek(), Some(&1));
            }

            #[test]
            fn test_stack_push() {
                let mut s: Stack<i32> = Stack::empty();
                assert_eq!(s.peek(), None);
                s = s.push(1);
                assert_eq!(s.peek(), Some(&1));
                s = s.push(6);
                assert_eq!(s.peek(), Some(&6));
            }

            #[test]
            fn test_stack_pop() {
                let mut s: Stack<i32> = Stack::empty();
                assert_eq!(s.peek(), None);
                s = s.push(1);
                assert_eq!(s.peek(), Some(&1));
                s = s.push(6);
                assert_eq!(s.peek(), Some(&6));
            }

            #[test]
            fn test_list_macro() {
                let l: List<i32> = list!(1i32, 2i32, 3i32);
                assert_eq!(l.to_string(), "(1i32, (2i32, (3i32, nil)))")
            }
        }
    }

    /// SVM item types
    pub enum SVMCell {
        Atom,
        ListCell(Box<List<SVMCell>>)
    }

    pub enum Atom {
        AtomUInt(usize),
        AtomSInt(isize),
        AtomFloat(f64),
        AtomStr(String)
    }

    /// SVM instruction types
    pub enum SVMInstruction {
        /// `nil`
        ///
        /// Pushes an empty list (nil) onto the stack
        InstNIL,
        /// `ldc`: `L`oa`d` `C`onstant. Loads a constant (atom)
        InstLDC(Atom),
        /// `ld`: `L`oa`d`. Pushes a variable onto the stack.
        ///
        /// The variable is indicated by the argument, a pair.
        /// The pair's `car` specifies the level, the `cdr` the position.
        /// So `(1 . 3)` gives the current function's (level 1) third
        /// parameter.
        InstLD,
        /// `ldf`: `L`oa`d` `F`unction.
        ///
        ///  Takes one list argument representing a function and constructs
        ///  a closure (a pair containing the function and the current
        ///  environment) and pushes that onto the stack.
        InstLDF,
        /// `join`
        ///
        /// Pops a list reference from the dump and makes this the new value
        /// of `C`. This instruction occurs at the end of both alternatives of
        ///  a `sel`.
        InstJOIN,
        /// `ap`: `Ap`ply.
        ///
        /// Pops a closure and a list of parameter values from the stack.
        /// The closure is applied to the parameters by installing its
        /// environment as the current one, pushing the parameter list
        /// in front of that, clearing the stack, and setting `C` to the
        /// closure's function pointer. The previous values of `S`, `E`,
        ///  and the next value of `C` are saved on the dump.
        InstAP,
        /// `ret`: `Ret`urn.
        ///
        /// Pops one return value from the stack, restores
        /// `S`, `E`, and `C` from the dump, and pushes
        /// the return value onto the now-current stack.
        InstRET,
        /// `dum`: `Dum`my.
        ///
        /// Pops a dummy environment (an empty list) onto the `E` stack.
        InstDUM,
        /// `rap`: `R`ecursive `Ap`ply.
        /// Works like `ap`, only that it replaces an occurrence of a
        /// dummy environment with the current one, thus making recursive
        ///  functions possible.
        InstRAP,
        /// `sel`: `Sel`ect
        ///
        /// Expects two list arguments, and pops a value from the stack.
        /// The first list is executed if the popped value was non-nil,
        /// the second list otherwise. Before one of these list pointers
        ///  is made the new `C`, a pointer to the instruction following
        ///  `sel` is saved on the dump.
        InstSEL,
        /// `add`
        ///
        /// Pops two numbers off of the stack and adds them, pushing the
        /// result onto the stack. This will up-convert integers to floating
        /// point if necessary.
        ///
        /// TODO: figure out what happens when you try to add things that aren't
        /// numbers (maybe the compiler won't let this happen?).
        InstADD,
        /// `sub`: `Sub`tract
        ///
        /// Pops two numbers off of the stack and subtracts the first from the
        /// second, pushing the result onto the stack. This will up-convert
        /// integers to floating point if necessary.
        ///
        /// TODO: figure out what happens when you try to subtract things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstSUB,
        /// `mul`: `Mul`tiply
        ///
        /// Pops two numbers off of the stack and multiplies them, pushing the
        /// result onto the stack. This will up-convert integers to floating
        /// point if necessary.
        ///
        /// TODO: figure out what happens when you try to multiply things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstMUL,
        /// `div`: `Div`ide
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the result onto the stack. This performs integer division.
        ///
        /// TODO: figure out what happens when you try to divide things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstDIV,
        /// `fdiv`: `F`loating-point `div`ide
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the result onto the stack. This performs float division.
        ///
        /// TODO: figure out what happens when you try to divide things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        ///
        /// TODO: Not sure if there should be separate float and int divide words
        /// I guess the compiler can figure this out
        InstFDIV,
        /// `mod`: `Mod`ulo
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the remainder onto the stack.
        ///
        /// TODO: figure out what happens when you try to modulo things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstMOD
        // TODO: add some hardcoded I/O instructions here so that you can
        //  do I/O without farming everything out to `stdio`
        // TODO: add `cons` and `cdr` words
    }

    /// Represents a SVM machine state
    pub struct State {
        stack: Stack<SVMCell>,
        env: Stack<SVMCell>,
        control: Stack<SVMCell>,
        dump: Stack<SVMCell>
    }

    impl State {

        /// Creates a new empty state
        fn new() -> State {
            State {
                stack: Stack::empty(),
                env: Stack::empty(),
                control: Stack::empty(),
                dump: Stack::empty()
            }
        }

        /// Evaluates an instruction.
        ///
        /// Evaluates an instruction against a state, returning a new state.
        pub fn eval(self, inst: SVMInstruction) -> State {
            match inst {
                SVMInstruction::InstNIL => State {
                    stack: self.stack.push(SVMCell::ListCell(box List::new())),
                    env: self.env,
                    control: self.control,
                    dump: self.dump
                },
                _ => { unimplemented!() }
            }
        }
    }

}
<commit_msg>Documentation and test improvements<commit_after>#![crate_id = "seax-svm"]
#![crate_type="lib"]
#![feature(box_syntax)]
#![allow(dead_code)]

/// Contains the Seax Virtual Machine (SVM) and miscellaneous
/// support code.
pub mod svm {
    use svm::slist::List;
    use svm::slist::Stack;
    use std::iter::IteratorExt;

    /// Singly-linked list and stack implementations. `List<T>` is a
    /// singly-linked cons list with boxed items. `Stack<T>` is basically
    /// just a struct containing a boxed pointer to the head of a list,
    /// and some methods.
    pub mod slist {

        use svm::slist::List::{Cons,Nil};
        use std::fmt::Show;

        /// A stack implementation wrapping a `List<T>`
        ///
        /// This is essentially just a struct containing a boxed pointer
        /// to the head of a `List<T>`, so that when items are pushed to or
        /// popped from the stack, the pointer is changed to point to the
        /// new head item. There may be saner ways of doing this.
        pub struct Stack<T> {
            /// The head item of the list.
            head: Box<List<T>>
        }

        impl<T> Stack<T> {
            /// Push an item to the top of the stack, returning a new stack
            pub fn push(self, it: T) -> Stack<T> {
                Stack { head: Box::new(self.head.prepend(it)) }
            }

            /// Peak at the top item of the stack.
            ///
            /// Returns Some<T> if there is an item on top of the stack,
            /// and None if the stack is empty.
            pub fn peek(&self) -> Option<&T> {
                match *self.head {
                    Nil => None,
                    Cons(ref it,_) => Some(it)
                }
            }

            /// Returns an empty stack.
            pub fn empty() -> Stack<T> {
                Stack { head: box Nil }
            }

            /// Wraps a list into a stack.
            pub fn new(l: List<T>) -> Stack<T> {
                Stack { head: box l }
            }
        }

        /// Singly-linked cons list.
        ///
        /// This is used internally to represent list primitives in the machine.
        pub enum List<T> {
            Cons(T, Box<List<T>>),
            Nil,
        }

        /// Public implementation for List.
        impl<T> List<T> {

            /// Creates a new empty list
            pub fn new() -> List<T> {
                Nil
            }

            /// Prepends the given item to the list, returning the new head item.
            pub fn prepend(self, it: T) -> List<T> {
                Cons(it, box self)
            }

            /// Returns the length of the list.
            pub fn length (&self) -> isize {
                match *self {
                    Cons(_, ref tail) => 1 + tail.length(),
                    Nil => 0
                }
            }
        }

        impl<T> List<T> where T: Show {
            /// Return a string representation of the list
            fn to_string(&self) -> String {
                match *self {
                    Cons(ref head, ref tail) => format!("({:?}, {})", head, tail.to_string()),
                    Nil => format!("nil")
                }
            }

        }

        /// Convenience macro for making lists.
        ///
        /// Usage: `list!(1i32, 2i32, 3i32);` expands to
        /// `Cons(1i32, Box::new(Cons(2i32, Box::new(Cons(3i32, Box::new(Nil))))));`.
        macro_rules! list(
            ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
            ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
            () => ( @Empty )
        );

        #[cfg(test)]
        mod tests {
            use super::{List, Stack};
            use super::List::{Cons,Nil};

            #[test]
            fn test_list_length() {
                let full_list: List<i32> = list!(1i32, 2i32, 3i32);
                let empty_list: List<i32> = List::new();
                assert_eq!(full_list.length(), 3);
                assert_eq!(empty_list.length(), 0);
            }

            #[test]
            fn test_list_to_string() {
                let l: List<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
                assert_eq!(l.to_string(), "(1i32, (2i32, (3i32, nil)))");
            }

            #[test]
            fn test_stack_peek() {
                let s: Stack<i32> = Stack::new(list!(1i32, 2i32, 3i32));
                assert_eq!(s.peek(), Some(&1));
            }

            #[test]
            fn test_stack_push() {
                let mut s: Stack<i32> = Stack::empty();
                assert_eq!(s.peek(), None);
                s = s.push(1);
                assert_eq!(s.peek(), Some(&1));
                s = s.push(6);
                assert_eq!(s.peek(), Some(&6));
            }

            #[test]
            fn test_stack_pop() {
                let mut s: Stack<i32> = Stack::empty();
                assert_eq!(s.peek(), None); // TODO: implement
                s = s.push(1);
                assert_eq!(s.peek(), Some(&1));
                s = s.push(6);
                assert_eq!(s.peek(), Some(&6));
            }

            #[test]
            fn test_list_macro() {
                let l: List<i32> = list!(1i32, 2i32, 3i32);
                assert_eq!(l.to_string(), "(1i32, (2i32, (3i32, nil)))")
            }
        }
    }

    /// SVM item types
    pub enum SVMCell {
        Atom,
        ListCell(Box<List<SVMCell>>)
    }

    pub enum Atom {
        AtomUInt(usize),
        AtomSInt(isize),
        AtomFloat(f64),
        AtomStr(String)
    }

    /// SVM instruction types
    pub enum SVMInstruction {
        /// `nil`
        ///
        /// Pushes an empty list (nil) onto the stack
        InstNIL,
        /// `ldc`: `L`oa`d` `C`onstant. Loads a constant (atom)
        InstLDC(Atom),
        /// `ld`: `L`oa`d`. Pushes a variable onto the stack.
        ///
        /// The variable is indicated by the argument, a pair.
        /// The pair's `car` specifies the level, the `cdr` the position.
        /// So `(1 . 3)` gives the current function's (level 1) third
        /// parameter.
        InstLD,
        /// `ldf`: `L`oa`d` `F`unction.
        ///
        ///  Takes one list argument representing a function and constructs
        ///  a closure (a pair containing the function and the current
        ///  environment) and pushes that onto the stack.
        InstLDF,
        /// `join`
        ///
        /// Pops a list reference from the dump and makes this the new value
        /// of `C`. This instruction occurs at the end of both alternatives of
        ///  a `sel`.
        InstJOIN,
        /// `ap`: `Ap`ply.
        ///
        /// Pops a closure and a list of parameter values from the stack.
        /// The closure is applied to the parameters by installing its
        /// environment as the current one, pushing the parameter list
        /// in front of that, clearing the stack, and setting `C` to the
        /// closure's function pointer. The previous values of `S`, `E`,
        ///  and the next value of `C` are saved on the dump.
        InstAP,
        /// `ret`: `Ret`urn.
        ///
        /// Pops one return value from the stack, restores
        /// `S`, `E`, and `C` from the dump, and pushes
        /// the return value onto the now-current stack.
        InstRET,
        /// `dum`: `Dum`my.
        ///
        /// Pops a dummy environment (an empty list) onto the `E` stack.
        InstDUM,
        /// `rap`: `R`ecursive `Ap`ply.
        /// Works like `ap`, only that it replaces an occurrence of a
        /// dummy environment with the current one, thus making recursive
        ///  functions possible.
        InstRAP,
        /// `sel`: `Sel`ect
        ///
        /// Expects two list arguments, and pops a value from the stack.
        /// The first list is executed if the popped value was non-nil,
        /// the second list otherwise. Before one of these list pointers
        ///  is made the new `C`, a pointer to the instruction following
        ///  `sel` is saved on the dump.
        InstSEL,
        /// `add`
        ///
        /// Pops two numbers off of the stack and adds them, pushing the
        /// result onto the stack. This will up-convert integers to floating
        /// point if necessary.
        ///
        /// TODO: figure out what happens when you try to add things that aren't
        /// numbers (maybe the compiler won't let this happen?).
        InstADD,
        /// `sub`: `Sub`tract
        ///
        /// Pops two numbers off of the stack and subtracts the first from the
        /// second, pushing the result onto the stack. This will up-convert
        /// integers to floating point if necessary.
        ///
        /// TODO: figure out what happens when you try to subtract things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstSUB,
        /// `mul`: `Mul`tiply
        ///
        /// Pops two numbers off of the stack and multiplies them, pushing the
        /// result onto the stack. This will up-convert integers to floating
        /// point if necessary.
        ///
        /// TODO: figure out what happens when you try to multiply things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstMUL,
        /// `div`: `Div`ide
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the result onto the stack. This performs integer division.
        ///
        /// TODO: figure out what happens when you try to divide things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstDIV,
        /// `fdiv`: `F`loating-point `div`ide
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the result onto the stack. This performs float division.
        ///
        /// TODO: figure out what happens when you try to divide things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        ///
        /// TODO: Not sure if there should be separate float and int divide words
        /// I guess the compiler can figure this out
        InstFDIV,
        /// `mod`: `Mod`ulo
        ///
        /// Pops two numbers off of the stack and divides the first by the second,
        /// pushing the remainder onto the stack.
        ///
        /// TODO: figure out what happens when you try to modulo things that
        /// aren't numbers (maybe the compiler won't let this happen?).
        InstMOD
        // TODO: add some hardcoded I/O instructions here so that you can
        //  do I/O without farming everything out to `stdio`
        // TODO: add `cons` and `cdr` words
    }

    /// Represents a SVM machine state
    pub struct State {
        stack: Stack<SVMCell>,
        env: Stack<SVMCell>,
        control: Stack<SVMCell>,
        dump: Stack<SVMCell>
    }

    impl State {

        /// Creates a new empty state
        fn new() -> State {
            State {
                stack: Stack::empty(),
                env: Stack::empty(),
                control: Stack::empty(),
                dump: Stack::empty()
            }
        }

        /// Evaluates an instruction.
        ///
        /// Evaluates an instruction against a state, returning a new state.
        pub fn eval(self, inst: SVMInstruction) -> State {
            match inst {
                SVMInstruction::InstNIL => State {
                    stack: self.stack.push(SVMCell::ListCell(box List::new())),
                    env: self.env,
                    control: self.control,
                    dump: self.dump
                },
                _ => { unimplemented!() }
            }
        }
    }

    /*
    /// Evaluates a program.
    ///
    /// Evaluates a program represented as an `Iterator` of `SVMInstruction`s.
    /// Returns the final machine state at the end of execution

    pub fn evalProgram(insts: Iterator<Item=SVMInstruction>) -> State {
        insts.fold(State::new(), |last_state: State, inst: SVMInstruction| last_state.eval(inst));
    }*/

}
<|endoftext|>


<commit_before>use chrono::*;
use http_headers::*;
use hyper::header::Headers;
use openssl::crypto::hash::hash;
use openssl::crypto::hash::Type::SHA1;
use openssl::crypto::pkey::PKey;
use rustc_serialize::base64::ToBase64;
use std::fmt;
use std::fs::File;
use utils::{squeeze_path, expand_string};
use authentication::BASE64_AUTH;

#[derive(Clone)]
pub struct Auth12 {
    body: Option<String>,
    date: String,
    pub headers: Headers,
    keypath: String,
    method: String,
    path: String,
    userid: String,
    version: String,
}

impl fmt::Debug for Auth12 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Auth12")
         .field("method", &self.method)
         .field("userid", &self.userid)
         .field("path", &self.path)
         .field("body", &self.body)
         .field("keypath", &self.keypath)
         .finish()
    }
}

impl Auth12 {
    pub fn new<P, K, M, U>(path: P, key: K, method: M, userid: U) -> Auth12
        where P: Into<String>,
              K: Into<String>,
              M: Into<String>,
              U: Into<String>
    {
        let dt = UTC::now().format("%Y-%m-%dT%H:%M:%SZ").to_string();

        let userid = userid.into();

        let mut headers = Headers::new();
        headers.set(OpsSign(String::from("algorithm=sha1;version=1.2")));
        headers.set(OpsTimestamp(dt.clone()));
        headers.set(OpsUserId(userid.clone()));

        Auth12 {
            body: None,
            date: dt,
            headers: headers,
            keypath: key.into(),
            method: method.into(),
            path: squeeze_path(path.into()),
            userid: userid,
            version: String::from("1.2"),
        }
    }

    pub fn body<S>(mut self, body: S) -> Auth12
        where S: Into<String>
    {
        self.body = Some(body.into());
        self
    }

    fn hashed_path(&self) -> String {
        debug!("Path is: {:?}", &self.path);
        hash(SHA1, &self.path.as_bytes()).to_base64(BASE64_AUTH)
    }

    fn content_hash(&self) -> String {
        let body = expand_string(&self.body);
        let content = hash(SHA1, body.as_bytes()).to_base64(BASE64_AUTH);
        debug!("{:?}", content);
        content
    }

    fn set_content_hash(mut self) -> Auth12 {
        let hsh = self.content_hash();
        self.headers.set(OpsContentHash(hsh));
        self
    }

    fn canonical_user_id(&self) -> String {
        hash(SHA1, &self.userid.as_bytes()).to_base64(BASE64_AUTH)
    }

    fn canonical_request(&self) -> String {
        let cr = format!("Method:{}\nHashed \
                          Path:{}\nX-Ops-Content-Hash:{}\nX-Ops-Timestamp:{}\nX-Ops-UserId:{}",
                         &self.method,
                         self.hashed_path(),
                         self.content_hash(),
                         self.date,
                         self.canonical_user_id());
        debug!("Canonical Request is: {:?}", cr);
        cr

    }

    fn encrypted_request(&self) -> String {
        match File::open(&self.keypath) {
            Ok(mut fh) => {
                let key = PKey::private_key_from_pem(&mut fh).unwrap();
                key.private_encrypt(&self.canonical_request().as_bytes()).to_base64(BASE64_AUTH)
            }
            Err(_) => panic!("Couldn't open private key"),
        }
    }

    pub fn headers(self) -> Headers {
        let fin = self.set_content_hash();
        let enc = fin.encrypted_request();
        let mut headers = fin.headers;
        let mut i = 1;
        for h in enc.split('\n') {
            let key = format!("X-Ops-Authorization-{}", i);
            headers.set_raw(key, vec![h.as_bytes().to_vec()]);
            i += 1;
        }
        headers
    }
}

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

    use http_headers::*;
    use hyper::header::Headers;

    const PATH: &'static str = "/organizations/clownco";
    const BODY: &'static str = "Spec Body";
    const USER: &'static str = "spec-user";
    const DT: &'static str = "2009-01-01T12:00:00Z";

    const PRIVATE_KEY: &'static str = "fixtures/spec-user.pem";

    #[test]
    fn test_new_authentication() {
        let auth = Auth12::new(PATH, PRIVATE_KEY, "GET", USER);
        assert_eq!(auth.body, None)
    }

    #[test]
    fn test_userid() {
        let auth = Auth12::new(PATH, PRIVATE_KEY, "GET", USER);
        assert_eq!(auth.userid, "spec-user");
        assert_eq!(auth.headers.get::<OpsUserId>().unwrap().to_string(),
                   "spec-user")
    }

    #[test]
    fn test_method() {
        let auth = Auth12::new(PATH, PRIVATE_KEY, "GET", USER);
        assert_eq!(auth.method, "GET")
    }

    #[test]
    fn test_canonical_user_id_v12() {
        let auth = Auth12::new(PATH, PRIVATE_KEY, "GET", USER);
        assert_eq!(auth.canonical_user_id(), "EAF7Wv/hbAudWV5ZkwKz40Z/lO0=")
    }

    #[test]
    fn test_canonical_request() {
        let auth = Auth12 {
            body: Some(String::from(BODY)),
            date: String::from(DT),
            headers: Headers::new(),
            keypath: String::from(""),
            method: String::from("POST"),
            path: String::from(PATH),
            userid: String::from(USER),
            version: String::from("1.2"),
        };
        assert_eq!(auth.canonical_request(),
                   "Method:POST\nHashed \
                    Path:YtBWDn1blGGuFIuKksdwXzHU9oE=\nX-Ops-Content-Hash:\
                    DFteJZPVv6WKdQmMqZUQUumUyRs=\nX-Ops-Timestamp:2009-01-01T12:00:\
                    00Z\nX-Ops-UserId:EAF7Wv/hbAudWV5ZkwKz40Z/lO0=")
    }

    #[test]
    fn test_private_key() {
        let auth = Auth12 {
            body: Some(String::from(BODY)),
            date: String::from(DT),
            headers: Headers::new(),
            keypath: String::from(PRIVATE_KEY),
            method: String::from("POST"),
            path: String::from(PATH),
            userid: String::from(USER),
            version: String::from("1.2"),
        };
        assert_eq!(&auth.encrypted_request(),
                   "UfZD9dRz6rFu6LbP5Mo1oNHcWYxpNIcUfFCffJS1FQa0GtfU/vkt3/O5HuCM\n1wIFl/U0f5faH9EW\
                    pXWY5NwKR031Myxcabw4t4ZLO69CIh/3qx1XnjcZvt2w\nc2R9bx/43IWA/r8w8Q6decuu0f6ZlNhe\
                    JeJhaYPI8piX/aH+uHBH8zTACZu8\nvMnl5MF3/OIlsZc8cemq6eKYstp8a8KYq9OmkB5IXIX6qVMJ\
                    HA6fRvQEB/7j\n281Q7oI/O+lE8AmVyBbwruPb7Mp6s4839eYiOdjbDwFjYtbS3XgAjrHlaD7W\nFD\
                    lbAG7H8Dmvo+wBxmtNkszhzbBnEYtuwQqT8nM/8A==")
    }

    #[test]
    fn test_headers() {
        let auth = Auth12::new(PATH, PRIVATE_KEY, "GET", USER);
        let headers = auth.as_headers();

        let _ = headers.get_raw("x-ops-authorization-1").unwrap();
    }
}
<commit_msg>We'll never implement the 1.2 auth scheme<commit_after><|endoftext|>


<commit_before>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8])
        .unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8]);
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8]);
    match dbc {
        Success(c) => panic_with_diagnostic(&c.disconnect()),
        Info(c) => panic_with_diagnostic(&c),
        Error(c) => panic_with_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8])
        .unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        match stmt.exec_direct(b"SELECT * FROM information_schema.tables" as &[u8]) {
            ReturnNoData::Success(s) |
            ReturnNoData::Info(s) => {
                panic_with_diagnostic(&s);
                assert_eq!(12, s.num_result_cols().unwrap());
            }
            ReturnNoData::NoData(_) => panic!("No Data"),
            ReturnNoData::Error(s) => {
                panic_with_diagnostic(&s);
            }
        }
    }
    dbc.disconnect().unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn panic_with_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) |
        DiagReturn::Info(dr) => {
            panic!(
                "{}",
                str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
            )
        }
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}
<commit_msg>refactor for readability<commit_after>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8])
        .unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8]);
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8]);
    match dbc {
        Success(c) => assert_no_diagnostic(&c.disconnect()),
        Info(c) => assert_no_diagnostic(&c),
        Error(c) => assert_no_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8])
        .unwrap();
    {
        let stmt = Statement::with_parent(&dbc).unwrap();
        let stmt = match stmt.exec_direct(b"SELECT * FROM information_schema.tables" as &[u8]) {
            ReturnNoData::Success(s) | ReturnNoData::Info(s) => {
                assert_no_diagnostic(&s);
                s
            }
            ReturnNoData::NoData(_) => panic!("No Data"),
            ReturnNoData::Error(s) => panic!("{}", get_last_error(&s)),
        };
        assert_eq!(12, stmt.num_result_cols().unwrap());
    }
    dbc.disconnect().unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn assert_no_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => {
            panic!(
                "{}",
                str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
            )
        }
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}

fn get_last_error(diag: &Diagnostics) -> String {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) | DiagReturn::Info(dr) => {
            str::from_utf8(&buffer[0..(dr.text_length as usize)])
                .unwrap()
                .to_owned()
        }
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => panic!("No diagnostic available"),
    }
}
<|endoftext|>


<commit_before>extern crate mtl;
extern crate cocoa;

use mtl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion};
use mtl::LibraryErrorType;
use mtl::{FromRaw, FromRawError, IntoRaw};
use mtl::sys::{MTLCompileOptions, MTLLanguageVersion};
use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    let dummy_command_queue_name = "foo";
    command_queue.set_label(dummy_command_queue_name);

    assert_eq!(command_queue.get_label().into_owned(),
               dummy_command_queue_name.to_string());
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}
<commit_msg>Fix tests<commit_after>extern crate mtl;
extern crate cocoa;

use mtl::{CompileOptions, Device, LanguageVersion, SpecificLanguageVersion};
use mtl::LibraryErrorType;
use mtl::{FromRaw, FromRawError, IntoRaw};
use mtl::sys::{MTLCompileOptions, MTLLanguageVersion};
use cocoa::base::{BOOL, nil};
use cocoa::foundation::NSString;

#[test]
fn get_device() {
    let device = Device::system_default_device();
    assert!(device.is_ok());
}

#[test]
fn get_all_devices() {
    let all_devices = Device::enumerate_all_system_devices();
    assert!(!all_devices.is_empty());
    for device in all_devices {
        assert!(device.is_ok());
    }
}

#[test]
fn get_device_name() {
    let device = Device::system_default_device().unwrap();
    assert!(!device.name().into_owned().is_empty());
}

#[test]
fn set_get_command_queue_label() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();

    let dummy_command_queue_name = "foo";
    command_queue.set_label(dummy_command_queue_name);

    assert_eq!(command_queue.label().into_owned(),
               dummy_command_queue_name.to_string());
}

#[test]
fn insert_debug_capture_boundary_on_command_queue() {
    let mut device = Device::system_default_device().unwrap();
    let mut command_queue = device.new_command_queue().unwrap();
    command_queue.insert_debug_capture_boundary();

    // if nothing panics/fails here, everything is okay
}

#[test]
fn device_from_to_raw() {
    let device = Device::system_default_device().unwrap();
    let raw = device.into_raw();
    let device = Device::from_raw(raw);
    assert!(device.is_ok());
}

#[test]
fn device_from_wrong_type() {
    let some_string = unsafe { NSString::alloc(nil).init_str("Hello") };
    let device_result = Device::from_raw(some_string);
    match device_result {
        Result::Err(FromRawError::WrongPointerType) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn device_from_nullptr() {
    let device_result = Device::from_raw(nil);
    match device_result {
        Result::Err(FromRawError::NilPointer) => {
            // pass
        }
        _ => assert!(false),
    }
}

#[test]
fn compile_opts_creation_is_correct() {
    let fast_math_enabled = true;
    let options = CompileOptions::default()
                      .fast_math_enabled(fast_math_enabled)
                      .language_version(LanguageVersion::Specific(SpecificLanguageVersion::Version_1_0))
                      .with_macro("Foo", 54)
                      .with_macro("Bar", 32.0)
                      .with_macro("Baz", "Hi")
                      .mtl_compile_options();

    unsafe {
        assert_eq!(fast_math_enabled as BOOL, options.fastMathEnabled());
        assert_eq!(options.languageVersion(),
                   MTLLanguageVersion::MTLLanguageVersion1_0);
    }
}

#[test]
fn create_invalid_shader() {
    let mut device = Device::system_default_device().unwrap();
    const BAD_SHADER: &'static str = r"abcdefghijklmnopqrstuvwxyz";
    match device.new_library_with_source(&BAD_SHADER, &Default::default()) {
        Ok(_) => panic!("Incorrect result: expected an error"),
        Err(error) => {
            if let LibraryErrorType::SourceError = error.error_type {
                assert!(true);
            } else {
                panic!("Incorrect error type");
            }
        }
    }
}

#[test]
fn device_create_library_with_valid_shader_code_and_get_fn_names() {
    let mut device = Device::system_default_device().unwrap();
    // Shader source taken from http://metalbyexample.com/up-and-running-2/
    const SHADER: &'static str = r"
        using namespace metal;

        struct ColoredVertex
        {
            float4 position [[position]];
            float4 color;
        };

        vertex ColoredVertex vertex_main(constant float4 *position [[buffer(0)]],
                                         constant float4 *color [[buffer(1)]],
                                         uint vid [[vertex_id]])
        {
            ColoredVertex vert;
            vert.position = position[vid];
            vert.color = color[vid];
            return vert;
        }

        fragment float4 fragment_main(ColoredVertex vert [[stage_in]])
        {
            return vert.color;
        }
    ";
    let library = device.new_library_with_source(&SHADER, &Default::default()).ok().unwrap();
    let names = library.function_names();
    assert_eq!(names[0], "vertex_main");
    assert_eq!(names[1], "fragment_main");
}
<|endoftext|>


<commit_before>use std::ptr;

macro_rules! A32(
    ($expr:expr) => (
        {
            let thing: *u32 = ::std::cast::transmute($expr);
            *thing
        }
    )
)

macro_rules! rotl32(
    ($x:expr, $r:expr) => ( ($x << $r) | ($x >> (32 - $r)) )
)

// macro_rules! rotl32u(
//     ($x:expr, $r:expr) => ( (x << r) | (x >> (32u32 - r)) )
// )

macro_rules! swap32(
    ($x:expr) => (::std::unstable::intrinsics::bswap32($x as i32))
)

macro_rules! do_while(
    ($body:expr, $cond:expr) => (
        loop {
            $body;

            if !$cond { break; }
        }
    )
)

static SIZE_OF_STATE: uint = 48;

#[cfg(target_endian = "big")]
static ENDIANNESS: Endianness =  BigEndian;

#[cfg(target_endian = "little")]
static ENDIANNESS: Endianness =  LittleEndian;

// pub fn size_of_state() -> uint {
//     std::sys::size_of::<State>()
// }

#[deriving(Eq, Clone, ToStr)]
enum ErrCode {
    Okay = 0,
    Error
}

#[deriving(Eq, Clone, ToStr)]
enum Alignment {
    Aligned,
    Unaligned
}

#[deriving(Eq, Clone, ToStr)]
enum Endianness {
    LittleEndian,
    BigEndian
}

static PRIME32_1: u32 = 2654435761u32;
static PRIME32_2: u32 = 2246822519u32;
static PRIME32_3: u32 = 3266489917u32;
static PRIME32_4: u32 = 668265263u32;
static PRIME32_5: u32 = 374761393u32;

#[inline(always)]
fn read_le32_align(ptr: *u32, endian: Endianness, align: Alignment) -> u32 {
    unsafe {
        if align == Unaligned {
            if endian == LittleEndian { A32!(ptr) } else { (swap32!(A32!(ptr)) as u32) }
        } else {
            if endian == LittleEndian { *ptr } else { (swap32!(*ptr) as u32) }
        }
    }
}

#[inline(always)]
fn read_le32(ptr: *u32, endian: Endianness) -> u32 {
    read_le32_align(ptr, endian, Unaligned)
}

#[inline(always)]
fn endian_align(input: *u8, len: uint, seed: u32, endian: Endianness, align: Alignment) -> u32 {
    let mut p = input;
    let b_end = unsafe { input.offset(len as int) };
    let mut h32: u32;

    if len >= 16u {
        let limit = unsafe { b_end.offset(-16) };
        let mut v1: u32 = seed + PRIME32_1 + PRIME32_2;
        let mut v2: u32 = seed + PRIME32_2;
        let mut v3: u32 = seed + 0u32;
        let mut v4: u32 = seed - PRIME32_1;

        do_while!({
            v1 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v1 = rotl32!(v1, 13);
            v1 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v2 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v2 = rotl32!(v2, 13);
            v2 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v3 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v3 = rotl32!(v3, 13);
            v3 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v4 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v4 = rotl32!(v4, 13);
            v4 *= PRIME32_1;
            p = unsafe { p.offset(4) };

        }, p <= limit)

        h32 = rotl32!(v1, 1) + rotl32!(v2, 7) + rotl32!(v3, 12) + rotl32!(v4, 18);
    } else {
        h32 = seed + PRIME32_5;
    }

    h32 += len as u32;

    while unsafe { p <= b_end.offset(-4) } {
        h32 += read_le32_align(p as *u32, endian, align) * PRIME32_3;
        h32 = rotl32!(h32, 17) * PRIME32_4;
        p = unsafe { p.offset(4) };
    }

    while p <= b_end {
        h32 += unsafe { *p } as u32 * PRIME32_5;
        h32 = rotl32!(h32, 11) * PRIME32_1;
        p = unsafe { p.offset(1) };
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;

    h32
}

fn xxh32(input: *u8, len: uint, seed: u32) -> u32 {
    if ENDIANNESS == LittleEndian {
        endian_align(input, len, seed, LittleEndian, Unaligned)
    } else {
        endian_align(input, len, seed, BigEndian, Unaligned)
    }
}

// #[deriving(Clone, ToStr)]
struct State32 {
    total_len: u64,
    seed: u32,
    v1: u32,
    v2: u32,
    v3: u32,
    v4: u32,
    memsize: i32,
    memory: [u8, ..16]
}

impl State32 {
    pub fn new(seed: u32) -> State32 {
        State32 {
            total_len: 0u64,
            seed: seed,
            v1: seed + PRIME32_1 + PRIME32_2,
            v2: seed + PRIME32_2,
            v3: seed + 0u32,
            v4: seed - PRIME32_1,
            memsize: 0i32,
            memory: [0u8, ..16]
        }
    }
}

fn size_of_state() -> uint {
    use std::mem;

    assert!(SIZE_OF_STATE >= mem::size_of::<State32>());

    mem::size_of::<State32>()
}

fn reset_state(state: &mut State32, seed: u32) -> ErrCode {
    state.seed = seed;
    state.v1 = seed + PRIME32_1 + PRIME32_2;
    state.v2 = seed + PRIME32_2;
    state.v3 = seed + 0u32;
    state.v4 = seed + PRIME32_1;
    state.total_len = 0u64;
    state.memsize = 0i32;
    Okay
}

#[inline(always)]
fn update_endian(state: &mut State32, input: *u8, len: uint, endian: Endianness) -> ErrCode {
    let mut p = input;
    let b_end = unsafe { input.offset(len as int) };

    assert!(ptr::is_not_null(p));

    state.total_len += len as u64;

    if state.memsize + (len as i32) < 16 {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf.offset(state.memsize as int), input, len);
            }
        };

        state.memsize += len as i32;
        return Okay;
    }

    if (state.memsize > 0) {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf.offset(state.memsize as int), input, 16 - state.memsize as uint);
            }
        };
        unsafe {
            let mut p32: *u32 = p as *u32;
            state.v1 += read_le32(p32, endian) * PRIME32_2;
            state.v1 = rotl32!(state.v1, 13);
            state.v1 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v2 += read_le32(p32, endian) * PRIME32_2;
            state.v2 = rotl32!(state.v2, 13);
            state.v2 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v3 += read_le32(p32, endian) * PRIME32_2;
            state.v3 = rotl32!(state.v3, 13);
            state.v3 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v4 += read_le32(p32, endian) * PRIME32_2;
            state.v4 = rotl32!(state.v4, 13);
            state.v4 *= PRIME32_1;
//             p32 = p32.offset(1);
        }

        p = unsafe { p.offset(16 - state.memsize as int) };
        state.memsize = 0i32;
    }

    if unsafe { p <= b_end.offset(-16) }{
        let limit = unsafe { b_end.offset(-16) };
        let mut v1 = state.v1;
        let mut v2 = state.v2;
        let mut v3 = state.v3;
        let mut v4 = state.v4;

        do_while!({
            v1 += read_le32(p as *u32, endian) * PRIME32_2;
            v1 = rotl32!(v1, 13);
            v1 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v2 += read_le32(p as *u32, endian) * PRIME32_2;
            v2 = rotl32!(v2, 13);
            v2 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v3 += read_le32(p as *u32, endian) * PRIME32_2;
            v3 = rotl32!(v3, 13);
            v3 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v4 += read_le32(p as *u32, endian) * PRIME32_2;
            v4 = rotl32!(v4, 13);
            v4 *= PRIME32_1;
            p = unsafe { p.offset(4) };

        }, p <= limit)

        state.v1 = v1;
        state.v2 = v2;
        state.v3 = v3;
        state.v4 = v4;
    }

    if p < b_end {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf, p, b_end.to_uint() - p.to_uint());
            }
        };

        state.memsize = (b_end.to_uint() - p.to_uint() ) as i32;
    }

    Okay
}<commit_msg>First commit<commit_after>use std::ptr;

macro_rules! A32(
    ($expr:expr) => (
        {
            let thing: *u32 = ::std::cast::transmute($expr);
            *thing
        }
    )
)

macro_rules! rotl32(
    ($x:expr, $r:expr) => ( ($x << $r) | ($x >> (32 - $r)) )
)

// macro_rules! rotl32u(
//     ($x:expr, $r:expr) => ( (x << r) | (x >> (32u32 - r)) )
// )

macro_rules! swap32(
    ($x:expr) => (::std::unstable::intrinsics::bswap32($x as i32))
)

macro_rules! do_while(
    ($body:expr, $cond:expr) => (
        loop {
            $body;

            if !$cond { break; }
        }
    )
)

static SIZE_OF_STATE: uint = 48;

#[cfg(target_endian = "big")]
static ENDIANNESS: Endianness =  BigEndian;

#[cfg(target_endian = "little")]
static ENDIANNESS: Endianness =  LittleEndian;

// pub fn size_of_state() -> uint {
//     std::sys::size_of::<State>()
// }

#[deriving(Eq, Clone, ToStr)]
enum ErrCode {
    Okay = 0,
    Error
}

#[deriving(Eq, Clone, ToStr)]
enum Alignment {
    Aligned,
    Unaligned
}

#[deriving(Eq, Clone, ToStr)]
enum Endianness {
    LittleEndian,
    BigEndian
}

static PRIME32_1: u32 = 2654435761u32;
static PRIME32_2: u32 = 2246822519u32;
static PRIME32_3: u32 = 3266489917u32;
static PRIME32_4: u32 = 668265263u32;
static PRIME32_5: u32 = 374761393u32;

#[inline(always)]
fn read_le32_align(ptr: *u32, endian: Endianness, align: Alignment) -> u32 {
    unsafe {
        if align == Unaligned {
            if endian == LittleEndian { A32!(ptr) } else { (swap32!(A32!(ptr)) as u32) }
        } else {
            if endian == LittleEndian { *ptr } else { (swap32!(*ptr) as u32) }
        }
    }
}

#[inline(always)]
fn read_le32(ptr: *u32, endian: Endianness) -> u32 {
    read_le32_align(ptr, endian, Unaligned)
}

#[inline(always)]
fn endian_align(input: *u8, len: uint, seed: u32, endian: Endianness, align: Alignment) -> u32 {
    let mut p = input;
    let b_end = unsafe { input.offset(len as int) };
    let mut h32: u32;

    if len >= 16u {
        let limit = unsafe { b_end.offset(-16) };
        let mut v1: u32 = seed + PRIME32_1 + PRIME32_2;
        let mut v2: u32 = seed + PRIME32_2;
        let mut v3: u32 = seed + 0u32;
        let mut v4: u32 = seed - PRIME32_1;

        do_while!({
            v1 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v1 = rotl32!(v1, 13);
            v1 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v2 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v2 = rotl32!(v2, 13);
            v2 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v3 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v3 = rotl32!(v3, 13);
            v3 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v4 += read_le32_align(p as *u32, endian, align) * PRIME32_2;
            v4 = rotl32!(v4, 13);
            v4 *= PRIME32_1;
            p = unsafe { p.offset(4) };

        }, p <= limit)

        h32 = rotl32!(v1, 1) + rotl32!(v2, 7) + rotl32!(v3, 12) + rotl32!(v4, 18);
    } else {
        h32 = seed + PRIME32_5;
    }

    h32 += len as u32;

    while unsafe { p <= b_end.offset(-4) } {
        h32 += read_le32_align(p as *u32, endian, align) * PRIME32_3;
        h32 = rotl32!(h32, 17) * PRIME32_4;
        p = unsafe { p.offset(4) };
    }

    while p <= b_end {
        h32 += unsafe { *p } as u32 * PRIME32_5;
        h32 = rotl32!(h32, 11) * PRIME32_1;
        p = unsafe { p.offset(1) };
    }

    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;

    h32
}

fn xxh32(input: *u8, len: uint, seed: u32) -> u32 {
    if ENDIANNESS == LittleEndian {
        endian_align(input, len, seed, LittleEndian, Unaligned)
    } else {
        endian_align(input, len, seed, BigEndian, Unaligned)
    }
}

// #[deriving(Clone, ToStr)]
struct State32 {
    total_len: u64,
    seed: u32,
    v1: u32,
    v2: u32,
    v3: u32,
    v4: u32,
    memsize: i32,
    memory: [u8, ..16]
}

impl State32 {
    pub fn new(seed: u32) -> State32 {
        State32 {
            total_len: 0u64,
            seed: seed,
            v1: seed + PRIME32_1 + PRIME32_2,
            v2: seed + PRIME32_2,
            v3: seed + 0u32,
            v4: seed - PRIME32_1,
            memsize: 0i32,
            memory: [0u8, ..16]
        }
    }
}

fn size_of_state() -> uint {
    use std::mem;

    assert!(SIZE_OF_STATE >= mem::size_of::<State32>());

    mem::size_of::<State32>()
}

fn reset_state(state: &mut State32, seed: u32) -> ErrCode {
    state.seed = seed;
    state.v1 = seed + PRIME32_1 + PRIME32_2;
    state.v2 = seed + PRIME32_2;
    state.v3 = seed + 0u32;
    state.v4 = seed + PRIME32_1;
    state.total_len = 0u64;
    state.memsize = 0i32;
    Okay
}

#[inline(always)]
fn update_endian(state: &mut State32, input: *u8, len: uint, endian: Endianness) -> ErrCode {
    let mut p = input;
    let b_end = unsafe { input.offset(len as int) };

    assert!(ptr::is_not_null(p));

    state.total_len += len as u64;

    if state.memsize + (len as i32) < 16 {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf.offset(state.memsize as int), input, len);
            }
        };

        state.memsize += len as i32;
        return Okay;
    }

    if (state.memsize > 0) {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf.offset(state.memsize as int), input, 16 - state.memsize as uint);
            }
        };
        unsafe {
            let mut p32: *u32 = p as *u32;
            state.v1 += read_le32(p32, endian) * PRIME32_2;
            state.v1 = rotl32!(state.v1, 13);
            state.v1 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v2 += read_le32(p32, endian) * PRIME32_2;
            state.v2 = rotl32!(state.v2, 13);
            state.v2 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v3 += read_le32(p32, endian) * PRIME32_2;
            state.v3 = rotl32!(state.v3, 13);
            state.v3 *= PRIME32_1;
            p32 = p32.offset(1);

            state.v4 += read_le32(p32, endian) * PRIME32_2;
            state.v4 = rotl32!(state.v4, 13);
            state.v4 *= PRIME32_1;
//             p32 = p32.offset(1);
        }

        p = unsafe { p.offset(16 - state.memsize as int) };
        state.memsize = 0i32;
    }

    if unsafe { p <= b_end.offset(-16) }{
        let limit = unsafe { b_end.offset(-16) };
        let mut v1 = state.v1;
        let mut v2 = state.v2;
        let mut v3 = state.v3;
        let mut v4 = state.v4;

        do_while!({
            v1 += read_le32(p as *u32, endian) * PRIME32_2;
            v1 = rotl32!(v1, 13);
            v1 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v2 += read_le32(p as *u32, endian) * PRIME32_2;
            v2 = rotl32!(v2, 13);
            v2 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v3 += read_le32(p as *u32, endian) * PRIME32_2;
            v3 = rotl32!(v3, 13);
            v3 *= PRIME32_1;
            p = unsafe { p.offset(4) };

            v4 += read_le32(p as *u32, endian) * PRIME32_2;
            v4 = rotl32!(v4, 13);
            v4 *= PRIME32_1;
            p = unsafe { p.offset(4) };

        }, p <= limit)

        state.v1 = v1;
        state.v2 = v2;
        state.v3 = v3;
        state.v4 = v4;
    }

    if p < b_end {
        do state.memory.as_mut_buf |buf, _| {
            unsafe {
                ptr::copy_memory(buf, p, b_end.to_uint() - p.to_uint());
            }
        };

        state.memsize = (b_end.to_uint() - p.to_uint() ) as i32;
    }

    Okay
}

fn update(state: &mut State32, input: *u8, len: uint) -> ErrCode {
    if ENDIANNESS == LittleEndian {
        update_endian(state, input, len, LittleEndian)
    } else {
        update_endian(state, input, len, BigEndian)
    }
}

#[inline(always)]
fn intermediate_digest_endian(state: &mut state, endian: Endianness) -> u32 {
    let mut p = state.memory.as_mut_buf(|buf, _| buf);

    Okay
}<|endoftext|>


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

//! The implementations of the `Standard` distribution for integer types.

use {Rng};
use distributions::{Distribution, Standard};

impl Distribution<isize> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> isize {
        rng.gen::<usize>() as isize
    }
}

impl Distribution<i8> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Distribution<i16> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Distribution<i32> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Distribution<i64> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

#[cfg(feature = "i128_support")]
impl Distribution<i128> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> i128 {
        rng.gen::<u128>() as i128
    }
}

impl Distribution<usize> for Standard {
    #[inline]
    #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u32() as usize
    }

    #[inline]
    #[cfg(target_pointer_width = "64")]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u64() as usize
    }
}

impl Distribution<u8> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Distribution<u16> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Distribution<u32> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Distribution<u64> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Distribution<u128> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
        // Use LE; we explicitly generate one value before the next.
        let x = rng.next_u64() as u128;
        let y = rng.next_u64() as u128;
        (y << 64) | x
    }
}

#[cfg(test)]
mod tests {
    use Rng;
    use distributions::{Standard};

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng(806);

        rng.sample::<isize, _>(Standard);
        rng.sample::<i8, _>(Standard);
        rng.sample::<i16, _>(Standard);
        rng.sample::<i32, _>(Standard);
        rng.sample::<i64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<i128, _>(Standard);

        rng.sample::<usize, _>(Standard);
        rng.sample::<u8, _>(Standard);
        rng.sample::<u16, _>(Standard);
        rng.sample::<u32, _>(Standard);
        rng.sample::<u64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<u128, _>(Standard);
    }
}
<commit_msg>Simplify code implementing the Standard distribution for integers<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of the `Standard` distribution for integer types.

use {Rng};
use distributions::{Distribution, Standard};

impl Distribution<u8> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Distribution<u16> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Distribution<u32> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Distribution<u64> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

#[cfg(feature = "i128_support")]
impl Distribution<u128> for Standard {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u128 {
        // Use LE; we explicitly generate one value before the next.
        let x = rng.next_u64() as u128;
        let y = rng.next_u64() as u128;
        (y << 64) | x
    }
}

impl Distribution<usize> for Standard {
    #[inline]
    #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u32() as usize
    }

    #[inline]
    #[cfg(target_pointer_width = "64")]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        rng.next_u64() as usize
    }
}

macro_rules! impl_int_from_uint {
    ($ty:ty, $uty:ty) => {
        impl Distribution<$ty> for Standard {
            #[inline]
            fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
                rng.gen::<$uty>() as $ty
            }
        }
    }
}

impl_int_from_uint! { i8, u8 }
impl_int_from_uint! { i16, u16 }
impl_int_from_uint! { i32, u32 }
impl_int_from_uint! { i64, u64 }
#[cfg(feature = "i128_support")] impl_int_from_uint! { i128, u128 }
impl_int_from_uint! { isize, usize }

#[cfg(test)]
mod tests {
    use Rng;
    use distributions::{Standard};

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng(806);

        rng.sample::<isize, _>(Standard);
        rng.sample::<i8, _>(Standard);
        rng.sample::<i16, _>(Standard);
        rng.sample::<i32, _>(Standard);
        rng.sample::<i64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<i128, _>(Standard);

        rng.sample::<usize, _>(Standard);
        rng.sample::<u8, _>(Standard);
        rng.sample::<u16, _>(Standard);
        rng.sample::<u32, _>(Standard);
        rng.sample::<u64, _>(Standard);
        #[cfg(feature = "i128_support")]
        rng.sample::<u128, _>(Standard);
    }
}
<|endoftext|>


<commit_before><commit_msg>fix: don't use relative path<commit_after><|endoftext|>


<commit_before><commit_msg>updates<commit_after><|endoftext|>


<commit_before><commit_msg>Improve Enigma doc examples<commit_after><|endoftext|>


<commit_before><commit_msg>Remove unused use import<commit_after><|endoftext|>


<commit_before>use crate::ich::StableHashingContext;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use std::cmp;
use std::mem;

/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// kind of crate, including cdylibs which export very few things.
/// `Rust` will only be exported if the crate produced is a Rust
/// dylib.
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum SymbolExportLevel {
    C,
    Rust,
}

impl SymbolExportLevel {
    pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
        threshold == SymbolExportLevel::Rust // export everything from Rust dylibs
          || self == SymbolExportLevel::C
    }
}

#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum ExportedSymbol<'tcx> {
    NonGeneric(DefId),
    Generic(DefId, SubstsRef<'tcx>),
    NoDefId(ty::SymbolName),
}

impl<'tcx> ExportedSymbol<'tcx> {
    /// This is the symbol name of an instance if it is instantiated in the
    /// local crate.
    pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
        match *self {
            ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
            ExportedSymbol::Generic(def_id, substs) => {
                tcx.symbol_name(ty::Instance::new(def_id, substs))
            }
            ExportedSymbol::NoDefId(symbol_name) => symbol_name,
        }
    }

    pub fn compare_stable(&self, tcx: TyCtxt<'tcx>, other: &ExportedSymbol<'tcx>) -> cmp::Ordering {
        match *self {
            ExportedSymbol::NonGeneric(self_def_id) => match *other {
                ExportedSymbol::NonGeneric(other_def_id) => {
                    tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
                }
                ExportedSymbol::Generic(..) | ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
            },
            ExportedSymbol::Generic(self_def_id, self_substs) => match *other {
                ExportedSymbol::NonGeneric(_) => cmp::Ordering::Greater,
                ExportedSymbol::Generic(other_def_id, other_substs) => {
                    // We compare the symbol names because they are cached as query
                    // results which makes them relatively cheap to access repeatedly.
                    //
                    // It might be even faster to build a local cache of stable IDs
                    // for sorting. Exported symbols are really only sorted once
                    // in order to make the `exported_symbols` query result stable.
                    let self_symbol_name =
                        tcx.symbol_name(ty::Instance::new(self_def_id, self_substs));
                    let other_symbol_name =
                        tcx.symbol_name(ty::Instance::new(other_def_id, other_substs));

                    self_symbol_name.cmp(&other_symbol_name)
                }
                ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
            },
            ExportedSymbol::NoDefId(self_symbol_name) => match *other {
                ExportedSymbol::NonGeneric(_) | ExportedSymbol::Generic(..) => {
                    cmp::Ordering::Greater
                }
                ExportedSymbol::NoDefId(ref other_symbol_name) => {
                    self_symbol_name.cmp(other_symbol_name)
                }
            },
        }
    }
}

pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
    format!(
        "rust_metadata_{}_{}",
        tcx.original_crate_name(LOCAL_CRATE),
        tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
    )
}

impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ExportedSymbol<'tcx> {
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
        mem::discriminant(self).hash_stable(hcx, hasher);
        match *self {
            ExportedSymbol::NonGeneric(def_id) => {
                def_id.hash_stable(hcx, hasher);
            }
            ExportedSymbol::Generic(def_id, substs) => {
                def_id.hash_stable(hcx, hasher);
                substs.hash_stable(hcx, hasher);
            }
            ExportedSymbol::NoDefId(symbol_name) => {
                symbol_name.hash_stable(hcx, hasher);
            }
        }
    }
}
<commit_msg>Always just use symbol name for sorting exported symbols.<commit_after>use crate::ich::StableHashingContext;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use std::mem;

/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// kind of crate, including cdylibs which export very few things.
/// `Rust` will only be exported if the crate produced is a Rust
/// dylib.
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum SymbolExportLevel {
    C,
    Rust,
}

impl SymbolExportLevel {
    pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
        threshold == SymbolExportLevel::Rust // export everything from Rust dylibs
          || self == SymbolExportLevel::C
    }
}

#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum ExportedSymbol<'tcx> {
    NonGeneric(DefId),
    Generic(DefId, SubstsRef<'tcx>),
    NoDefId(ty::SymbolName),
}

impl<'tcx> ExportedSymbol<'tcx> {
    /// This is the symbol name of an instance if it is instantiated in the
    /// local crate.
    pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
        match *self {
            ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
            ExportedSymbol::Generic(def_id, substs) => {
                tcx.symbol_name(ty::Instance::new(def_id, substs))
            }
            ExportedSymbol::NoDefId(symbol_name) => symbol_name,
        }
    }
}

pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
    format!(
        "rust_metadata_{}_{}",
        tcx.original_crate_name(LOCAL_CRATE),
        tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
    )
}

impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ExportedSymbol<'tcx> {
    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
        mem::discriminant(self).hash_stable(hcx, hasher);
        match *self {
            ExportedSymbol::NonGeneric(def_id) => {
                def_id.hash_stable(hcx, hasher);
            }
            ExportedSymbol::Generic(def_id, substs) => {
                def_id.hash_stable(hcx, hasher);
                substs.hash_stable(hcx, hasher);
            }
            ExportedSymbol::NoDefId(symbol_name) => {
                symbol_name.hash_stable(hcx, hasher);
            }
        }
    }
}
<|endoftext|>


<commit_before>// 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.

use std::collections::HashMap;
use std::fmt;

use super::english_cardinal_classifier;
use {Args, Format, Message, Value};

/// The set of [grammatical numbers] that we support.
///
/// [grammatical numbers]: https://en.wikipedia.org/wiki/Grammatical_number
#[derive(Clone,Copy,Debug,PartialEq)]
pub enum PluralCategory {
    /// Value is `0`.
    Zero,
    /// Value is `1`. In English, this corresponds to the "singular" form.
    One,
    /// Value is `2`.
    Two,
    /// Value is a few, more than `2`, but less than `many`. The exact
    /// range depends upon the locale.
    Few,
    /// Value is many, more than `few`. The exact range depends
    /// upon the locale.
    Many,
    /// Not one of the others. In English, this is used for the "plural"
    /// form.
    Other,
}

/// Format a value taking pluralization rules into account.
pub struct PluralFormat {
    /// The name of the variable whose value should be formatted.
    variable_name: String,
    classifier: fn(i64) -> PluralCategory,
    literals: HashMap<i64, Message>,
    offset: i64,
    zero: Option<Message>,
    one: Option<Message>,
    two: Option<Message>,
    few: Option<Message>,
    many: Option<Message>,
    other: Message,
}

impl PluralFormat {
    /// Construct a `PluralFormat`.
    pub fn new(variable_name: &str, other: Message) -> Self {
        PluralFormat {
            variable_name: variable_name.to_string(),
            classifier: english_cardinal_classifier,
            literals: HashMap::new(),
            offset: 0,
            zero: None,
            one: None,
            two: None,
            few: None,
            many: None,
            other: other,
        }
    }

    /// Set the `message` to be used for a literal value.
    pub fn literal(&mut self, literal: i64, message: Message) -> &mut Self {
        self.literals.insert(literal, message);
        self
    }

    /// Apply an `offset`.
    pub fn offset(&mut self, offset: i64) -> &mut Self {
        self.offset = offset;
        self
    }

    /// Set the `message` for `PluralCategory::Zero`.
    pub fn zero(&mut self, message: Message) -> &mut Self {
        self.zero = Some(message);
        self
    }

    /// Set the `message` for `PluralCategory::One`.
    pub fn one(&mut self, message: Message) -> &mut Self {
        self.one = Some(message);
        self
    }

    /// Set the `message` for `PluralCategory::Two`.
    pub fn two(&mut self, message: Message) -> &mut Self {
        self.two = Some(message);
        self
    }

    /// Set the `message` for `PluralCategory::Few`.
    pub fn few(&mut self, message: Message) -> &mut Self {
        self.few = Some(message);
        self
    }

    /// Set the `message` for `PluralCategory::Many`.
    pub fn many(&mut self, message: Message) -> &mut Self {
        self.many = Some(message);
        self
    }

    /// Given a value adjusted by the `offset`, determine which `Message` to use.
    fn lookup_message(&self, offset_value: i64) -> &Message {
        if let Some(literal) = self.literals.get(&offset_value) {
            literal
        } else {
            let category = (self.classifier)(offset_value);
            match category {
                PluralCategory::Zero => self.zero.as_ref().unwrap_or(&self.other),
                PluralCategory::One => self.one.as_ref().unwrap_or(&self.other),
                PluralCategory::Two => self.two.as_ref().unwrap_or(&self.other),
                PluralCategory::Few => self.few.as_ref().unwrap_or(&self.other),
                PluralCategory::Many => self.many.as_ref().unwrap_or(&self.other),
                PluralCategory::Other => &self.other,
            }
        }
    }

    /// Handle specialized behavior for `PlaceholderFormat` when formatting
    /// a `PluralFormat`.
    ///
    /// XXX: Can we fold this away and do something more general for
    /// `PlaceholderFormat`?
    fn format_plural_message<'f>(&'f self,
                                 stream: &mut fmt::Write,
                                 message: &'f Message,
                                 _offset_value: i64,
                                 args: &'f Args<'f>)
                                 -> fmt::Result {
        for part in &message.parts {
            // XXX: Need to deal with PlaceholderFormat here and give it
            // the `offset_value`.
            try!(part.apply_format(stream, args));
        }
        Ok(())
    }
}

impl Format for PluralFormat {
    fn apply_format<'f>(&'f self, stream: &mut fmt::Write, args: &'f Args<'f>) -> fmt::Result {
        if let Some(arg) = args.get(&self.variable_name) {
            let value = match *arg.value() {
                Value::Number(n) => n,
                _ => panic!("Wrong variable type."),
            };
            let offset_value = value - self.offset;
            let message = self.lookup_message(offset_value);
            try!(self.format_plural_message(stream, message, offset_value, args));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use icu::parse;
    use super::PluralFormat;
    use {arg, Format};

    #[test]
    fn it_works() {
        let mut fmt = PluralFormat::new("count", parse("Other").unwrap());
        fmt.one(parse("One").unwrap());

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 0)).unwrap();
        assert_eq!("Other", output);

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 1)).unwrap();
        assert_eq!("One", output);

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 3)).unwrap();
        assert_eq!("Other", output);
    }
}
<commit_msg>PluralFormat: No chainable API for construction.<commit_after>// 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.

use std::collections::HashMap;
use std::fmt;

use super::english_cardinal_classifier;
use {Args, Format, Message, Value};

/// The set of [grammatical numbers] that we support.
///
/// [grammatical numbers]: https://en.wikipedia.org/wiki/Grammatical_number
#[derive(Clone,Copy,Debug,PartialEq)]
pub enum PluralCategory {
    /// Value is `0`.
    Zero,
    /// Value is `1`. In English, this corresponds to the "singular" form.
    One,
    /// Value is `2`.
    Two,
    /// Value is a few, more than `2`, but less than `many`. The exact
    /// range depends upon the locale.
    Few,
    /// Value is many, more than `few`. The exact range depends
    /// upon the locale.
    Many,
    /// Not one of the others. In English, this is used for the "plural"
    /// form.
    Other,
}

/// Format a value taking pluralization rules into account.
pub struct PluralFormat {
    /// The name of the variable whose value should be formatted.
    variable_name: String,
    classifier: fn(i64) -> PluralCategory,
    literals: HashMap<i64, Message>,
    offset: i64,
    zero: Option<Message>,
    one: Option<Message>,
    two: Option<Message>,
    few: Option<Message>,
    many: Option<Message>,
    other: Message,
}

impl PluralFormat {
    /// Construct a `PluralFormat`.
    pub fn new(variable_name: &str, other: Message) -> Self {
        PluralFormat {
            variable_name: variable_name.to_string(),
            classifier: english_cardinal_classifier,
            literals: HashMap::new(),
            offset: 0,
            zero: None,
            one: None,
            two: None,
            few: None,
            many: None,
            other: other,
        }
    }

    /// Set the `message` to be used for a literal value.
    pub fn literal(&mut self, literal: i64, message: Message) {
        self.literals.insert(literal, message);
    }

    /// Apply an `offset`.
    pub fn offset(&mut self, offset: i64) {
        self.offset = offset;
    }

    /// Set the `message` for `PluralCategory::Zero`.
    pub fn zero(&mut self, message: Message) {
        self.zero = Some(message);
    }

    /// Set the `message` for `PluralCategory::One`.
    pub fn one(&mut self, message: Message) {
        self.one = Some(message);
    }

    /// Set the `message` for `PluralCategory::Two`.
    pub fn two(&mut self, message: Message) {
        self.two = Some(message);
    }

    /// Set the `message` for `PluralCategory::Few`.
    pub fn few(&mut self, message: Message) {
        self.few = Some(message);
    }

    /// Set the `message` for `PluralCategory::Many`.
    pub fn many(&mut self, message: Message) {
        self.many = Some(message);
    }

    /// Given a value adjusted by the `offset`, determine which `Message` to use.
    fn lookup_message(&self, offset_value: i64) -> &Message {
        if let Some(literal) = self.literals.get(&offset_value) {
            literal
        } else {
            let category = (self.classifier)(offset_value);
            match category {
                PluralCategory::Zero => self.zero.as_ref().unwrap_or(&self.other),
                PluralCategory::One => self.one.as_ref().unwrap_or(&self.other),
                PluralCategory::Two => self.two.as_ref().unwrap_or(&self.other),
                PluralCategory::Few => self.few.as_ref().unwrap_or(&self.other),
                PluralCategory::Many => self.many.as_ref().unwrap_or(&self.other),
                PluralCategory::Other => &self.other,
            }
        }
    }

    /// Handle specialized behavior for `PlaceholderFormat` when formatting
    /// a `PluralFormat`.
    ///
    /// XXX: Can we fold this away and do something more general for
    /// `PlaceholderFormat`?
    fn format_plural_message<'f>(&'f self,
                                 stream: &mut fmt::Write,
                                 message: &'f Message,
                                 _offset_value: i64,
                                 args: &'f Args<'f>)
                                 -> fmt::Result {
        for part in &message.parts {
            // XXX: Need to deal with PlaceholderFormat here and give it
            // the `offset_value`.
            try!(part.apply_format(stream, args));
        }
        Ok(())
    }
}

impl Format for PluralFormat {
    fn apply_format<'f>(&'f self, stream: &mut fmt::Write, args: &'f Args<'f>) -> fmt::Result {
        if let Some(arg) = args.get(&self.variable_name) {
            let value = match *arg.value() {
                Value::Number(n) => n,
                _ => panic!("Wrong variable type."),
            };
            let offset_value = value - self.offset;
            let message = self.lookup_message(offset_value);
            try!(self.format_plural_message(stream, message, offset_value, args));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use icu::parse;
    use super::PluralFormat;
    use {arg, Format};

    #[test]
    fn it_works() {
        let mut fmt = PluralFormat::new("count", parse("Other").unwrap());
        fmt.one(parse("One").unwrap());

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 0)).unwrap();
        assert_eq!("Other", output);

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 1)).unwrap();
        assert_eq!("One", output);

        let mut output = String::new();
        fmt.apply_format(&mut output, &arg("count", 3)).unwrap();
        assert_eq!("Other", output);
    }
}
<|endoftext|>