<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 http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::js::{OptionalRootedRootable, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(tokens.as_slice()).map(|slice| Atom::from_slice(slice)) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = {
            let slices: Vec<&str> = atoms.iter().map(|atom| atom.as_slice()).collect();
            slices.connect("\x20")
        };
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        // XXX Is parse() correct?
        let result: u32 = string.parse().unwrap_or(default);
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
            AttrValue::TokenList(ref value, _) |
            AttrValue::UInt(ref value, _) => value.as_slice(),
            AttrValue::Atom(ref value) => value.as_slice(),
        }
    }
}

#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: Option<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: owner.map(|o| JS::from_rooted(o)),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Temporary<Attr> {
        reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
                           GlobalRef::Window(window), AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<DOMString> {
        &self.prefix
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().to_owned()
    }

    fn Value(self) -> DOMString {
        self.value().as_slice().to_owned()
    }

    fn SetValue(self, value: DOMString) {
        match self.owner {
            None => {
                *self.value.borrow_mut() = AttrValue::String(value)
            }
            Some(o) => {
                let owner = o.root();
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    fn TextContent(self) -> DOMString {
        self.Value()
    }

    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    fn Name(self) -> DOMString {
        self.name.as_slice().to_owned()
    }

    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }

    fn GetOwnerElement(self) -> Option<Temporary<Element>> {
        self.owner.map(|o| Temporary::new(o))
    }

    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) {
        assert!(Some(owner) == self.owner.root().r());

        let node: JSRef<Node> = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for Attr {
    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        value.as_slice()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = self.value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        match *value {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<commit_msg>auto merge of #5435 : frewsxcv/servo/dom-attr-cleanup, r=jdm<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 http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::js::{OptionalRootedRootable, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(&tokens).map(Atom::from_slice) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = atoms.iter().map(Atom::as_slice).collect::<Vec<_>>().connect("\x20");
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        // XXX Is parse() correct?
        let result: u32 = string.parse().unwrap_or(default);
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(&string);
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
                AttrValue::TokenList(ref value, _) |
                AttrValue::UInt(ref value, _) => &value,
            AttrValue::Atom(ref value) => value.as_slice(),
        }
    }
}

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: Option<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: owner.map(JS::from_rooted),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: Option<JSRef<Element>>) -> Temporary<Attr> {
        reflect_dom_object(
            box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
            GlobalRef::Window(window),
            AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<DOMString> {
        &self.prefix
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(self) -> DOMString {
        self.value().as_slice().to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(self, value: DOMString) {
        match self.owner {
            None => *self.value.borrow_mut() = AttrValue::String(value),
            Some(o) => {
                let owner = o.root();
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn TextContent(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(self) -> DOMString {
        self.name.as_slice().to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(self) -> Option<Temporary<Element>> {
        self.owner.map(|o| Temporary::new(o))
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) {
        assert!(Some(owner) == self.owner.root().r());

        let node: JSRef<Node> = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for Attr {
    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        value.as_slice()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = self.value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        let value = mem::transmute::<&AttrValue, &AttrValue>(self.value.borrow_for_layout());
        match *value {
            AttrValue::TokenList(_, ref tokens) => Some(tokens.as_slice()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]

fn main() {
    // (all the type annotations are superfluous)
    // A reference to a string allocated in read only memory
    let pangram: &'static str = "the quick brown fox jumps over the lazy dog";
    println!("Pangram: {}", pangram);

    // Iterate over words in reverse, no new string is allocated
    println!("Words in reverse");
    for word in pangram.words().rev() {
        println!("> {}", word);
    }

    // Copy chars into a vector, sort and remove duplicates
    let mut chars: Vec<char> = pangram.chars().collect();
    chars.sort();
    chars.dedup();

    // Create an empty and growable `String`
    let mut string = String::new();
    for c in chars {
        // Insert a char at the end of string
        string.push(c);
        // Insert a string at the end of string
        string.push_str(", ");
    }

    // The trimmed string is a slice to the original string, hence no new
    // allocation is performed
    let chars_to_trim: &[char] = &[' ', ','];
    let trimmed_str: &str = string.as_slice().trim_matches(chars_to_trim);
    println!("Used characters: {}", trimmed_str);

    // Heap allocate a string
    let alice = String::from_str("I like dogs");
    // Allocate new memory and store the modified string there
    let bob: String = alice.replace("dog", "cat");

    println!("Alice says: {}", alice);
    println!("Bob says: {}", bob);
}
<commit_msg>Add in new feature gate<commit_after>#![feature(collections)]
#![feature(core)]
#![feature(str_words)]

fn main() {
    // (all the type annotations are superfluous)
    // A reference to a string allocated in read only memory
    let pangram: &'static str = "the quick brown fox jumps over the lazy dog";
    println!("Pangram: {}", pangram);

    // Iterate over words in reverse, no new string is allocated
    println!("Words in reverse");
    for word in pangram.words().rev() {
        println!("> {}", word);
    }

    // Copy chars into a vector, sort and remove duplicates
    let mut chars: Vec<char> = pangram.chars().collect();
    chars.sort();
    chars.dedup();

    // Create an empty and growable `String`
    let mut string = String::new();
    for c in chars {
        // Insert a char at the end of string
        string.push(c);
        // Insert a string at the end of string
        string.push_str(", ");
    }

    // The trimmed string is a slice to the original string, hence no new
    // allocation is performed
    let chars_to_trim: &[char] = &[' ', ','];
    let trimmed_str: &str = string.as_slice().trim_matches(chars_to_trim);
    println!("Used characters: {}", trimmed_str);

    // Heap allocate a string
    let alice = String::from_str("I like dogs");
    // Allocate new memory and store the modified string there
    let bob: String = alice.replace("dog", "cat");

    println!("Alice says: {}", alice);
    println!("Bob says: {}", bob);
}
<|endoftext|>


<commit_before>#![feature(async_await)]
#![deny(warnings)]
extern crate hyper;
extern crate pretty_env_logger;
extern crate serde_json;

use hyper::{Body, Chunk, Client, Method, Request, Response, Server, StatusCode, header};
use hyper::client::HttpConnector;
use hyper::service::{service_fn, make_service_fn};
use futures_util::{TryStreamExt};

type GenericError = Box<dyn std::error::Error + Send + Sync>;

static NOTFOUND: &[u8] = b"Not Found";
static URL: &str = "http://127.0.0.1:1337/json_api";
static INDEX: &[u8] = b"test.html";
static POST_DATA: &str = r#"{"original": "data"}"#;

async fn client_request_response(client: &Client<HttpConnector>)
    -> Result<Response, GenericError>
{
     let req = Request::builder()
         .method(Method::POST)
         .uri(URL)
         .header(header::CONTENT_TYPE, "application/json")
         .body(POST_DATA.into())
         .unwrap();

     let web_res = client.request(req).await?;
    // Compare the JSON we sent (before) with what we received (after):
    let body = Body::wrap_stream(web_res.into_body().map_ok(|b| {
        Chunk::from(format!("POST request body: {}
Response: {}",
                            POST_DATA,
                            std::str::from_utf8(&b).unwrap()))
    }));

    Ok(Response::new(body))
}

async fn api_post_response(req: Request)
    -> Result<Response, GenericError>
{
    // A web api to run against
    let entire_body = req.into_body().try_concat().await?;
    // TODO: Replace all unwraps with proper error handling
    let str = String::from_utf8(entire_body.to_vec())?;
    let mut data : serde_json::Value = serde_json::from_str(&str)?;
    data["test"] = serde_json::Value::from("test_value");
    let json = serde_json::to_string(&data)?;
    let response = Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "application/json")
        .body(Body::from(json))?;
    Ok(response)
}

async fn api_get_response() -> Result<Response, GenericError> {
    let data = vec!["foo", "bar"];
    let res = match serde_json::to_string(&data) {
        Ok(json) => {
            Response::builder()
                .header(header::CONTENT_TYPE, "application/json")
                .body(Body::from(json))
                .unwrap()
        }
        Err(_) => {
            Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::from("Internal Server Error"))
                .unwrap()
        }
    };
    Ok(res)
}

async fn response_examples(req: Request, client: Client<HttpConnector>)
    -> Result<Response, GenericError>
{
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") | (&Method::GET, "/index.html") => {
            let body = Body::from(INDEX);
            Ok(Response::new(body))
        },
        (&Method::GET, "/test.html") => {
            client_request_response(&client).await
        },
        (&Method::POST, "/json_api") => {
            api_post_response(req).await
        },
        (&Method::GET, "/json_api") => {
            api_get_response().await
        }
        _ => {
            // Return 404 not found response.
            let body = Body::from(NOTFOUND);
            Ok(Response::builder()
                        .status(StatusCode::NOT_FOUND)
                        .body(body)
                        .unwrap())
        }
    }
}

#[hyper::rt::main]
async fn main() -> Result<(), GenericError> {
    pretty_env_logger::init();

    let addr = "127.0.0.1:1337".parse().unwrap();

    // Share a `Client` with all `Service`s
    let client = Client::new();

    let new_service = make_service_fn(move |_| {
        // Move a clone of `client` into the `service_fn`.
        let client = client.clone();
        async {
            Ok::<_, GenericError>(service_fn(move |req| {
                // Clone again to ensure that client outlives this closure.
                response_examples(req, client.to_owned())
            }))
        }
    });

    let server = Server::bind(&addr)
        .serve(new_service);

    println!("Listening on http://{}", addr);

    server.await?;

    Ok(())
}
<commit_msg>docs(examples): formatting and refactoring<commit_after>#![feature(async_await)]
#![deny(warnings)]

use hyper::{Body, Chunk, Client, Method, Request, Response, Server, StatusCode, header};
use hyper::client::HttpConnector;
use hyper::service::{make_service_fn, service_fn};
use futures_util::{TryStreamExt};

type GenericError = Box<dyn std::error::Error + Send + Sync>;
type Result<T> = std::result::Result<T, GenericError>;

static INDEX: &[u8] = b"test.html";
static INTERNAL_SERVER_ERROR: &[u8] = b"Internal Server Error";
static NOTFOUND: &[u8] = b"Not Found";
static POST_DATA: &str = r#"{"original": "data"}"#;
static URL: &str = "http://127.0.0.1:1337/json_api";

async fn client_request_response(
    client: &Client<HttpConnector>
) -> Result<Response> {
    let req = Request::builder()
        .method(Method::POST)
        .uri(URL)
        .header(header::CONTENT_TYPE, "application/json")
        .body(POST_DATA.into())
        .unwrap();

    let web_res = client.request(req).await?;
    // Compare the JSON we sent (before) with what we received (after):
    let body = Body::wrap_stream(web_res.into_body().map_ok(|b| {
        Chunk::from(format!("POST request body: {}
Response: {}",
                            POST_DATA,
                            std::str::from_utf8(&b).unwrap()))
    }));

    Ok(Response::new(body))
}

async fn api_post_response(req: Request) -> Result<Response> {
    // A web api to run against
    let entire_body = req.into_body().try_concat().await?;
    // TODO: Replace all unwraps with proper error handling
    let str = String::from_utf8(entire_body.to_vec())?;
    let mut data : serde_json::Value = serde_json::from_str(&str)?;
    data["test"] = serde_json::Value::from("test_value");
    let json = serde_json::to_string(&data)?;
    let response = Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "application/json")
        .body(Body::from(json))?;
    Ok(response)
}

async fn api_get_response() -> Result<Response> {
    let data = vec!["foo", "bar"];
    let res = match serde_json::to_string(&data) {
        Ok(json) => {
            Response::builder()
                .header(header::CONTENT_TYPE, "application/json")
                .body(Body::from(json))
                .unwrap()
        }
        Err(_) => {
            Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(INTERNAL_SERVER_ERROR.into())
                .unwrap()
        }
    };
    Ok(res)
}

async fn response_examples(
    req: Request,
    client: Client<HttpConnector>
) -> Result<Response> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") |
        (&Method::GET, "/index.html") => {
            Ok(Response::new(INDEX.into()))
        },
        (&Method::GET, "/test.html") => {
            client_request_response(&client).await
        },
        (&Method::POST, "/json_api") => {
            api_post_response(req).await
        },
        (&Method::GET, "/json_api") => {
            api_get_response().await
        }
        _ => {
            // Return 404 not found response.
            Ok(Response::builder()
                .status(StatusCode::NOT_FOUND)
                .body(NOTFOUND.into())
                .unwrap())
        }
    }
}

#[hyper::rt::main]
async fn main() -> Result<()> {
    pretty_env_logger::init();

    let addr = "127.0.0.1:1337".parse().unwrap();

    // Share a `Client` with all `Service`s
    let client = Client::new();

    let new_service = make_service_fn(move |_| {
        // Move a clone of `client` into the `service_fn`.
        let client = client.clone();
        async {
            Ok::<_, GenericError>(service_fn(move |req| {
                // Clone again to ensure that client outlives this closure.
                response_examples(req, client.to_owned())
            }))
        }
    });

    let server = Server::bind(&addr)
        .serve(new_service);

    println!("Listening on http://{}", addr);

    server.await?;

    Ok(())
}
<|endoftext|>


<commit_before>extern crate orbtk;
use orbtk::*;

use std::sync::Arc;

// use orbtk::{Application, Button, Center, Container, Content, Rect, Row, Thickness, Label, Widget};
// use orbtk::theme::{Style, Selector};

// struct MainView {}

// impl MainView {
//     fn new() -> Arc<MainView> {
//         Arc::new(MainView {})
//     }
// }

// impl Widget for MainView {
//     fn build(&self) -> Content {
//         /* todo: content! marco
//             content!(
//                 Center (
//                     Row (
//                         Container (
//                             padding: 8,
//                             Button (
//                                 text: "Button" 1
//                             )
//                         )
//                         Container (
//                             padding: 8,
//                             Button (
//                                 text: "Button 2"
//                             )
//                         )
//                     )
//                 )
//             )
//         */
//         let container = Container::new();
//         container.selector().set(Selector::new(Some("button")));
//         let root = Container::new();
//         root.padding().set(Thickness::new(32, 32, 32, 32));
//         root.child(&container);
//         Content::Single(root)
//         // let center = Center::new();
//         // // let row = Row::new();
//         // // let left_container = Container::new();
//         // // left_container.padding().set(Thickness::new(8, 8, 8, 8));
//         // // left_container.child(&Button::new());
//         // // row.push(&left_container);
//         // // let right_container = Container::new();
//         // // right_container.padding().set(Thickness::new(8, 8, 8, 8));
//         // // right_container.child(&Button::new());
//         // // row.push(&right_container);
//         // let label = Label::new("Test");
//         // center.child(&label);
//         // Content::Single(center)
//     }
//     fn element(&self) -> &str {
//         "mainView"
//     }
// }

struct MainView;

impl Widget for MainView {
    fn template(&self) -> Template {
        Template::Single(Arc::new(Button))
    }

    fn components(&self) -> Vec<ComponentBox> {
        vec![]
    }
}

fn main() {
    println!("Widget example");
    // let mut wm = WidgetManager::new();
    // wm.root(Arc::new(MainView));
    // wm.run();

    let mut application = Application::new();
    application
        .create_window()
        .with_bounds(Rect::new(0, 0, 420, 730))
        .with_title("Orbtk")
        .with_root(MainView)
        .build();
    application.run();

    // let application = Application::new(Rect::new(0, 0, 420, 730), "Orbtk");
    // application.root(&MainView::new()).run();
}
<commit_msg>Cleanup widget example.<commit_after>extern crate orbtk;
use orbtk::*;

use std::sync::Arc;

struct MainView;

impl Widget for MainView {
    fn template(&self) -> Template {
        Template::Single(Arc::new(Button))
    }

    fn components(&self) -> Vec<ComponentBox> {
        vec![]
    }
}

fn main() {
    println!("Widget example");

    let mut application = Application::new();
    application
        .create_window()
        .with_bounds(Rect::new(0, 0, 420, 730))
        .with_title("Orbtk")
        .with_root(MainView)
        .build();
    application.run();
}
<|endoftext|>


<commit_before>// FIXME: Validation disabled until https://github.com/rust-lang/rust/pull/56161 lands
// compile-flags: -Zmiri-disable-validation

use std::collections::VecDeque;

fn main() {
    let mut dst = VecDeque::new();
    dst.push_front(Box::new(1));
    dst.push_front(Box::new(2));
    dst.pop_back();

    let mut src = VecDeque::new();
    src.push_front(Box::new(2));
    dst.append(&mut src);
    for a in dst {
      assert_eq!(*a, 2);
    }
}
<commit_msg>VecDeque got fixed<commit_after>use std::collections::VecDeque;

fn main() {
    let mut dst = VecDeque::new();
    dst.push_front(Box::new(1));
    dst.push_front(Box::new(2));
    dst.pop_back();

    let mut src = VecDeque::new();
    src.push_front(Box::new(2));
    dst.append(&mut src);
    for a in dst {
      assert_eq!(*a, 2);
    }
}
<|endoftext|>


<commit_before>extern crate bit_vec;

use self::bit_vec::BitVec;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt;

use super::dfa::{DFA, DFAState, DFA_STUCK, DFA_START};

pub type StateNumberSet = HashSet<usize>;

pub const NFA_START: usize = 0;

#[derive(Clone)]
pub struct NFAState {
    transitions: Vec<StateNumberSet>,
}

pub struct NFA {
    states: Vec<NFAState>,
    finals: BitVec,
}

impl NFA {
    pub fn from_dictionary(dict: &[&str]) -> Self {
        let num_states = dict.iter().fold(1, |sum, elem| sum + elem.len());
        let mut nfa = NFA {
            states: vec![NFAState { transitions: vec![HashSet::new(); 256] }; num_states],
            finals: BitVec::from_elem(num_states, false),
        };
        let mut nxt_state = NFA_START;
        for &string in dict.iter() {
            let mut cur_state = NFA_START;
            for byte in string.bytes() {
                if let Some(&state) = nfa.states[cur_state].transitions[byte as usize].get(&0) {
                    cur_state = state;
                } else {
                    nxt_state += 1;
                    nfa.states[cur_state].transitions[byte as usize].insert(nxt_state);
                    cur_state = nxt_state;
                }
            }
            nfa.finals.set(cur_state, true);
        }
        nfa
    }

    pub fn ignore_prefixes(&mut self) {
        for transition in &mut self.states[NFA_START].transitions {
            transition.insert(NFA_START);
        }
    }

    pub fn ignore_postfixes(&mut self) {
        for (fin,_) in self.finals.iter().enumerate().filter(|&(_,b)| b) {
            for mut transition in &mut self.states[fin].transitions {
                transition.insert(fin);
            }
        }
    }

    pub fn freeze(&self) -> Result<DFA, ()> {
        let mut states = Vec::with_capacity(self.states.len());
        for state in &self.states {
            states.push(try!(state.freeze()));
        }
        Ok(DFA::new(states.into_boxed_slice(), self.finals.clone()))
    }

    pub fn apply(&self, input: &[u8]) -> bool {
        let mut cur_states = HashSet::new();
        let mut nxt_states = HashSet::new();
        cur_states.insert(NFA_START);
        for &byte in input {
            for cur_state in cur_states {
                for &nxt_state in &self.states[cur_state].transitions[byte as usize] {
                    nxt_states.insert(nxt_state);
                }
            }
            cur_states = nxt_states;
            nxt_states = HashSet::new();
        }
        for state in cur_states {
            if self.finals[state] {
                return true;
            }
        }
        false
    }

    pub fn powerset_construction(&self) -> Self {
        let mut dnfa = NFA {
            states: vec![NFAState { transitions: vec![HashSet::new(); 256] }; 2],
            finals: BitVec::from_elem(2, false),
        };
        let mut states_map: HashMap<Vec<usize>, usize> = HashMap::new();
        let cur_states: HashSet<usize> = [NFA_START].into_iter().map(|x| *x).collect();

        dnfa.finals.set(DFA_START, self.finals.get(NFA_START).unwrap());

        states_map.insert(Vec::new(), DFA_STUCK);
        states_map.insert(cur_states.clone().into_iter().collect(), DFA_START);

        psc_rec_helper(self, &mut dnfa, &mut states_map, cur_states, DFA_START);
        dnfa
    }
}

impl fmt::Display for NFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, state) in (*self.states).into_iter().enumerate() {
            try!(write!(f, "{} -> [", i));
            if !state.transitions.is_empty() {
                try!(writeln!(f, ""));
            }
            let mut last_c = 0;
            let mut iter = (*state.transitions)
                .into_iter()
                .enumerate()
                .peekable();
            while let Some((c, tr)) = iter.next() {
                if let Some(&(c2, tr2)) = iter.peek() {
                    if tr == tr2 {
                        continue;
                    }
                    if c == last_c {
                        try!(writeln!(f, "  {:?} -> {:?},", c as u8 as char, tr));
                    } else {
                        try!(writeln!(f,
                                      "  [{:?}-{:?}] -> {:?},",
                                      last_c as u8 as char,
                                      (c as u8) as char,
                                      tr));
                    }
                    last_c = c2;
                }
            }
            try!(write!(f, "]"));
            if i == NFA_START {
                try!(write!(f, " -- start state"));
            }
            if self.finals[i] {
                try!(write!(f, " -- final state"));
            }
            try!(writeln!(f, ","));
        }
        Ok(())
    }
}

impl NFAState {
    fn freeze(&self) -> Result<DFAState, ()> {
        let mut transitions = Vec::with_capacity(self.transitions.len());
        for sns in &self.transitions {
            match sns.len() {
                0 => transitions.push(DFA_STUCK),
                1 => // Is there a better way to get this single element?
                    for &sn in sns {
                        transitions.push(sn);
                    },
                _ => return Err(()),
            }
        }
        Ok(DFAState::new(transitions.into_boxed_slice()))
    }
}

// Quick and dirty implementation, needs better thought out version
fn psc_rec_helper(nfa: &NFA,
                  dnfa: &mut NFA,
                  states_map: &mut HashMap<Vec<usize>, usize>,
                  cur_states: HashSet<usize>,
                  cur_num: usize) {
    for input in 0..255 {
        let mut nxt_states = HashSet::new();
        let mut fin = false;
        for cur_state in cur_states.clone() {
            let states = &nfa.states[cur_state].transitions[input];
            nxt_states = nxt_states.union(&mut states.clone()).map(|x| *x).collect();
            fin |= states.iter().map(|&st| nfa.finals.get(st).unwrap_or(false)).any(|x| x);
        }
        let nxt_states_vec = nxt_states.clone().into_iter().collect();
        match states_map.get(&nxt_states_vec) {
            Some(&nxt_num) => {
                dnfa.states[cur_num].transitions[input].insert(nxt_num);
            },
            None => {
                let nxt_num = dnfa.states.len();
                dnfa.states.push(NFAState { transitions: vec![HashSet::new(); 256] });
                dnfa.finals.push(fin);
                states_map.insert(nxt_states_vec, nxt_num);
                dnfa.states[cur_num].transitions[input].insert(nxt_num);
                if nxt_num != DFA_STUCK {
                    psc_rec_helper(nfa, dnfa, states_map, nxt_states, nxt_num);
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {}
<commit_msg>Following clippy's advice and using cloned<commit_after>extern crate bit_vec;

use self::bit_vec::BitVec;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fmt;

use super::dfa::{DFA, DFAState, DFA_STUCK, DFA_START};

pub type StateNumberSet = HashSet<usize>;

pub const NFA_START: usize = 0;

#[derive(Clone)]
pub struct NFAState {
    transitions: Vec<StateNumberSet>,
}

pub struct NFA {
    states: Vec<NFAState>,
    finals: BitVec,
}

impl NFA {
    pub fn from_dictionary(dict: &[&str]) -> Self {
        let num_states = dict.iter().fold(1, |sum, elem| sum + elem.len());
        let mut nfa = NFA {
            states: vec![NFAState { transitions: vec![HashSet::new(); 256] }; num_states],
            finals: BitVec::from_elem(num_states, false),
        };
        let mut nxt_state = NFA_START;
        for &string in dict.iter() {
            let mut cur_state = NFA_START;
            for byte in string.bytes() {
                if let Some(&state) = nfa.states[cur_state].transitions[byte as usize].get(&0) {
                    cur_state = state;
                } else {
                    nxt_state += 1;
                    nfa.states[cur_state].transitions[byte as usize].insert(nxt_state);
                    cur_state = nxt_state;
                }
            }
            nfa.finals.set(cur_state, true);
        }
        nfa
    }

    pub fn ignore_prefixes(&mut self) {
        for transition in &mut self.states[NFA_START].transitions {
            transition.insert(NFA_START);
        }
    }

    pub fn ignore_postfixes(&mut self) {
        for (fin,_) in self.finals.iter().enumerate().filter(|&(_,b)| b) {
            for mut transition in &mut self.states[fin].transitions {
                transition.insert(fin);
            }
        }
    }

    pub fn freeze(&self) -> Result<DFA, ()> {
        let mut states = Vec::with_capacity(self.states.len());
        for state in &self.states {
            states.push(try!(state.freeze()));
        }
        Ok(DFA::new(states.into_boxed_slice(), self.finals.clone()))
    }

    pub fn apply(&self, input: &[u8]) -> bool {
        let mut cur_states = HashSet::new();
        let mut nxt_states = HashSet::new();
        cur_states.insert(NFA_START);
        for &byte in input {
            for cur_state in cur_states {
                for &nxt_state in &self.states[cur_state].transitions[byte as usize] {
                    nxt_states.insert(nxt_state);
                }
            }
            cur_states = nxt_states;
            nxt_states = HashSet::new();
        }
        for state in cur_states {
            if self.finals[state] {
                return true;
            }
        }
        false
    }

    pub fn powerset_construction(&self) -> Self {
        let mut dnfa = NFA {
            states: vec![NFAState { transitions: vec![HashSet::new(); 256] }; 2],
            finals: BitVec::from_elem(2, false),
        };
        let mut states_map: HashMap<Vec<usize>, usize> = HashMap::new();
        let cur_states: HashSet<usize> = [NFA_START].into_iter().cloned().collect();

        dnfa.finals.set(DFA_START, self.finals.get(NFA_START).unwrap());

        states_map.insert(Vec::new(), DFA_STUCK);
        states_map.insert(cur_states.clone().into_iter().collect(), DFA_START);

        psc_rec_helper(self, &mut dnfa, &mut states_map, cur_states, DFA_START);
        dnfa
    }
}

impl fmt::Display for NFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, state) in (*self.states).into_iter().enumerate() {
            try!(write!(f, "{} -> [", i));
            if !state.transitions.is_empty() {
                try!(writeln!(f, ""));
            }
            let mut last_c = 0;
            let mut iter = (*state.transitions)
                .into_iter()
                .enumerate()
                .peekable();
            while let Some((c, tr)) = iter.next() {
                if let Some(&(c2, tr2)) = iter.peek() {
                    if tr == tr2 {
                        continue;
                    }
                    if c == last_c {
                        try!(writeln!(f, "  {:?} -> {:?},", c as u8 as char, tr));
                    } else {
                        try!(writeln!(f,
                                      "  [{:?}-{:?}] -> {:?},",
                                      last_c as u8 as char,
                                      (c as u8) as char,
                                      tr));
                    }
                    last_c = c2;
                }
            }
            try!(write!(f, "]"));
            if i == NFA_START {
                try!(write!(f, " -- start state"));
            }
            if self.finals[i] {
                try!(write!(f, " -- final state"));
            }
            try!(writeln!(f, ","));
        }
        Ok(())
    }
}

impl NFAState {
    fn freeze(&self) -> Result<DFAState, ()> {
        let mut transitions = Vec::with_capacity(self.transitions.len());
        for sns in &self.transitions {
            match sns.len() {
                0 => transitions.push(DFA_STUCK),
                1 => // Is there a better way to get this single element?
                    for &sn in sns {
                        transitions.push(sn);
                    },
                _ => return Err(()),
            }
        }
        Ok(DFAState::new(transitions.into_boxed_slice()))
    }
}

// Quick and dirty implementation, needs better thought out version
fn psc_rec_helper(nfa: &NFA,
                  dnfa: &mut NFA,
                  states_map: &mut HashMap<Vec<usize>, usize>,
                  cur_states: HashSet<usize>,
                  cur_num: usize) {
    for input in 0..255 {
        let mut nxt_states = HashSet::new();
        let mut fin = false;
        for cur_state in cur_states.clone() {
            let states = &nfa.states[cur_state].transitions[input];
            nxt_states = nxt_states.union(states).cloned().collect();
            fin |= states.iter().map(|&st| nfa.finals.get(st).unwrap_or(false)).any(|x| x);
        }
        let nxt_states_vec = nxt_states.clone().into_iter().collect();
        match states_map.get(&nxt_states_vec) {
            Some(&nxt_num) => {
                dnfa.states[cur_num].transitions[input].insert(nxt_num);
            },
            None => {
                let nxt_num = dnfa.states.len();
                dnfa.states.push(NFAState { transitions: vec![HashSet::new(); 256] });
                dnfa.finals.push(fin);
                states_map.insert(nxt_states_vec, nxt_num);
                dnfa.states[cur_num].transitions[input].insert(nxt_num);
                if nxt_num != DFA_STUCK {
                    psc_rec_helper(nfa, dnfa, states_map, nxt_states, nxt_num);
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.
//! A one-dimensional length, tagged with its units.

use num_traits;

pub trait Zero {
    fn zero() -> Self;
}

impl<T: num_traits::Zero> Zero for T {
    fn zero() -> T {
        num_traits::Zero::zero()
    }
}

pub trait One {
    fn one() -> Self;
}

impl<T: num_traits::One> One for T {
    fn one() -> T {
        num_traits::One::one()
    }
}

/// Defines the nearest integer value to the original value.
pub trait Round: Copy {
    /// Rounds to the nearest integer value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn round(self) -> Self;
}
/// Defines the biggest integer equal or lower than the original value.
pub trait Floor: Copy {
    /// Rounds to the biggest integer equal or lower than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn floor(self) -> Self;
}
/// Defines the smallest integer equal or greater than the original value.
pub trait Ceil: Copy {
    /// Rounds to the smallest integer equal or greater than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn ceil(self) -> Self;
}

macro_rules! num_int {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                self
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                self
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                self
            }
        }
    };
}
macro_rules! num_float {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                num_traits::Float::round(self)
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                num_traits::Float::floor(self)
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                num_traits::Float::ceil(self)
            }
        }
    };
}

num_int!(i16);
num_int!(u16);
num_int!(i32);
num_int!(u32);
num_int!(i64);
num_int!(u64);
num_int!(isize);
num_int!(usize);
num_float!(f32);
num_float!(f64);
<commit_msg>Auto merge of #433 - nical:numtraits, r=gw3583<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.
//! A one-dimensional length, tagged with its units.

use num_traits;

// Euclid has its own Zero and One traits instead of of using the num_traits equivalents.
// Unfortunately, num_traits::Zero requires Add, which opens a bag of sad things:
//  - Most importantly, for Point2D to implement Zero it would need to implement Add<Self> which we
//    don't want (we allow "Point + Vector" and "Vector + Vector" semantics and purposefully disallow
//    "Point + Point".
//  - Some operations that require, say, One and Div (for example Scale::inv) currently return a
//    type parameterized over T::Output which is ambiguous with num_traits::One because it inherits
//    Mul which also has an Output associated type. To fix it need to complicate type signatures
//    by using <T as Trait>::Output which makes the code and documentation harder to read.
//
// On the other hand, euclid::num::Zero/One are automatically implemented for all types that
// implement their num_traits counterpart. Euclid users never need to explicitly use
// euclid::num::Zero/One and can/should only manipulate the num_traits equivalents without risk
// of compatibility issues with euclid.

pub trait Zero {
    fn zero() -> Self;
}

impl<T: num_traits::Zero> Zero for T {
    fn zero() -> T {
        num_traits::Zero::zero()
    }
}

pub trait One {
    fn one() -> Self;
}

impl<T: num_traits::One> One for T {
    fn one() -> T {
        num_traits::One::one()
    }
}

/// Defines the nearest integer value to the original value.
pub trait Round: Copy {
    /// Rounds to the nearest integer value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn round(self) -> Self;
}
/// Defines the biggest integer equal or lower than the original value.
pub trait Floor: Copy {
    /// Rounds to the biggest integer equal or lower than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn floor(self) -> Self;
}
/// Defines the smallest integer equal or greater than the original value.
pub trait Ceil: Copy {
    /// Rounds to the smallest integer equal or greater than the original value.
    ///
    /// This behavior is preserved for negative values (unlike the basic cast).
    #[must_use]
    fn ceil(self) -> Self;
}

macro_rules! num_int {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                self
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                self
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                self
            }
        }
    };
}
macro_rules! num_float {
    ($ty:ty) => {
        impl Round for $ty {
            #[inline]
            fn round(self) -> $ty {
                num_traits::Float::round(self)
            }
        }
        impl Floor for $ty {
            #[inline]
            fn floor(self) -> $ty {
                num_traits::Float::floor(self)
            }
        }
        impl Ceil for $ty {
            #[inline]
            fn ceil(self) -> $ty {
                num_traits::Float::ceil(self)
            }
        }
    };
}

num_int!(i16);
num_int!(u16);
num_int!(i32);
num_int!(u32);
num_int!(i64);
num_int!(u64);
num_int!(isize);
num_int!(usize);
num_float!(f32);
num_float!(f64);
<|endoftext|>


<commit_before>use super::VirtualMachine;
use std::num::Wrapping;
use std::iter::range_inclusive;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] = vm.v[x] + Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] | vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] & vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] ^ vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 { 1 } else { 0 };
    vm.v[x] = vm.v[x] + vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] {1} else {0};
    vm.v[x] = vm.v[x] - vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] {1} else {0};
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if check_bit(vm.v[y].0, 0) {1} else {0};
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if check_bit(vm.v[y].0, 7) {1} else {0};
    vm.v[x] = vm.v[y] << 1;
}

fn check_bit(byte: u8, pos: usize) -> bool {
    byte & (1 << pos) != 0
}

#[test]
fn test_check_bit() {
    assert!(check_bit(0b10000000, 7));
    for i in 0..7 {
        assert!(!check_bit(0b10000000, i));
    }
    assert!(check_bit(0b01000000, 6));
    assert!(check_bit(0b00100000, 5));
    assert!(check_bit(0b00010000, 4));
    assert!(check_bit(0b00001000, 3));
    assert!(check_bit(0b00000100, 2));
    assert!(check_bit(0b00000010, 1));
    assert!(check_bit(0b00000001, 0));
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{ DISPLAY_WIDTH, DISPLAY_HEIGHT };

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + (vm.v[vx].0 as usize % DISPLAY_WIDTH);
            let yy = y + (vm.v[vy].0 as usize % DISPLAY_HEIGHT);

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in range_inclusive(0, x) {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in range_inclusive(0, x) {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<commit_msg>Remove horizontal wrapping behavior from sprite drawing<commit_after>use super::VirtualMachine;
use std::num::Wrapping;
use std::iter::range_inclusive;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] = vm.v[x] + Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] | vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] & vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] ^ vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 { 1 } else { 0 };
    vm.v[x] = vm.v[x] + vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] {1} else {0};
    vm.v[x] = vm.v[x] - vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] {1} else {0};
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if check_bit(vm.v[y].0, 0) {1} else {0};
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if check_bit(vm.v[y].0, 7) {1} else {0};
    vm.v[x] = vm.v[y] << 1;
}

fn check_bit(byte: u8, pos: usize) -> bool {
    byte & (1 << pos) != 0
}

#[test]
fn test_check_bit() {
    assert!(check_bit(0b10000000, 7));
    for i in 0..7 {
        assert!(!check_bit(0b10000000, i));
    }
    assert!(check_bit(0b01000000, 6));
    assert!(check_bit(0b00100000, 5));
    assert!(check_bit(0b00010000, 4));
    assert!(check_bit(0b00001000, 3));
    assert!(check_bit(0b00000100, 2));
    assert!(check_bit(0b00000010, 1));
    assert!(check_bit(0b00000001, 0));
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{ DISPLAY_WIDTH, DISPLAY_HEIGHT };

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + vm.v[vx].0 as usize;
            let yy = y + vm.v[vy].0 as usize;

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in range_inclusive(0, x) {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in range_inclusive(0, x) {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<|endoftext|>


<commit_before>/*
 * Rust BareBones OS
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * main.rs
 * - Top-level file for kernel
 *
 * This code has been put into the public domain, there are no restrictions on
 * its use, and the author takes no liability.
 */
#![feature(lang_items)]	//< unwind needs to define lang items
#![feature(asm)]	//< As a kernel, we need inline assembly
#![no_std]	//< Kernels can't use std
#![crate_name="kernel"]

/// A dummy 'std' module to work around a set of issues in rustc
mod std {
	// #18491 - write!() expands to std::fmt::Arguments::new
	pub use core::fmt;
	// #16803 - #[derive] references std::cmp
	pub use core::cmp;
	// #21827 - Slicing syntax references std::ops
	pub use core::ops;
	// #21827 - Loops reference std
	pub use core::iter;
	pub use core::option;
	// #16803 - Derive references marker/ops
	pub use core::marker;
}

/// Macros, need to be loaded before everything else due to how rust parses
#[macro_use]
mod macros;

// Achitecture-specific modules
#[cfg(target_arch="x86_64")] #[path="arch/amd64/mod.rs"]
pub mod arch;
#[cfg(target_arch="x86")] #[path="arch/x86/mod.rs"]
pub mod arch;

/// Exception handling (panic)
pub mod unwind;

/// Logging code
mod logging;

// Kernel entrypoint
#[lang="start"]
#[no_mangle]
pub fn kmain()
{
	log!("Hello world! 1={}", 1);
	loop {}
}

<commit_msg>Remove fake std module (no-longer needed)<commit_after>/*
 * Rust BareBones OS
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * main.rs
 * - Top-level file for kernel
 *
 * This code has been put into the public domain, there are no restrictions on
 * its use, and the author takes no liability.
 */
#![feature(lang_items)]	//< unwind needs to define lang items
#![feature(asm)]	//< As a kernel, we need inline assembly
#![no_std]	//< Kernels can't use std
#![crate_name="kernel"]

/// Macros, need to be loaded before everything else due to how rust parses
#[macro_use]
mod macros;

// Achitecture-specific modules
#[cfg(target_arch="x86_64")] #[path="arch/amd64/mod.rs"]
pub mod arch;
#[cfg(target_arch="x86")] #[path="arch/x86/mod.rs"]
pub mod arch;

/// Exception handling (panic)
pub mod unwind;

/// Logging code
mod logging;

// Kernel entrypoint
#[lang="start"]
#[no_mangle]
pub fn kmain()
{
	log!("Hello world! 1={}", 1);
	loop {}
}

<|endoftext|>


<commit_before>//! Create master and slave virtual pseudo-terminals (PTYs)

use libc;

pub use libc::pid_t as SessionId;
pub use libc::winsize as Winsize;

use std::ffi::CStr;
use std::mem;
use std::os::unix::prelude::*;

use sys::termios::Termios;
use {Result, Error, fcntl};
use errno::Errno;

/// Representation of a master/slave pty pair
///
/// This is returned by `openpty`.  Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
pub struct OpenptyResult {
    pub master: RawFd,
    pub slave: RawFd,
}

/// Representation of the Master device in a master/slave pty pair
///
/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
#[derive(Debug)]
pub struct PtyMaster(RawFd);

impl AsRawFd for PtyMaster {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

impl IntoRawFd for PtyMaster {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.0;
        mem::forget(self);
        fd
    }
}

impl Drop for PtyMaster {
    fn drop(&mut self) {
        // On drop, we ignore errors like EINTR and EIO because there's no clear
        // way to handle them, we can't return anything, and (on FreeBSD at
        // least) the file descriptor is deallocated in these cases.  However,
        // we must panic on EBADF, because it is always an error to close an
        // invalid file descriptor.  That frequently indicates a double-close
        // condition, which can cause confusing errors for future I/O
        // operations.
        let e = ::unistd::close(self.0);
        if e == Err(Error::Sys(Errno::EBADF)) {
            panic!("Closing an invalid file descriptor!");
        };
    }
}

/// Grant access to a slave pseudoterminal (see
/// [grantpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
///
/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
#[inline]
pub fn grantpt(fd: &PtyMaster) -> Result<()> {
    if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
        return Err(Error::last().into());
    }

    Ok(())
}

/// Open a pseudoterminal device (see
/// [posix_openpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
///
/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
///
/// # Examples
///
/// A common use case with this function is to open both a master and slave PTY pair. This can be
/// done as follows:
///
/// ```
/// use std::path::Path;
/// use nix::fcntl::{OFlag, open};
/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt};
/// use nix::sys::stat::Mode;
///
/// # #[allow(dead_code)]
/// # fn run() -> nix::Result<()> {
/// // Open a new PTY master
/// let master_fd = posix_openpt(OFlag::O_RDWR)?;
///
/// // Allow a slave to be generated for it
/// grantpt(&master_fd)?;
/// unlockpt(&master_fd)?;
///
/// // Get the name of the slave
/// let slave_name = unsafe { ptsname(&master_fd) }?;
///
/// // Try to open the slave
/// # #[allow(unused_variables)]
/// let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
    let fd = unsafe {
        libc::posix_openpt(flags.bits())
    };

    if fd < 0 {
        return Err(Error::last().into());
    }

    Ok(PtyMaster(fd))
}

/// Get the name of the slave pseudoterminal (see
/// [ptsname(3)](http://man7.org/linux/man-pages/man3/ptsname.3.html))
///
/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
/// referred to by `fd`.
///
/// This value is useful for opening the slave pty once the master has already been opened with
/// `posix_openpt()`.
///
/// # Safety
///
/// `ptsname()` mutates global variables and is *not* threadsafe.
/// Mutating global variables is always considered `unsafe` by Rust and this
/// function is marked as `unsafe` to reflect that.
///
/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
#[inline]
pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
    let name_ptr = libc::ptsname(fd.as_raw_fd());
    if name_ptr.is_null() {
        return Err(Error::last().into());
    }

    let name = CStr::from_ptr(name_ptr);
    Ok(name.to_string_lossy().into_owned())
}

/// Get the name of the slave pseudoterminal (see
/// [ptsname(3)](http://man7.org/linux/man-pages/man3/ptsname.3.html))
///
/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
/// POSIX standard and is instead a Linux-specific extension.
///
/// This value is useful for opening the slave ptty once the master has already been opened with
/// `posix_openpt()`.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[inline]
pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
    let mut name_buf = vec![0u8; 64];
    let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
    if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
        return Err(Error::last().into());
    }

    // Find the first null-character terminating this string. This is guaranteed to succeed if the
    // return value of `libc::ptsname_r` is 0.
    let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
    name_buf.truncate(null_index);

    let name = String::from_utf8(name_buf)?;
    Ok(name)
}

/// Unlock a pseudoterminal master/slave pseudoterminal pair (see
/// [unlockpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
///
/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
/// referred to by `fd`. This must be called before trying to open the slave side of a
/// pseuoterminal.
#[inline]
pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
    if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
        return Err(Error::last().into());
    }

    Ok(())
}

/// Create a new pseudoterminal, returning the slave and master file descriptors
/// in `OpenptyResult`
/// (see [openpty](http://man7.org/linux/man-pages/man3/openpty.3.html)).
///
/// If `winsize` is not `None`, the window size of the slave will be set to
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
    use std::ptr;

    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
    let mut master: libc::c_int = unsafe { mem::uninitialized() };
    let ret = {
        match (termios.into(), winsize.into()) {
            (Some(termios), Some(winsize)) => {
                let inner_termios = termios.get_libc_termios();
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        &*inner_termios as *const libc::termios as *mut _,
                        winsize as *const Winsize as *mut _,
                    )
                }
            }
            (None, Some(winsize)) => {
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        ptr::null_mut(),
                        winsize as *const Winsize as *mut _,
                    )
                }
            }
            (Some(termios), None) => {
                let inner_termios = termios.get_libc_termios();
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        &*inner_termios as *const libc::termios as *mut _,
                        ptr::null_mut(),
                    )
                }
            }
            (None, None) => {
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        ptr::null_mut(),
                        ptr::null_mut(),
                    )
                }
            }
        }
    };

    Errno::result(ret)?;

    Ok(OpenptyResult {
        master: master,
        slave: slave,
    })
}
<commit_msg>Remove unnecessary .into()<commit_after>//! Create master and slave virtual pseudo-terminals (PTYs)

use libc;

pub use libc::pid_t as SessionId;
pub use libc::winsize as Winsize;

use std::ffi::CStr;
use std::mem;
use std::os::unix::prelude::*;

use sys::termios::Termios;
use {Result, Error, fcntl};
use errno::Errno;

/// Representation of a master/slave pty pair
///
/// This is returned by `openpty`.  Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
pub struct OpenptyResult {
    pub master: RawFd,
    pub slave: RawFd,
}

/// Representation of the Master device in a master/slave pty pair
///
/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
#[derive(Debug)]
pub struct PtyMaster(RawFd);

impl AsRawFd for PtyMaster {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

impl IntoRawFd for PtyMaster {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.0;
        mem::forget(self);
        fd
    }
}

impl Drop for PtyMaster {
    fn drop(&mut self) {
        // On drop, we ignore errors like EINTR and EIO because there's no clear
        // way to handle them, we can't return anything, and (on FreeBSD at
        // least) the file descriptor is deallocated in these cases.  However,
        // we must panic on EBADF, because it is always an error to close an
        // invalid file descriptor.  That frequently indicates a double-close
        // condition, which can cause confusing errors for future I/O
        // operations.
        let e = ::unistd::close(self.0);
        if e == Err(Error::Sys(Errno::EBADF)) {
            panic!("Closing an invalid file descriptor!");
        };
    }
}

/// Grant access to a slave pseudoterminal (see
/// [grantpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
///
/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
#[inline]
pub fn grantpt(fd: &PtyMaster) -> Result<()> {
    if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
        return Err(Error::last());
    }

    Ok(())
}

/// Open a pseudoterminal device (see
/// [posix_openpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
///
/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
///
/// # Examples
///
/// A common use case with this function is to open both a master and slave PTY pair. This can be
/// done as follows:
///
/// ```
/// use std::path::Path;
/// use nix::fcntl::{OFlag, open};
/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt};
/// use nix::sys::stat::Mode;
///
/// # #[allow(dead_code)]
/// # fn run() -> nix::Result<()> {
/// // Open a new PTY master
/// let master_fd = posix_openpt(OFlag::O_RDWR)?;
///
/// // Allow a slave to be generated for it
/// grantpt(&master_fd)?;
/// unlockpt(&master_fd)?;
///
/// // Get the name of the slave
/// let slave_name = unsafe { ptsname(&master_fd) }?;
///
/// // Try to open the slave
/// # #[allow(unused_variables)]
/// let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
    let fd = unsafe {
        libc::posix_openpt(flags.bits())
    };

    if fd < 0 {
        return Err(Error::last());
    }

    Ok(PtyMaster(fd))
}

/// Get the name of the slave pseudoterminal (see
/// [ptsname(3)](http://man7.org/linux/man-pages/man3/ptsname.3.html))
///
/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
/// referred to by `fd`.
///
/// This value is useful for opening the slave pty once the master has already been opened with
/// `posix_openpt()`.
///
/// # Safety
///
/// `ptsname()` mutates global variables and is *not* threadsafe.
/// Mutating global variables is always considered `unsafe` by Rust and this
/// function is marked as `unsafe` to reflect that.
///
/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
#[inline]
pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
    let name_ptr = libc::ptsname(fd.as_raw_fd());
    if name_ptr.is_null() {
        return Err(Error::last());
    }

    let name = CStr::from_ptr(name_ptr);
    Ok(name.to_string_lossy().into_owned())
}

/// Get the name of the slave pseudoterminal (see
/// [ptsname(3)](http://man7.org/linux/man-pages/man3/ptsname.3.html))
///
/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
/// POSIX standard and is instead a Linux-specific extension.
///
/// This value is useful for opening the slave ptty once the master has already been opened with
/// `posix_openpt()`.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[inline]
pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
    let mut name_buf = vec![0u8; 64];
    let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
    if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
        return Err(Error::last());
    }

    // Find the first null-character terminating this string. This is guaranteed to succeed if the
    // return value of `libc::ptsname_r` is 0.
    let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
    name_buf.truncate(null_index);

    let name = String::from_utf8(name_buf)?;
    Ok(name)
}

/// Unlock a pseudoterminal master/slave pseudoterminal pair (see
/// [unlockpt(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
///
/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
/// referred to by `fd`. This must be called before trying to open the slave side of a
/// pseuoterminal.
#[inline]
pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
    if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
        return Err(Error::last());
    }

    Ok(())
}

/// Create a new pseudoterminal, returning the slave and master file descriptors
/// in `OpenptyResult`
/// (see [openpty](http://man7.org/linux/man-pages/man3/openpty.3.html)).
///
/// If `winsize` is not `None`, the window size of the slave will be set to
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
/// terminal settings of the slave will be set to the values in `termios`.
#[inline]
pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
    use std::ptr;

    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
    let mut master: libc::c_int = unsafe { mem::uninitialized() };
    let ret = {
        match (termios.into(), winsize.into()) {
            (Some(termios), Some(winsize)) => {
                let inner_termios = termios.get_libc_termios();
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        &*inner_termios as *const libc::termios as *mut _,
                        winsize as *const Winsize as *mut _,
                    )
                }
            }
            (None, Some(winsize)) => {
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        ptr::null_mut(),
                        winsize as *const Winsize as *mut _,
                    )
                }
            }
            (Some(termios), None) => {
                let inner_termios = termios.get_libc_termios();
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        &*inner_termios as *const libc::termios as *mut _,
                        ptr::null_mut(),
                    )
                }
            }
            (None, None) => {
                unsafe {
                    libc::openpty(
                        &mut master,
                        &mut slave,
                        ptr::null_mut(),
                        ptr::null_mut(),
                        ptr::null_mut(),
                    )
                }
            }
        }
    };

    Errno::result(ret)?;

    Ok(OpenptyResult {
        master: master,
        slave: slave,
    })
}
<|endoftext|>


<commit_before>extern crate mmap;

use std::ptr;
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;

const BCM2708_PERI_BASE: u32 = 0x20000000;
const GPIO_BASE: u8 = (BCM2708_PERI_BASE + 0x200000) as u8;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = (4*1024);

#[allow(dead_code)]
struct Bcm2835Peripheral {
    addr_p: *const u8,
    mem_fd: i32,
    map: mmap::MemoryMap,
    addr: *mut u8
}

fn main() {
    let gpio = Bcm2835Peripheral { addr_p: &GPIO_BASE, mem_fd: 0, map: MemoryMap::new(1024, &[]).unwrap(), addr: ptr::null_mut()};
    map_peripheral(gpio);
}

fn map_peripheral(mut foo: Bcm2835Peripheral) {
    let file = match OpenOptions::new()
                    .read(true)
                    .write(true)
                    .mode(O_SYNC)
                    .open("/dev/mem") {
      Ok(file) => file,
      Err(_e) => panic!("Unable to open /dev/mem, Are you root?")
    };

    let map_opts = &[
        MapOption::MapNonStandardFlags(MAP_SHARED),
        MapOption::MapReadable,
        MapOption::MapWritable,
       // MapOption::MapAddr(foo.addr_p),
        MapOption::MapFd(file.as_raw_fd())
    ];

   let mmap = match MemoryMap::new(BLOCK_SIZE, map_opts) {
     Ok(mmap) => mmap,
     Err(e) => panic!("ERR: {}", e)
    };
    foo.map = mmap;
    foo.addr = foo.map.data();
    println!("{:?}", foo.map.data());
}
<commit_msg>add unmap_peripheral fn just in case<commit_after>extern crate mmap;

use std::ptr;
use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;
use mmap::{MemoryMap, MapOption};
use std::os::unix::prelude::AsRawFd;

const BCM2708_PERI_BASE: u32 = 0x20000000;
const GPIO_BASE: u8 = (BCM2708_PERI_BASE + 0x200000) as u8;
const O_SYNC: u32 = 1052672;
const MAP_SHARED: i32 = 0x0001;
const BLOCK_SIZE: usize = (4*1024);

#[allow(dead_code)]
struct Bcm2835Peripheral {
    addr_p: *const u8,
    mem_fd: std::fs::File,
    map: mmap::MemoryMap,
    addr: *mut u8
}

fn main() {
    let mut gpio = Bcm2835Peripheral { addr_p: &GPIO_BASE, mem_fd: OpenOptions::new().create(true).open("temp.txt").unwrap(), map: MemoryMap::new(1024, &[]).unwrap(), addr: ptr::null_mut()};
    map_peripheral(&mut gpio);
    unmap_peripheral(&gpio);
}

fn map_peripheral(ref mut foo: &mut Bcm2835Peripheral) {
    let file = match OpenOptions::new()
                    .read(true)
                    .write(true)
                    .mode(O_SYNC)
                    .open("/dev/mem") {
      Ok(file) => file,
      Err(_e) => panic!("Unable to open /dev/mem, Are you root?")
    };

    let map_opts = &[
        MapOption::MapNonStandardFlags(MAP_SHARED),
        MapOption::MapReadable,
        MapOption::MapWritable,
       // MapOption::MapAddr(foo.addr_p),
        MapOption::MapFd(file.as_raw_fd())
    ];

   let mmap = match MemoryMap::new(BLOCK_SIZE, map_opts) {
     Ok(mmap) => mmap,
     Err(e) => panic!("ERR: {}", e)
    };
    foo.map = mmap;
    foo.addr = foo.map.data();
    println!("{:?}", foo.map.data());
}

fn unmap_peripheral(foo: &Bcm2835Peripheral) {
    drop(&foo.mem_fd);                              //Just in case :)
    drop(&foo.map);
}

<|endoftext|>