<commit_before>//! A collection of updates of the form `(T, i64)`.

/// A collection of updates of the form `(T, i64)`.
///
/// A `ChangeBatch` accumulates updates of the form `(T, i64)`, where it is capable of consolidating
/// the representation and removing elements whose `i64` field accumulates to zero.
///
/// The implementation is designed to be as lazy as possible, simply appending to a list of updates
/// until they are required. This means that several seemingly simple operations may be expensive, in
/// that they may provoke a compaction. I've tried to prevent exposing methods that allow surprisingly
/// expensive operations; all operations should take an amortized constant or logarithmic time.
#[derive(Clone, Debug)]
pub struct ChangeBatch<T> {
    // A list of updates to which we append.
    updates: Vec<(T, i64)>,
    // The length of the prefix of `self.updates` known to be compact.
    clean: usize,
}

impl<T:Ord> ChangeBatch<T> {

    /// Allocates a new empty `ChangeBatch`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// assert!(batch.is_empty());
    ///```
    pub fn new() -> ChangeBatch<T> {
        ChangeBatch {
            updates: Vec::new(),
            clean: 0
        }
    }

    /// Allocates a new `ChangeBatch` with a single entry.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    pub fn new_from(key: T, val: i64) -> ChangeBatch<T> {
        let mut result = ChangeBatch::new();
        result.update(key, val);
        result
    }

    /// Adds a new update, for `item` with `value`.
    ///
    /// This could be optimized to perform compaction when the number of "dirty" elements exceeds
    /// half the length of the list, which would keep the total footprint within reasonable bounds
    /// even under an arbitrary number of updates. This has a cost, and it isn't clear whether it
    /// is worth paying without some experimentation.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// batch.update(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    #[inline]
    pub fn update(&mut self, item: T, value: i64) {
        self.updates.push((item, value));
    }

    /// Performs a sequence of updates described by `iterator`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.extend(vec![(17, -1)].into_iter());
    /// assert!(batch.is_empty());
    ///```
    #[inline]
    pub fn extend<I: Iterator<Item=(T, i64)>>(&mut self, iterator: I) {
        for (key, val) in iterator {
            self.update(key, val);
        }
    }

    /// Extracts the `Vec<(T, i64)>` from the map, consuming it.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert_eq!(batch.into_inner(), vec![(17, 1)]);
    ///```
    pub fn into_inner(mut self) -> Vec<(T, i64)> {
        self.compact();
        self.updates
    }

    /// Iterates over the contents of the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.iter();
    ///     assert_eq!(iter.next(), Some(&(17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(!batch.is_empty());
    ///```
    pub fn iter(&mut self) -> ::std::slice::Iter<(T, i64)> {
        self.compact();
        self.updates.iter()
    }

    /// Drains the set of updates.
    ///
    /// This operation first compacts the set of updates so that the drained results
    /// have at most one occurence of each item.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.drain();
    ///     assert_eq!(iter.next(), Some((17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(batch.is_empty());
    ///```
    pub fn drain(&mut self) -> ::std::vec::Drain<(T, i64)> {
        self.compact();
        self.clean = 0;
        self.updates.drain(..)
    }

    /// Clears the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.clear();
    /// assert!(batch.is_empty());
    ///```
    pub fn clear(&mut self) {
        self.updates.clear();
        self.clean = 0;
    }

    /// True iff all keys have value zero.
    ///
    /// This method requires mutable access to `self` because it may need to compact the representation
    /// to determine if the batch of updates is indeed empty. We could also implement a weaker form of
    /// `is_empty` which just checks the length of `self.updates`, and which could confirm the absence of
    /// any updates, but could report false negatives if there are updates which would cancel.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.update(17, -1);
    /// assert!(batch.is_empty());
    ///```
    pub fn is_empty(&mut self) -> bool {
        if self.clean > self.updates.len() / 2 {
            false
        }
        else {
            self.compact();
            self.updates.is_empty()
        }
    }

    /// Drains `self` into `other`.
    ///
    /// This method has similar a effect to calling `other.extend(self.drain())`, but has the
    /// opportunity to optimize this to a `::std::mem::swap(self, other)` when `other` is empty.
    /// As many uses of this method are to propagate updates, this optimization can be quite
    /// handy.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch1 = ChangeBatch::<usize>::new_from(17, 1);
    /// let mut batch2 = ChangeBatch::new();
    /// batch1.drain_into(&mut batch2);
    /// assert!(batch1.is_empty());
    /// assert!(!batch2.is_empty());
    ///```
    pub fn drain_into(&mut self, other: &mut ChangeBatch<T>) where T: Clone {
        if other.updates.len() == 0 {
            ::std::mem::swap(self, other);
        }
        else {
            while let Some((ref key, val)) = self.updates.pop() {
                other.update(key.clone(), val);
            }
        }
    }

    /// Compact the internal representation.
    ///
    /// This method sort `self.updates` and consolidates elements with equal item, discarding
    /// any whose accumulation is zero. It is optimized to only do this if the number of dirty
    /// elements is non-zero.
    #[inline]
    fn compact(&mut self) {
        if self.clean < self.updates.len() && self.updates.len() > 1 {
            self.updates.sort_by(|x,y| x.0.cmp(&y.0));
            for i in 0 .. self.updates.len() - 1 {
                if self.updates[i].0 == self.updates[i+1].0 {
                    self.updates[i+1].1 += self.updates[i].1;
                    self.updates[i].1 = 0;
                }
            }
            self.updates.retain(|x| x.1 != 0);
        }
        self.clean = self.updates.len();
    }
}
<commit_msg>optimized drain_into<commit_after>//! A collection of updates of the form `(T, i64)`.

/// A collection of updates of the form `(T, i64)`.
///
/// A `ChangeBatch` accumulates updates of the form `(T, i64)`, where it is capable of consolidating
/// the representation and removing elements whose `i64` field accumulates to zero.
///
/// The implementation is designed to be as lazy as possible, simply appending to a list of updates
/// until they are required. This means that several seemingly simple operations may be expensive, in
/// that they may provoke a compaction. I've tried to prevent exposing methods that allow surprisingly
/// expensive operations; all operations should take an amortized constant or logarithmic time.
#[derive(Clone, Debug)]
pub struct ChangeBatch<T> {
    // A list of updates to which we append.
    updates: Vec<(T, i64)>,
    // The length of the prefix of `self.updates` known to be compact.
    clean: usize,
}

impl<T:Ord> ChangeBatch<T> {

    /// Allocates a new empty `ChangeBatch`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// assert!(batch.is_empty());
    ///```
    pub fn new() -> ChangeBatch<T> {
        ChangeBatch {
            updates: Vec::new(),
            clean: 0
        }
    }

    /// Allocates a new `ChangeBatch` with a single entry.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    pub fn new_from(key: T, val: i64) -> ChangeBatch<T> {
        let mut result = ChangeBatch::new();
        result.update(key, val);
        result
    }

    /// Adds a new update, for `item` with `value`.
    ///
    /// This could be optimized to perform compaction when the number of "dirty" elements exceeds
    /// half the length of the list, which would keep the total footprint within reasonable bounds
    /// even under an arbitrary number of updates. This has a cost, and it isn't clear whether it
    /// is worth paying without some experimentation.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new();
    /// batch.update(17, 1);
    /// assert!(!batch.is_empty());
    ///```
    #[inline]
    pub fn update(&mut self, item: T, value: i64) {
        self.updates.push((item, value));
    }

    /// Performs a sequence of updates described by `iterator`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.extend(vec![(17, -1)].into_iter());
    /// assert!(batch.is_empty());
    ///```
    #[inline]
    pub fn extend<I: Iterator<Item=(T, i64)>>(&mut self, iterator: I) {
        for (key, val) in iterator {
            self.update(key, val);
        }
    }

    /// Extracts the `Vec<(T, i64)>` from the map, consuming it.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let batch = ChangeBatch::<usize>::new_from(17, 1);
    /// assert_eq!(batch.into_inner(), vec![(17, 1)]);
    ///```
    pub fn into_inner(mut self) -> Vec<(T, i64)> {
        self.compact();
        self.updates
    }

    /// Iterates over the contents of the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.iter();
    ///     assert_eq!(iter.next(), Some(&(17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(!batch.is_empty());
    ///```
    pub fn iter(&mut self) -> ::std::slice::Iter<(T, i64)> {
        self.compact();
        self.updates.iter()
    }

    /// Drains the set of updates.
    ///
    /// This operation first compacts the set of updates so that the drained results
    /// have at most one occurence of each item.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// {   // scope allows borrow of `batch` to drop.
    ///     let mut iter = batch.drain();
    ///     assert_eq!(iter.next(), Some((17, 1)));
    ///     assert_eq!(iter.next(), None);
    /// }
    /// assert!(batch.is_empty());
    ///```
    pub fn drain(&mut self) -> ::std::vec::Drain<(T, i64)> {
        self.compact();
        self.clean = 0;
        self.updates.drain(..)
    }

    /// Clears the map.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.clear();
    /// assert!(batch.is_empty());
    ///```
    pub fn clear(&mut self) {
        self.updates.clear();
        self.clean = 0;
    }

    /// True iff all keys have value zero.
    ///
    /// This method requires mutable access to `self` because it may need to compact the representation
    /// to determine if the batch of updates is indeed empty. We could also implement a weaker form of
    /// `is_empty` which just checks the length of `self.updates`, and which could confirm the absence of
    /// any updates, but could report false negatives if there are updates which would cancel.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch = ChangeBatch::<usize>::new_from(17, 1);
    /// batch.update(17, -1);
    /// assert!(batch.is_empty());
    ///```
    pub fn is_empty(&mut self) -> bool {
        if self.clean > self.updates.len() / 2 {
            false
        }
        else {
            self.compact();
            self.updates.is_empty()
        }
    }

    /// Drains `self` into `other`.
    ///
    /// This method has similar a effect to calling `other.extend(self.drain())`, but has the
    /// opportunity to optimize this to a `::std::mem::swap(self, other)` when `other` is empty.
    /// As many uses of this method are to propagate updates, this optimization can be quite
    /// handy.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::ChangeBatch;
    ///
    /// let mut batch1 = ChangeBatch::<usize>::new_from(17, 1);
    /// let mut batch2 = ChangeBatch::new();
    /// batch1.drain_into(&mut batch2);
    /// assert!(batch1.is_empty());
    /// assert!(!batch2.is_empty());
    ///```
    pub fn drain_into(&mut self, other: &mut ChangeBatch<T>) where T: Clone {
        if other.updates.len() == 0 {
            ::std::mem::swap(self, other);
        }
        else {
            other.extend(self.updates.drain(..));
        }
    }

    /// Compact the internal representation.
    ///
    /// This method sort `self.updates` and consolidates elements with equal item, discarding
    /// any whose accumulation is zero. It is optimized to only do this if the number of dirty
    /// elements is non-zero.
    #[inline]
    fn compact(&mut self) {
        if self.clean < self.updates.len() && self.updates.len() > 1 {
            self.updates.sort_by(|x,y| x.0.cmp(&y.0));
            for i in 0 .. self.updates.len() - 1 {
                if self.updates[i].0 == self.updates[i+1].0 {
                    self.updates[i+1].1 += self.updates[i].1;
                    self.updates[i].1 = 0;
                }
            }
            self.updates.retain(|x| x.1 != 0);
        }
        self.clean = self.updates.len();
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use std::rc::Rc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use relay::socks5::Address;
use relay::BoxIoFuture;
use relay::dns_resolver::DnsResolver;

use futures::{self, Future};
use futures::stream::Stream;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::{Io, ReadHalf, WriteHalf};
use tokio_core::io::copy;

use ip::IpAddr;

use super::{tunnel, proxy_handshake, DecryptedHalf, EncryptedHalfFut};

/// Context for doing handshake with client
pub struct TcpRelayClientHandshake {
    handle: Handle,
    dns_resolver: DnsResolver,
    s: TcpStream,
    svr_cfg: Rc<ServerConfig>,
    forbidden_ip: Rc<HashSet<IpAddr>>,
}

impl TcpRelayClientHandshake {
    /// Doing handshake with client
    pub fn handshake(self) -> BoxIoFuture<TcpRelayClientPending> {
        let TcpRelayClientHandshake { handle, forbidden_ip, dns_resolver, s, svr_cfg } = self;

        let fut = proxy_handshake(s, svr_cfg).and_then(|(r_fut, w_fut)| {
            r_fut.and_then(|r| Address::read_from(r).map_err(From::from))
                .map(move |(r, addr)| {
                    TcpRelayClientPending {
                        handle: handle,
                        r: r,
                        addr: addr,
                        w: w_fut,
                        forbidden_ip: forbidden_ip,
                        dns_resolver: dns_resolver,
                    }
                })
        });
        Box::new(fut)
    }
}

/// Context for connecting remote
pub struct TcpRelayClientPending {
    handle: Handle,
    r: DecryptedHalf,
    addr: Address,
    w: EncryptedHalfFut,
    forbidden_ip: Rc<HashSet<IpAddr>>,
    dns_resolver: DnsResolver,
}

impl TcpRelayClientPending {
    /// Resolve Address to SocketAddr
    fn resolve_address(addr: Address, dns_resolver: DnsResolver) -> BoxIoFuture<SocketAddr> {
        match addr {
            Address::SocketAddress(addr) => Box::new(futures::finished(addr)),
            Address::DomainNameAddress(dname, port) => {
                let fut = dns_resolver.resolve(&dname[..])
                    .and_then(move |ipaddr| {
                        Ok(match ipaddr {
                            IpAddr::V4(v4) => SocketAddr::V4(SocketAddrV4::new(v4, port)),
                            IpAddr::V6(v6) => SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0)),
                        })
                    });
                Box::new(fut)
            }
        }
    }

    /// Resolve remote address to SocketAddr
    /// Report failure if the SocketAddr is forbidden by `forbidden_ip`
    fn resolve_remote(dns_resolver: DnsResolver,
                      addr: Address,
                      forbidden_ip: Rc<HashSet<IpAddr>>)
                      -> BoxIoFuture<SocketAddr> {
        let fut = TcpRelayClientPending::resolve_address(addr, dns_resolver).and_then(move |addr| {
            trace!("Resolved address as {}", addr);
            let ipaddr = match addr.clone() {
                SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
            };

            if forbidden_ip.contains(&ipaddr) {
                info!("{} has been forbidden", ipaddr);
                let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                Err(err)
            } else {
                Ok(addr)
            }
        });
        Box::new(fut)
    }

    /// Connect to the remote server
    fn connect_remote(dns_resolver: DnsResolver,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Rc<HashSet<IpAddr>>)
                      -> BoxIoFuture<TcpStream> {
        trace!("Connecting to remote {}", addr);
        Box::new(TcpRelayClientPending::resolve_remote(dns_resolver, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    /// Connect to the remote server
    pub fn connect(self) -> BoxIoFuture<TcpRelayClientConnected> {
        let addr = self.addr.clone();
        let client_pair = (self.r, self.w);
        let fut = TcpRelayClientPending::connect_remote(self.dns_resolver, self.handle, self.addr, self.forbidden_ip)
            .map(|stream| {
                TcpRelayClientConnected {
                    server: stream.split(),
                    client: client_pair,
                    addr: addr,
                }
            });
        Box::new(fut)
    }
}

/// Context for extablishing tunnel
pub struct TcpRelayClientConnected {
    server: (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
    client: (DecryptedHalf, EncryptedHalfFut),
    addr: Address,
}

impl TcpRelayClientConnected {
    /// Establish tunnel
    pub fn tunnel(self) -> BoxIoFuture<()> {
        let (svr_r, svr_w) = self.server;
        let (r, w_fut) = self.client;
        tunnel(self.addr,
               copy(r, svr_w),
               w_fut.and_then(|w| w.copy_from_encrypted(svr_r)))
    }
}

/// Runs the server
pub fn run(config: Rc<Config>, handle: Handle, dns_resolver: DnsResolver) -> Box<Future<Item = (), Error = io::Error>> {
    let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

    let ref forbidden_ip = config.forbidden_ip;
    let forbidden_ip = Rc::new(forbidden_ip.clone());

    for svr_cfg in &config.server {
        let listener = {
            let addr = svr_cfg.addr();
            let addr = addr.listen_addr();
            let listener = TcpListener::bind(addr, &handle).unwrap();
            trace!("ShadowSocks TCP Listening on {}", addr);
            listener
        };

        let svr_cfg = Rc::new(svr_cfg.clone());
        let handle = handle.clone();
        let dns_resolver = dns_resolver.clone();
        let forbidden_ip = forbidden_ip.clone();
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = svr_cfg.clone();
                let forbidden_ip = forbidden_ip.clone();
                let dns_resolver = dns_resolver.clone();

                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);

                let client = TcpRelayClientHandshake {
                    handle: handle.clone(),
                    dns_resolver: dns_resolver,
                    s: socket,
                    svr_cfg: server_cfg,
                    forbidden_ip: forbidden_ip,
                };

                let fut = client.handshake()
                    .and_then(|c| c.connect())
                    .and_then(|c| c.tunnel())
                    .map_err(move |err| {
                        error!("Failed to handle client ({}): {}", addr, err);
                    });

                handle.spawn(fut);
                Ok(())
            })
            .map_err(|err| {
                error!("Server run failed: {}", err);
                err
            });

        fut = Some(match fut.take() {
            Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
            None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
        })
    }

    fut.expect("Must have at least one server")
}
<commit_msg>increase server important log level<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! TcpRelay server that running on the server side

use std::io;
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use std::rc::Rc;
use std::collections::HashSet;

use config::{Config, ServerConfig};

use relay::socks5::Address;
use relay::BoxIoFuture;
use relay::dns_resolver::DnsResolver;

use futures::{self, Future};
use futures::stream::Stream;

use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::io::{Io, ReadHalf, WriteHalf};
use tokio_core::io::copy;

use ip::IpAddr;

use super::{tunnel, proxy_handshake, DecryptedHalf, EncryptedHalfFut};

/// Context for doing handshake with client
pub struct TcpRelayClientHandshake {
    handle: Handle,
    dns_resolver: DnsResolver,
    s: TcpStream,
    svr_cfg: Rc<ServerConfig>,
    forbidden_ip: Rc<HashSet<IpAddr>>,
}

impl TcpRelayClientHandshake {
    /// Doing handshake with client
    pub fn handshake(self) -> BoxIoFuture<TcpRelayClientPending> {
        let TcpRelayClientHandshake { handle, forbidden_ip, dns_resolver, s, svr_cfg } = self;

        let fut = proxy_handshake(s, svr_cfg).and_then(|(r_fut, w_fut)| {
            r_fut.and_then(|r| Address::read_from(r).map_err(From::from))
                .map(move |(r, addr)| {
                    TcpRelayClientPending {
                        handle: handle,
                        r: r,
                        addr: addr,
                        w: w_fut,
                        forbidden_ip: forbidden_ip,
                        dns_resolver: dns_resolver,
                    }
                })
        });
        Box::new(fut)
    }
}

/// Context for connecting remote
pub struct TcpRelayClientPending {
    handle: Handle,
    r: DecryptedHalf,
    addr: Address,
    w: EncryptedHalfFut,
    forbidden_ip: Rc<HashSet<IpAddr>>,
    dns_resolver: DnsResolver,
}

impl TcpRelayClientPending {
    /// Resolve Address to SocketAddr
    fn resolve_address(addr: Address, dns_resolver: DnsResolver) -> BoxIoFuture<SocketAddr> {
        match addr {
            Address::SocketAddress(addr) => Box::new(futures::finished(addr)),
            Address::DomainNameAddress(dname, port) => {
                let fut = dns_resolver.resolve(&dname[..])
                    .and_then(move |ipaddr| {
                        Ok(match ipaddr {
                            IpAddr::V4(v4) => SocketAddr::V4(SocketAddrV4::new(v4, port)),
                            IpAddr::V6(v6) => SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0)),
                        })
                    });
                Box::new(fut)
            }
        }
    }

    /// Resolve remote address to SocketAddr
    /// Report failure if the SocketAddr is forbidden by `forbidden_ip`
    fn resolve_remote(dns_resolver: DnsResolver,
                      addr: Address,
                      forbidden_ip: Rc<HashSet<IpAddr>>)
                      -> BoxIoFuture<SocketAddr> {
        let fut = TcpRelayClientPending::resolve_address(addr, dns_resolver).and_then(move |addr| {
            trace!("Resolved address as {}", addr);
            let ipaddr = match addr.clone() {
                SocketAddr::V4(v4) => IpAddr::V4(v4.ip().clone()),
                SocketAddr::V6(v6) => IpAddr::V6(v6.ip().clone()),
            };

            if forbidden_ip.contains(&ipaddr) {
                info!("{} has been forbidden", ipaddr);
                let err = io::Error::new(io::ErrorKind::Other, "Forbidden IP");
                Err(err)
            } else {
                Ok(addr)
            }
        });
        Box::new(fut)
    }

    /// Connect to the remote server
    fn connect_remote(dns_resolver: DnsResolver,
                      handle: Handle,
                      addr: Address,
                      forbidden_ip: Rc<HashSet<IpAddr>>)
                      -> BoxIoFuture<TcpStream> {
        info!("Connecting to remote {}", addr);
        Box::new(TcpRelayClientPending::resolve_remote(dns_resolver, addr, forbidden_ip)
            .and_then(move |addr| TcpStream::connect(&addr, &handle)))
    }

    /// Connect to the remote server
    pub fn connect(self) -> BoxIoFuture<TcpRelayClientConnected> {
        let addr = self.addr.clone();
        let client_pair = (self.r, self.w);
        let fut = TcpRelayClientPending::connect_remote(self.dns_resolver, self.handle, self.addr, self.forbidden_ip)
            .map(|stream| {
                TcpRelayClientConnected {
                    server: stream.split(),
                    client: client_pair,
                    addr: addr,
                }
            });
        Box::new(fut)
    }
}

/// Context for extablishing tunnel
pub struct TcpRelayClientConnected {
    server: (ReadHalf<TcpStream>, WriteHalf<TcpStream>),
    client: (DecryptedHalf, EncryptedHalfFut),
    addr: Address,
}

impl TcpRelayClientConnected {
    /// Establish tunnel
    pub fn tunnel(self) -> BoxIoFuture<()> {
        let (svr_r, svr_w) = self.server;
        let (r, w_fut) = self.client;
        tunnel(self.addr,
               copy(r, svr_w),
               w_fut.and_then(|w| w.copy_from_encrypted(svr_r)))
    }
}

/// Runs the server
pub fn run(config: Rc<Config>, handle: Handle, dns_resolver: DnsResolver) -> Box<Future<Item = (), Error = io::Error>> {
    let mut fut: Option<Box<Future<Item = (), Error = io::Error>>> = None;

    let ref forbidden_ip = config.forbidden_ip;
    let forbidden_ip = Rc::new(forbidden_ip.clone());

    for svr_cfg in &config.server {
        let listener = {
            let addr = svr_cfg.addr();
            let addr = addr.listen_addr();
            let listener = TcpListener::bind(addr, &handle).unwrap();
            info!("ShadowSocks TCP Listening on {}", addr);
            listener
        };

        let svr_cfg = Rc::new(svr_cfg.clone());
        let handle = handle.clone();
        let dns_resolver = dns_resolver.clone();
        let forbidden_ip = forbidden_ip.clone();
        let listening = listener.incoming()
            .for_each(move |(socket, addr)| {
                let server_cfg = svr_cfg.clone();
                let forbidden_ip = forbidden_ip.clone();
                let dns_resolver = dns_resolver.clone();

                trace!("Got connection, addr: {}", addr);
                trace!("Picked proxy server: {:?}", server_cfg);

                let client = TcpRelayClientHandshake {
                    handle: handle.clone(),
                    dns_resolver: dns_resolver,
                    s: socket,
                    svr_cfg: server_cfg,
                    forbidden_ip: forbidden_ip,
                };

                let fut = client.handshake()
                    .and_then(|c| c.connect())
                    .and_then(|c| c.tunnel())
                    .map_err(move |err| {
                        error!("Failed to handle client ({}): {}", addr, err);
                    });

                handle.spawn(fut);
                Ok(())
            })
            .map_err(|err| {
                error!("Server run failed: {}", err);
                err
            });

        fut = Some(match fut.take() {
            Some(fut) => Box::new(fut.join(listening).map(|_| ())) as Box<Future<Item = (), Error = io::Error>>,
            None => Box::new(listening) as Box<Future<Item = (), Error = io::Error>>,
        })
    }

    fut.expect("Must have at least one server")
}
<|endoftext|>


<commit_before>
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct TextureRegion {
    pub u_min: u32,
    pub u_max: u32,
    pub v_min: u32,
    pub v_max: u32,
    pub texture_size: u32,
}

impl TextureRegion {
    pub fn width(&self) -> u32 {
        self.u_max - self.u_min
    }

    pub fn height(&self) -> u32 {
        self.v_max - self.v_min
    }

    pub fn nu_min(&self) -> f32 {
        (self.u_min as f32) / (self.texture_size as f32)
    }

    pub fn nu_max(&self) -> f32 {
        (self.u_max as f32) / (self.texture_size as f32)
    }

    pub fn nv_min(&self) -> f32 {
        (self.v_min as f32) / (self.texture_size as f32)
    }

    pub fn nv_max(&self) -> f32 {
        (self.v_max as f32) / (self.texture_size as f32)
    }

    pub fn nu_mid(&self) -> f32 {
        (self.nu_min() + self.nu_max()) / 2.0
    }

    pub fn nv_mid(&self) -> f32 {
        (self.nv_min() + self.nv_max()) / 2.0
    }

    pub fn n_width(&self) -> f32 {
        ((self.u_max - self.u_min) as f32) / (self.texture_size as f32)
    }

    pub fn n_height(&self) -> f32 {
        ((self.v_max - self.v_min) as f32) / (self.texture_size as f32)
    }
}
<commit_msg>Added simple grid based texture atlas contruct<commit_after>
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct TextureRegion {
    pub u_min: u32,
    pub u_max: u32,
    pub v_min: u32,
    pub v_max: u32,
    pub texture_size: u32,
}

impl TextureRegion {
    pub fn width(&self) -> u32 {
        self.u_max - self.u_min
    }

    pub fn height(&self) -> u32 {
        self.v_max - self.v_min
    }

    pub fn nu_min(&self) -> f32 {
        (self.u_min as f32) / (self.texture_size as f32)
    }

    pub fn nu_max(&self) -> f32 {
        (self.u_max as f32) / (self.texture_size as f32)
    }

    pub fn nv_min(&self) -> f32 {
        (self.v_min as f32) / (self.texture_size as f32)
    }

    pub fn nv_max(&self) -> f32 {
        (self.v_max as f32) / (self.texture_size as f32)
    }

    pub fn nu_mid(&self) -> f32 {
        (self.nu_min() + self.nu_max()) / 2.0
    }

    pub fn nv_mid(&self) -> f32 {
        (self.nv_min() + self.nv_max()) / 2.0
    }

    pub fn n_width(&self) -> f32 {
        ((self.u_max - self.u_min) as f32) / (self.texture_size as f32)
    }

    pub fn n_height(&self) -> f32 {
        ((self.v_max - self.v_min) as f32) / (self.texture_size as f32)
    }
}

pub struct TextureAtlas {
    pub texture_size: u32,
    pub tiles_wide: u32,
    pub tiles_high: u32,
}

impl TextureAtlas {
    pub fn per_tile_x(&self) -> u32 {
        self.texture_size / self.tiles_wide
    }

    pub fn per_tile_y(&self) -> u32 {
        self.texture_size / self.tiles_high
    }

    pub fn tile_extents_x(&self, u:u32, width:u32) -> (u32, u32) {
        let u_min = self.per_tile_x() * u;
        let u_max = u_min + self.per_tile_x() * width;
        (u_min, u_max)
    }

    pub fn tile_extents_y(&self, v:u32, height: u32) -> (u32, u32) {
        let v_min = self.per_tile_y() * v;
        let v_max = v_min + self.per_tile_y() * height;
        (v_min, v_max)
    }

    pub fn at(&self, u: u32, v:u32) -> TextureRegion {
        let (u_min, u_max) = self.tile_extents_x(u, 1);
        let (v_min, v_max) = self.tile_extents_y(v, 1);
        TextureRegion {
            u_min: u_min,
            u_max: u_max,
            v_min: v_min,
            v_max: v_max,
            texture_size: self.texture_size,
        }
    }

    pub fn get(&self, u: u32, v: u32, wide: u32, high: u32) -> TextureRegion {
        let (u_min, u_max) = self.tile_extents_x(u, wide);
        let (v_min, v_max) = self.tile_extents_y(v, high);
         TextureRegion {
            u_min: u_min,
            u_max: u_max,
            v_min: v_min,
            v_max: v_max,
            texture_size: self.texture_size,
        }
    }
}<|endoftext|>


<commit_before>//! n-body benchmark from the [benchmarks game][bg].
//!
//! [bg]: https://benchmarksgame.alioth.debian.org/u64q/nbody-description.
//! html#nbody

#![cfg_attr(stdsimd_strict, deny(warnings))]
#![feature(stdsimd)]
#![cfg_attr(feature = "cargo-clippy",
            allow(similar_names, missing_docs_in_private_items,
                  shadow_reuse, print_stdout))]

extern crate stdsimd;
use stdsimd::simd::*;

const PI: f64 = std::f64::consts::PI;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;

pub trait Frsqrt {
    fn frsqrt(&self) -> Self;
}

impl Frsqrt for f64x2 {
    fn frsqrt(&self) -> Self {
        #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
                  target_feature = "sse"))]
        {
            #[cfg(target_arch = "x86")]
            use stdsimd::arch::x86::*;
            #[cfg(target_arch = "x86_64")]
            use stdsimd::arch::x86_64::*;
            let t: f32x2 = (*self).into();

            let u: f64x4 = unsafe {
                let res = _mm_rsqrt_ps(_mm_setr_ps(
                    t.extract(0),
                    t.extract(1),
                    0.,
                    0.,
                ));
                f32x4::from_bits(res).into()
            };
            Self::new(u.extract(0), u.extract(1))
        }
        #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
        {
            #[cfg(target_arch = "aarch64")]
            use stdsimd::arch::aarch64::*;
            #[cfg(target_arch = "arm")]
            use stdsimd::arch::arm::*;

            let t: f32x2 = (*self).into();
            let t: f32x2 = unsafe { vrsqrte_f32(t.into_bits()).into_bits() };
            t.into()
        }
        #[cfg(not(any(all(any(target_arch = "x86",
                              target_arch = "x86_64"),
                          target_feature = "sse"),
                      all(target_arch = "aarch64",
                          target_feature = "neon"))))]
        {
            let r = self.replace(0, 1. / self.extract(0).sqrt());
            let r = r.replace(1, 1. / self.extract(1).sqrt());
            r
        }
    }
}

struct Body {
    x: [f64; 3],
    _fill: f64,
    v: [f64; 3],
    mass: f64,
}

impl Body {
    fn new(
        x0: f64, x1: f64, x2: f64, v0: f64, v1: f64, v2: f64, mass: f64
    ) -> Self {
        Self {
            x: [x0, x1, x2],
            _fill: 0.0,
            v: [v0, v1, v2],
            mass,
        }
    }
}

const N_BODIES: usize = 5;
const N: usize = N_BODIES * (N_BODIES - 1) / 2;
fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
    let (sun, rest) = bodies.split_at_mut(1);
    let sun = &mut sun[0];
    for body in rest {
        for k in 0..3 {
            sun.v[k] -= body.v[k] * body.mass / SOLAR_MASS;
        }
    }
}
fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
    let mut r = [[0.0; 4]; N];
    let mut mag = [0.0; N];

    let mut dx = [f64x2::splat(0.0); 3];
    let mut dsquared;
    let mut distance;
    let mut dmag;

    let mut i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            for m in 0..3 {
                r[i][m] = bodies[j].x[m] - bodies[k].x[m];
            }
            i += 1;
        }
    }

    i = 0;
    while i < N {
        for (m, dx) in dx.iter_mut().enumerate() {
            *dx = f64x2::new(r[i][m], r[i + 1][m]);
        }

        dsquared = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2];
        distance = dsquared.frsqrt();
        for _ in 0..2 {
            distance = distance * f64x2::splat(1.5)
                - ((f64x2::splat(0.5) * dsquared) * distance)
                    * (distance * distance)
        }
        dmag = f64x2::splat(dt) / dsquared * distance;
        dmag.store_unaligned(&mut mag[i..]);

        i += 2;
    }

    i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            for m in 0..3 {
                bodies[j].v[m] -= r[i][m] * bodies[k].mass * mag[i];
                bodies[k].v[m] += r[i][m] * bodies[j].mass * mag[i];
            }
            i += 1
        }
    }
    for body in bodies {
        for m in 0..3 {
            body.x[m] += dt * body.v[m]
        }
    }
}

fn energy(bodies: &[Body; N_BODIES]) -> f64 {
    let mut e = 0.0;
    for i in 0..N_BODIES {
        let bi = &bodies[i];
        e += bi.mass
            * (bi.v[0] * bi.v[0] + bi.v[1] * bi.v[1] + bi.v[2] * bi.v[2])
            / 2.0;
        for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
            let mut dx = [0.0; 3];
            for (k, dx) in dx.iter_mut().enumerate() {
                *dx = bi.x[k] - bj.x[k];
            }
            let mut distance = 0.0;
            for &d in &dx {
                distance += d * d
            }
            e -= bi.mass * bj.mass / distance.sqrt()
        }
    }
    e
}

fn main() {
    let mut bodies: [Body; N_BODIES] = [
        /* sun */
        Body::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS),
        /* jupiter */
        Body::new(
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
            1.66007664274403694e-03 * DAYS_PER_YEAR,
            7.69901118419740425e-03 * DAYS_PER_YEAR,
            -6.90460016972063023e-05 * DAYS_PER_YEAR,
            9.54791938424326609e-04 * SOLAR_MASS,
        ),
        /* saturn */
        Body::new(
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
            -2.76742510726862411e-03 * DAYS_PER_YEAR,
            4.99852801234917238e-03 * DAYS_PER_YEAR,
            2.30417297573763929e-05 * DAYS_PER_YEAR,
            2.85885980666130812e-04 * SOLAR_MASS,
        ),
        /* uranus */
        Body::new(
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
            2.96460137564761618e-03 * DAYS_PER_YEAR,
            2.37847173959480950e-03 * DAYS_PER_YEAR,
            -2.96589568540237556e-05 * DAYS_PER_YEAR,
            4.36624404335156298e-05 * SOLAR_MASS,
        ),
        /* neptune */
        Body::new(
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
            2.68067772490389322e-03 * DAYS_PER_YEAR,
            1.62824170038242295e-03 * DAYS_PER_YEAR,
            -9.51592254519715870e-05 * DAYS_PER_YEAR,
            5.15138902046611451e-05 * SOLAR_MASS,
        ),
    ];

    let n: usize = std::env::args()
        .nth(1)
        .expect("need one arg")
        .parse()
        .expect("argument should be a usize");

    offset_momentum(&mut bodies);
    println!("{:.9}", energy(&bodies));
    for _ in 0..n {
        advance(&mut bodies, 0.01);
    }
    println!("{:.9}", energy(&bodies));
}
<commit_msg>Use cfg_if for the nbody example<commit_after>//! n-body benchmark from the [benchmarks game][bg].
//!
//! [bg]: https://benchmarksgame.alioth.debian.org/u64q/nbody-description.
//! html#nbody

#![cfg_attr(stdsimd_strict, deny(warnings))]
#![feature(stdsimd)]
#![cfg_attr(feature = "cargo-clippy",
            allow(similar_names, missing_docs_in_private_items,
                  shadow_reuse, print_stdout))]

extern crate stdsimd;
#[macro_use]
extern crate cfg_if;

use stdsimd::simd::*;

const PI: f64 = std::f64::consts::PI;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;

pub trait Frsqrt {
    fn frsqrt(&self) -> Self;
}

cfg_if! {
    if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
                  target_feature = "sse"))] {
        fn frsqrt(s: &f64x2) -> f64x2 {
            #[cfg(target_arch = "x86")]
            use stdsimd::arch::x86::*;
            #[cfg(target_arch = "x86_64")]
            use stdsimd::arch::x86_64::*;
            let t: f32x2 = (*s).into();

            let u: f64x4 = unsafe {
                let res = _mm_rsqrt_ps(_mm_setr_ps(
                    t.extract(0),
                    t.extract(1),
                    0.,
                    0.,
                ));
                f32x4::from_bits(res).into()
            };
            f64x2::new(u.extract(0), u.extract(1))
        }
    } else if #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] {
        fn frsqrt(s: &f64x2) -> f64x2 {
            #[cfg(target_arch = "aarch64")]
            use stdsimd::arch::aarch64::*;
            #[cfg(target_arch = "arm")]
            use stdsimd::arch::arm::*;

            let t: f32x2 = (*s).into();
            let t: f32x2 = unsafe { vrsqrte_f32(t.into_bits()).into_bits() };
            t.into()
        }
    } else {
        fn frsqrt(s: &f64x2) -> f64x2 {
            let r = s.replace(0, 1. / s.extract(0).sqrt());
            let r = r.replace(1, 1. / s.extract(1).sqrt());
            r
        }
    }
}

impl Frsqrt for f64x2 {
    fn frsqrt(&self) -> Self {
        frsqrt(self)
    }
}

struct Body {
    x: [f64; 3],
    _fill: f64,
    v: [f64; 3],
    mass: f64,
}

impl Body {
    fn new(
        x0: f64, x1: f64, x2: f64, v0: f64, v1: f64, v2: f64, mass: f64
    ) -> Self {
        Self {
            x: [x0, x1, x2],
            _fill: 0.0,
            v: [v0, v1, v2],
            mass,
        }
    }
}

const N_BODIES: usize = 5;
const N: usize = N_BODIES * (N_BODIES - 1) / 2;
fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
    let (sun, rest) = bodies.split_at_mut(1);
    let sun = &mut sun[0];
    for body in rest {
        for k in 0..3 {
            sun.v[k] -= body.v[k] * body.mass / SOLAR_MASS;
        }
    }
}
fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
    let mut r = [[0.0; 4]; N];
    let mut mag = [0.0; N];

    let mut dx = [f64x2::splat(0.0); 3];
    let mut dsquared;
    let mut distance;
    let mut dmag;

    let mut i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            for m in 0..3 {
                r[i][m] = bodies[j].x[m] - bodies[k].x[m];
            }
            i += 1;
        }
    }

    i = 0;
    while i < N {
        for (m, dx) in dx.iter_mut().enumerate() {
            *dx = f64x2::new(r[i][m], r[i + 1][m]);
        }

        dsquared = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2];
        distance = dsquared.frsqrt();
        for _ in 0..2 {
            distance = distance * f64x2::splat(1.5)
                - ((f64x2::splat(0.5) * dsquared) * distance)
                    * (distance * distance)
        }
        dmag = f64x2::splat(dt) / dsquared * distance;
        dmag.store_unaligned(&mut mag[i..]);

        i += 2;
    }

    i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            for m in 0..3 {
                bodies[j].v[m] -= r[i][m] * bodies[k].mass * mag[i];
                bodies[k].v[m] += r[i][m] * bodies[j].mass * mag[i];
            }
            i += 1
        }
    }
    for body in bodies {
        for m in 0..3 {
            body.x[m] += dt * body.v[m]
        }
    }
}

fn energy(bodies: &[Body; N_BODIES]) -> f64 {
    let mut e = 0.0;
    for i in 0..N_BODIES {
        let bi = &bodies[i];
        e += bi.mass
            * (bi.v[0] * bi.v[0] + bi.v[1] * bi.v[1] + bi.v[2] * bi.v[2])
            / 2.0;
        for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
            let mut dx = [0.0; 3];
            for (k, dx) in dx.iter_mut().enumerate() {
                *dx = bi.x[k] - bj.x[k];
            }
            let mut distance = 0.0;
            for &d in &dx {
                distance += d * d
            }
            e -= bi.mass * bj.mass / distance.sqrt()
        }
    }
    e
}

fn main() {
    let mut bodies: [Body; N_BODIES] = [
        /* sun */
        Body::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS),
        /* jupiter */
        Body::new(
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
            1.66007664274403694e-03 * DAYS_PER_YEAR,
            7.69901118419740425e-03 * DAYS_PER_YEAR,
            -6.90460016972063023e-05 * DAYS_PER_YEAR,
            9.54791938424326609e-04 * SOLAR_MASS,
        ),
        /* saturn */
        Body::new(
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
            -2.76742510726862411e-03 * DAYS_PER_YEAR,
            4.99852801234917238e-03 * DAYS_PER_YEAR,
            2.30417297573763929e-05 * DAYS_PER_YEAR,
            2.85885980666130812e-04 * SOLAR_MASS,
        ),
        /* uranus */
        Body::new(
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
            2.96460137564761618e-03 * DAYS_PER_YEAR,
            2.37847173959480950e-03 * DAYS_PER_YEAR,
            -2.96589568540237556e-05 * DAYS_PER_YEAR,
            4.36624404335156298e-05 * SOLAR_MASS,
        ),
        /* neptune */
        Body::new(
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
            2.68067772490389322e-03 * DAYS_PER_YEAR,
            1.62824170038242295e-03 * DAYS_PER_YEAR,
            -9.51592254519715870e-05 * DAYS_PER_YEAR,
            5.15138902046611451e-05 * SOLAR_MASS,
        ),
    ];

    let n: usize = std::env::args()
        .nth(1)
        .expect("need one arg")
        .parse()
        .expect("argument should be a usize");

    offset_momentum(&mut bodies);
    println!("{:.9}", energy(&bodies));
    for _ in 0..n {
        advance(&mut bodies, 0.01);
    }
    println!("{:.9}", energy(&bodies));
}
<|endoftext|>


<commit_before>use std::cell::{Cell, RefCell};
use std::ptr;

use cairo::{self, ImageSurface, MatrixTrait, PatternTrait};

use aspect_ratio::AspectRatio;
use attributes::Attribute;
use defs::Href;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
use handle::{self, RsvgHandle};
use node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;
use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

use super::bounds::BoundsBuilder;
use super::context::{FilterContext, FilterOutput, FilterResult, IRect};
use super::{Filter, FilterError, Primitive};

/// The `feImage` filter primitive.
pub struct Image {
    base: Primitive,
    aspect: Cell<AspectRatio>,
    href: RefCell<Option<String>>,

    // Storing this here seems hack-ish... It's required by rsvg_cairo_surface_new_from_href(). The
    // <image> element calls it in set_atts() but I don't think it belongs there.
    handle: Cell<*const RsvgHandle>,
}

impl Image {
    /// Constructs a new `Image` with empty properties.
    #[inline]
    pub fn new() -> Image {
        Image {
            base: Primitive::new::<Self>(),
            aspect: Cell::new(AspectRatio::default()),
            href: RefCell::new(None),

            handle: Cell::new(ptr::null()),
        }
    }

    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
        bounds: IRect,
        href: &str,
    ) -> Result<ImageSurface, FilterError> {
        // TODO: Port more of this to Rust.
        // Currently this is essentially a direct port of the C function.
        let acquired_drawable = draw_ctx
            .get_acquired_node(href)
            .ok_or(FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        draw_ctx.get_cairo_context().set_matrix(ctx.paffine());

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();

        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        draw_ctx
            .draw_node_on_surface(
                &drawable,
                &cascaded,
                &surface,
                f64::from(ctx.source_graphic().width()),
                f64::from(ctx.source_graphic().height()),
            )
            .map_err(|e| {
                if let RenderingError::Cairo(status) = e {
                    FilterError::CairoError(status)
                } else {
                    // FIXME: this is just a dummy value; we should probably have a way to indicate
                    // an error in the underlying drawing process.
                    FilterError::CairoError(cairo::Status::InvalidStatus)
                }
            })?;

        // Clip the output to bounds.
        let output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let cr = cairo::Context::new(&output_surface);
        cr.rectangle(
            f64::from(bounds.x0),
            f64::from(bounds.y0),
            f64::from(bounds.x1 - bounds.x0),
            f64::from(bounds.y1 - bounds.y0),
        );
        cr.clip();
        cr.set_source_surface(&surface, 0f64, 0f64);
        cr.paint();

        Ok(output_surface)
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
        bounds_builder: BoundsBuilder<'_>,
        href: &str,
    ) -> Result<ImageSurface, FilterError> {
        // FIXME: translate the error better here
        let surface = handle::image_surface_new_from_href(self.handle.get() as *mut _, href)
            .map_err(|_| FilterError::InvalidInput)?;

        let output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        // TODO: this goes through a f64->i32->f64 conversion.
        let render_bounds = bounds_builder.into_irect_without_clipping(draw_ctx);
        let aspect = self.aspect.get();
        let (x, y, w, h) = aspect.compute(
            f64::from(surface.get_width()),
            f64::from(surface.get_height()),
            f64::from(render_bounds.x0),
            f64::from(render_bounds.y0),
            f64::from(render_bounds.x1 - render_bounds.x0),
            f64::from(render_bounds.y1 - render_bounds.y0),
        );

        if w != 0f64 && h != 0f64 {
            let ptn = cairo::SurfacePattern::create(&surface);
            let mut matrix = cairo::Matrix::new(
                w / f64::from(surface.get_width()),
                0f64,
                0f64,
                h / f64::from(surface.get_height()),
                x,
                y,
            );
            matrix.invert();
            ptn.set_matrix(matrix);

            let bounds = bounds_builder.into_irect(draw_ctx);
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                f64::from(bounds.x0),
                f64::from(bounds.y0),
                f64::from(bounds.x1 - bounds.x0),
                f64::from(bounds.y1 - bounds.y0),
            );
            cr.clip();
            cr.set_source(&cairo::Pattern::SurfacePattern(ptn));
            cr.paint();
        }

        Ok(output_surface)
    }
}

impl NodeTrait for Image {
    fn set_atts(
        &self,
        node: &RsvgNode,
        handle: *const RsvgHandle,
        pbag: &PropertyBag<'_>,
    ) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::PreserveAspectRatio => {
                    self.aspect.set(parse("preserveAspectRatio", value, ())?)
                }

                // "path" is used by some older Adobe Illustrator versions
                Attribute::XlinkHref | Attribute::Path => {
                    drop(self.href.replace(Some(value.to_string())))
                }
                _ => (),
            }
        }

        self.handle.set(handle);

        Ok(())
    }
}

impl Filter for Image {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
    ) -> Result<FilterResult, FilterError> {
        let href = self.href.borrow();
        let href = href.as_ref().ok_or(FilterError::InvalidInput)?;

        let bounds_builder = self.base.get_bounds(ctx);
        let bounds = bounds_builder.into_irect(draw_ctx);

        let output_surface = match Href::parse(href).map_err(|_| FilterError::InvalidInput)? {
            Href::PlainUri(_) => self.render_external_image(ctx, draw_ctx, bounds_builder, href)?,
            _ => self.render_node(ctx, draw_ctx, bounds, href)?,
        };

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, SurfaceType::SRgb)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}
<commit_msg>filters/image.rs: Tweak how we match the Href<commit_after>use std::cell::{Cell, RefCell};
use std::ptr;

use cairo::{self, ImageSurface, MatrixTrait, PatternTrait};

use aspect_ratio::AspectRatio;
use attributes::Attribute;
use defs::Href;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
use handle::{self, RsvgHandle};
use node::{CascadedValues, NodeResult, NodeTrait, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;
use surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

use super::bounds::BoundsBuilder;
use super::context::{FilterContext, FilterOutput, FilterResult, IRect};
use super::{Filter, FilterError, Primitive};

/// The `feImage` filter primitive.
pub struct Image {
    base: Primitive,
    aspect: Cell<AspectRatio>,
    href: RefCell<Option<String>>,

    // Storing this here seems hack-ish... It's required by rsvg_cairo_surface_new_from_href(). The
    // <image> element calls it in set_atts() but I don't think it belongs there.
    handle: Cell<*const RsvgHandle>,
}

impl Image {
    /// Constructs a new `Image` with empty properties.
    #[inline]
    pub fn new() -> Image {
        Image {
            base: Primitive::new::<Self>(),
            aspect: Cell::new(AspectRatio::default()),
            href: RefCell::new(None),

            handle: Cell::new(ptr::null()),
        }
    }

    /// Renders the filter if the source is an existing node.
    fn render_node(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
        bounds: IRect,
        href: &str,
    ) -> Result<ImageSurface, FilterError> {
        // TODO: Port more of this to Rust.
        // Currently this is essentially a direct port of the C function.
        let acquired_drawable = draw_ctx
            .get_acquired_node(href)
            .ok_or(FilterError::InvalidInput)?;
        let drawable = acquired_drawable.get();

        let surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        draw_ctx.get_cairo_context().set_matrix(ctx.paffine());

        let node_being_filtered_values = ctx.get_computed_values_from_node_being_filtered();

        let cascaded = CascadedValues::new_from_values(&drawable, node_being_filtered_values);

        draw_ctx
            .draw_node_on_surface(
                &drawable,
                &cascaded,
                &surface,
                f64::from(ctx.source_graphic().width()),
                f64::from(ctx.source_graphic().height()),
            )
            .map_err(|e| {
                if let RenderingError::Cairo(status) = e {
                    FilterError::CairoError(status)
                } else {
                    // FIXME: this is just a dummy value; we should probably have a way to indicate
                    // an error in the underlying drawing process.
                    FilterError::CairoError(cairo::Status::InvalidStatus)
                }
            })?;

        // Clip the output to bounds.
        let output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let cr = cairo::Context::new(&output_surface);
        cr.rectangle(
            f64::from(bounds.x0),
            f64::from(bounds.y0),
            f64::from(bounds.x1 - bounds.x0),
            f64::from(bounds.y1 - bounds.y0),
        );
        cr.clip();
        cr.set_source_surface(&surface, 0f64, 0f64);
        cr.paint();

        Ok(output_surface)
    }

    /// Renders the filter if the source is an external image.
    fn render_external_image(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
        bounds_builder: BoundsBuilder<'_>,
        uri: &str,
    ) -> Result<ImageSurface, FilterError> {
        // FIXME: translate the error better here
        let surface = handle::image_surface_new_from_href(self.handle.get() as *mut _, uri)
            .map_err(|_| FilterError::InvalidInput)?;

        let output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        // TODO: this goes through a f64->i32->f64 conversion.
        let render_bounds = bounds_builder.into_irect_without_clipping(draw_ctx);
        let aspect = self.aspect.get();
        let (x, y, w, h) = aspect.compute(
            f64::from(surface.get_width()),
            f64::from(surface.get_height()),
            f64::from(render_bounds.x0),
            f64::from(render_bounds.y0),
            f64::from(render_bounds.x1 - render_bounds.x0),
            f64::from(render_bounds.y1 - render_bounds.y0),
        );

        if w != 0f64 && h != 0f64 {
            let ptn = cairo::SurfacePattern::create(&surface);
            let mut matrix = cairo::Matrix::new(
                w / f64::from(surface.get_width()),
                0f64,
                0f64,
                h / f64::from(surface.get_height()),
                x,
                y,
            );
            matrix.invert();
            ptn.set_matrix(matrix);

            let bounds = bounds_builder.into_irect(draw_ctx);
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                f64::from(bounds.x0),
                f64::from(bounds.y0),
                f64::from(bounds.x1 - bounds.x0),
                f64::from(bounds.y1 - bounds.y0),
            );
            cr.clip();
            cr.set_source(&cairo::Pattern::SurfacePattern(ptn));
            cr.paint();
        }

        Ok(output_surface)
    }
}

impl NodeTrait for Image {
    fn set_atts(
        &self,
        node: &RsvgNode,
        handle: *const RsvgHandle,
        pbag: &PropertyBag<'_>,
    ) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::PreserveAspectRatio => {
                    self.aspect.set(parse("preserveAspectRatio", value, ())?)
                }

                // "path" is used by some older Adobe Illustrator versions
                Attribute::XlinkHref | Attribute::Path => {
                    drop(self.href.replace(Some(value.to_string())))
                }
                _ => (),
            }
        }

        self.handle.set(handle);

        Ok(())
    }
}

impl Filter for Image {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx<'_>,
    ) -> Result<FilterResult, FilterError> {
        let href_str = self.href.borrow();
        let href_str = href_str.as_ref().ok_or(FilterError::InvalidInput)?;

        let bounds_builder = self.base.get_bounds(ctx);
        let bounds = bounds_builder.into_irect(draw_ctx);

        let href = Href::parse(href_str).map_err(|_| FilterError::InvalidInput)?;

        let output_surface = match href {
            Href::PlainUri(ref uri) => {
                self.render_external_image(ctx, draw_ctx, bounds_builder, uri)?
            }
            _ => self.render_node(ctx, draw_ctx, bounds, href_str)?,
        };

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, SurfaceType::SRgb)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>#![crate_id(name="uptime", vers="1.0.0", author="José Neder")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#![allow(non_camel_case_types)]
#![feature(macro_rules, globs)]

extern crate getopts;
extern crate libc;

use std::os;
use std::mem::transmute;
use std::io::{print, File};
use std::ptr::null;
use std::from_str::from_str;
use libc::{time_t, c_double, c_int, c_char};
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

#[allow(dead_code)]
fn main() { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts).as_slice());
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2f}{}", avg[n as uint], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn process_utmpx() -> (Option<time_t>, uint) {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

fn print_nusers(nusers: uint) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return match boot_time {
                Some(t) => {
                    let now = unsafe { time(null()) };
                    (now - t) * 100 // Return in ms
                },
                _ => -1
             }
    };

    match uptime_text.as_slice().words().next() {
        Some(s) => match from_str(s.replace(".","").as_slice()) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<commit_msg>Fix build failure for systems with a non-64-bit time_t.<commit_after>#![crate_id(name="uptime", vers="1.0.0", author="José Neder")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: cat (GNU coreutils) 8.13 */

#![allow(non_camel_case_types)]
#![feature(macro_rules, globs)]

extern crate getopts;
extern crate libc;

use std::os;
use std::mem::transmute;
use std::io::{print, File};
use std::ptr::null;
use std::from_str::from_str;
use libc::{time_t, c_double, c_int, c_char};
use c_types::c_tm;
use utmpx::*;

#[path = "../common/util.rs"] mod util;

#[path = "../common/c_types.rs"] mod c_types;

#[path = "../common/utmpx.rs"] mod utmpx;

static NAME: &'static str = "uptime";

extern {
    fn time(timep: *time_t) -> time_t;
    fn localtime(timep: *time_t) -> *c_tm;

    fn getloadavg(loadavg: *c_double, nelem: c_int) -> c_int;

    fn getutxent() -> *c_utmp;
    fn setutxent();
    fn endutxent();

    fn utmpxname(file: *c_char) -> c_int;
}

#[allow(dead_code)]
fn main() { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();
    let opts = [
        getopts::optflag("v", "version", "output version information and exit"),
        getopts::optflag("h", "help", "display this help and exit"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("version") {
        println!("uptime 1.0.0");
        return 0;
    }
    if matches.opt_present("help") || matches.free.len() > 0 {
        println!("Usage:");
        println!("  {0:s} [OPTION]", program);
        println!("");
        print(getopts::usage("Print the current time, the length of time the system has been up,\n\
                              the number of users on the system, and the average number of jobs\n\
                              in the run queue over the last 1, 5 and 15 minutes.", opts).as_slice());
        return 0;
    }

    print_time();
    let (boot_time, user_count) = process_utmpx();
    let upsecs = get_uptime(boot_time) / 100;
    print_uptime(upsecs);
    print_nusers(user_count);
    print_loadavg();

    0
}

fn print_loadavg() {
    let avg: [c_double, ..3] = [0.0, ..3];
    let loads: i32 = unsafe { transmute(getloadavg(avg.as_ptr(), 3)) };

    if loads == -1 {
        print!("\n");
    }
    else {
        print!("load average: ")
        for n in range(0, loads) {
            print!("{:.2f}{}", avg[n as uint], if n == loads - 1 { "\n" }
                                   else { ", " } );
        }
    }
}

fn process_utmpx() -> (Option<time_t>, uint) {
    DEFAULT_FILE.with_c_str(|filename| {
        unsafe {
            utmpxname(filename);
        }
    });

    let mut nusers = 0;
    let mut boot_time = None;

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == null() {
                break;
            }

            match (*line).ut_type {
                USER_PROCESS => nusers += 1,
                BOOT_TIME => {
                    let t = (*line).ut_tv;
                    if t.tv_sec > 0 {
                        boot_time = Some(t.tv_sec);
                    }
                },
                _ => continue
            }
        }

        endutxent();
    }

    (boot_time, nusers)
}

fn print_nusers(nusers: uint) {
    if nusers == 1 {
        print!("1 user, ");
    } else if nusers > 1 {
        print!("{} users, ", nusers);
    }
}

fn print_time() {
    let local_time = unsafe { *localtime(&time(null())) };

    if local_time.tm_hour >= 0 && local_time.tm_min >= 0 &&
       local_time.tm_sec >= 0 {
        print!(" {:02d}:{:02d}:{:02d} ", local_time.tm_hour,
               local_time.tm_min, local_time.tm_sec);
    }
}

fn get_uptime(boot_time: Option<time_t>) -> i64 {
    let proc_uptime = File::open(&Path::new("/proc/uptime"))
                            .read_to_str();

    let uptime_text = match proc_uptime {
        Ok(s) => s,
        _ => return match boot_time {
                Some(t) => {
                    let now = unsafe { time(null()) };
                    ((now - t) * 100) as i64 // Return in ms
                },
                _ => -1
             }
    };

    match uptime_text.as_slice().words().next() {
        Some(s) => match from_str(s.replace(".","").as_slice()) {
                    Some(n) => n,
                    None => -1
                   },
        None => -1
    }
}

fn print_uptime(upsecs: i64) {
    let updays = upsecs / 86400;
    let uphours = (upsecs - (updays * 86400)) / 3600;
    let upmins = (upsecs - (updays * 86400) - (uphours * 3600)) / 60;
    if updays == 1 {
        print!("up {:1d} day, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else if updays > 1 {
        print!("up {:1d} days, {:2d}:{:02d},  ", updays, uphours, upmins);
    }
    else {
        print!("up  {:2d}:{:02d},  ", uphours, upmins);
    }
}
<|endoftext|>


<commit_before>//! # gpio module
//!
//! This module provides access to the GPIO of the stm32f0 board.
//! You can:
//!
//! * configure a PIN in Input or Output
//! * read or write the PIN depending on its configuration
//!
//! ## Examples
//!
//! ```
//! extern crate stm32f0_hal;
//!
//! use stm32f0_hal::gpio;
//!
// ! let p_in = gpio::Input::setup(gpio::Pin::PA1);
// ! let b = p_in.read();
// !
// ! let p_out = gpio::Output::setup(gpio::Pin::PA5);
// ! p_out.write(true);
//! ```

use cortex_m;
use stm32f0x2::{RCC, GPIOA};

enum Mode {
    Input = 0b00,
    Output = 0b01,
}

/// GPIO Pin available on PORT A
pub enum Pin {
    PA1,
    PA5,
}

/// Input Mode Pin
pub struct Input {
    pin: Pin,
}

impl Input {
    /// Setup a PIN in Input Mode
    pub fn setup(pin: Pin) -> Input {
        setup_pin(&pin, Mode::Input);
        Input { pin }
    }

    /// Read the state of a PIN
    pub fn read(&self) -> bool {
        unsafe {
            match self.pin {
                Pin::PA1 => (*GPIOA.get()).idr.read().idr1().bit(),
                Pin::PA5 => (*GPIOA.get()).idr.read().idr5().bit(),
            }
        }
    }
}

/// Output Mode Pin
pub struct Output {
    pin: Pin,
}

impl Output {
    /// Setup a PIN in Output Mode
    pub fn setup(pin: Pin) -> Output {
        setup_pin(&pin, Mode::Output);
        Output { pin }
    }
    /// Set the PIN to high
    pub fn high(&mut self) {
        self.set(true);
    }
    /// Set the PIN to low
    pub fn low(&mut self) {
        self.set(false);
    }
    fn set(&mut self, on: bool) {
        unsafe {
            match self.pin {
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.bs1().bit(on)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.bs5().bit(on)),
            }
        }
    }
}

fn setup_pin(pin: &Pin, mode: Mode) {
    cortex_m::interrupt::free(|cs| {
        let rcc = RCC.borrow(cs);

        let gpioa = GPIOA.borrow(cs);
        rcc.ahbenr.modify(|_, w| w.iopaen().enabled());

        let mode = mode as u8;

        match *pin {
            Pin::PA1 => gpioa.moder.modify(|_, w| w.moder1().bits(mode)),
            Pin::PA5 => gpioa.moder.modify(|_, w| w.moder5().bits(mode)),
        }
    });
}
<commit_msg>Bug fix in gpio::low command.<commit_after>//! # gpio module
//!
//! This module provides access to the GPIO of the stm32f0 board.
//! You can:
//!
//! * configure a PIN in Input or Output
//! * read or write the PIN depending on its configuration
//!
//! ## Examples
//!
//! ```
//! extern crate stm32f0_hal;
//!
//! use stm32f0_hal::gpio;
//!
// ! let p_in = gpio::Input::setup(gpio::Pin::PA1);
// ! let b = p_in.read();
// !
// ! let p_out = gpio::Output::setup(gpio::Pin::PA5);
// ! p_out.write(true);
//! ```

use cortex_m;
use stm32f0x2::{RCC, GPIOA};

enum Mode {
    Input = 0b00,
    Output = 0b01,
}

/// GPIO Pin available on PORT A
pub enum Pin {
    PA1,
    PA5,
}

/// Input Mode Pin
pub struct Input {
    pin: Pin,
}

impl Input {
    /// Setup a PIN in Input Mode
    pub fn setup(pin: Pin) -> Input {
        setup_pin(&pin, Mode::Input);
        Input { pin }
    }

    /// Read the state of a PIN
    pub fn read(&self) -> bool {
        unsafe {
            match self.pin {
                Pin::PA1 => (*GPIOA.get()).idr.read().idr1().bit(),
                Pin::PA5 => (*GPIOA.get()).idr.read().idr5().bit(),
            }
        }
    }
}

/// Output Mode Pin
pub struct Output {
    pin: Pin,
}

impl Output {
    /// Setup a PIN in Output Mode
    pub fn setup(pin: Pin) -> Output {
        setup_pin(&pin, Mode::Output);
        Output { pin }
    }
    /// Set the PIN to high
    pub fn high(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.bs1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.bs5().bit(true)),
            }
        }
    }
    /// Set the PIN to low
    pub fn low(&mut self) {
        unsafe {
            match self.pin {
                Pin::PA1 => (*GPIOA.get()).bsrr.write(|w| w.br1().bit(true)),
                Pin::PA5 => (*GPIOA.get()).bsrr.write(|w| w.br5().bit(true)),
            }
        }
    }
}

fn setup_pin(pin: &Pin, mode: Mode) {
    cortex_m::interrupt::free(|cs| {
        let rcc = RCC.borrow(cs);

        let gpioa = GPIOA.borrow(cs);
        rcc.ahbenr.modify(|_, w| w.iopaen().enabled());

        let mode = mode as u8;

        match *pin {
            Pin::PA1 => gpioa.moder.modify(|_, w| w.moder1().bits(mode)),
            Pin::PA5 => gpioa.moder.modify(|_, w| w.moder5().bits(mode)),
        }
    });
}
<|endoftext|>


<commit_before>extern mod harfbuzz;

use au = gfx::geometry;
use au::au;
use core::num::from_int;
use font::Font;
use font_cache::FontCache;
use geom::point::Point2D;
use glyph::{GlyphStore, GlyphIndex, GlyphData};
use libc::types::common::c99::int32_t;
use libc::{c_uint, c_int, c_void, c_char};
use ptr::{null, to_unsafe_ptr, offset};
use std::arc;
use text_run::TextRun;
use util::*;

use cast::reinterpret_cast;
use harfbuzz::{HB_MEMORY_MODE_READONLY,
                  HB_DIRECTION_LTR};
use harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t, hb_buffer_t,
                  hb_codepoint_t, hb_bool_t, hb_glyph_position_t,
		  hb_glyph_info_t, hb_var_int_t, hb_position_t};
use harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
                           hb_face_create, hb_face_destroy,
                           hb_font_create, hb_font_destroy,
                           hb_buffer_create, hb_buffer_destroy,
                           hb_buffer_add_utf8, hb_shape,
                           hb_buffer_get_glyph_infos,
                           hb_buffer_get_glyph_positions,
                           hb_font_set_ppem, hb_font_set_scale,
                           hb_buffer_set_direction,
                           hb_font_funcs_create, hb_font_funcs_destroy,
                           hb_font_set_funcs,
                           hb_font_funcs_set_glyph_h_advance_func,
                           hb_font_funcs_set_glyph_func,
                           hb_font_funcs_set_glyph_h_kerning_func};

fn float_to_fixed_hb(f: float) -> i32 {
    util::float_to_fixed(16, f)
}

fn fixed_to_float_hb(i: hb_position_t) -> float {
    util::fixed_to_float(16, i)
}

fn fixed_to_rounded_int_hb(f: hb_position_t) -> int {
    util::fixed_to_rounded_int(16, f)
}

/**
Calculate the layout metrics associated with a some given text
when rendered in a specific font.
*/
pub fn shape_textrun(run: &TextRun) {
    debug!("shaping text '%s'", run.text);

    // TODO: harfbuzz fonts and faces should be cached on the Font object.
    // TODO: font tables should be stored in Font object and cached by FontCache (Issue #92)
    let face_blob: *hb_blob_t = vec::as_imm_buf(*(run.font).fontbuf, |buf: *u8, len: uint| {
        hb_blob_create(buf as *c_char,
                       len as c_uint,
                       HB_MEMORY_MODE_READONLY,
                       null(),
                       null())
    });

    let hb_face: *hb_face_t = hb_face_create(face_blob, 0 as c_uint);
    let hb_font: *hb_font_t = hb_font_create(hb_face);

    // TODO: set font size here, based on Font's size
    // Set points-per-em. if zero, performs no hinting in that direction.
    hb_font_set_ppem(hb_font, 21 as c_uint, 21 as c_uint);
    // Set scaling. Note that this takes 16.16 fixed point.
    hb_font_set_scale(hb_font, float_to_fixed_hb(21f) as c_int, float_to_fixed_hb(21f) as c_int);

    let funcs: *hb_font_funcs_t = hb_font_funcs_create();
    hb_font_funcs_set_glyph_func(funcs, glyph_func, null(), null());
    hb_font_funcs_set_glyph_h_advance_func(funcs, glyph_h_advance_func, null(), null());

    unsafe {
        let font_data: *c_void = core::ptr::addr_of(run.font) as *c_void;
        hb_font_set_funcs(hb_font, funcs, font_data, null());
    };

    let hb_buffer: *hb_buffer_t = hb_buffer_create();
    hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);

    // Using as_buf because it never does a copy - we don't need the trailing null
    str::as_buf(run.text, |ctext: *u8, _l: uint| {
        hb_buffer_add_utf8(hb_buffer,
                           ctext as *c_char,
                           run.text.len() as c_int,
                           0 as c_uint,
                           run.text.len() as c_int);
    });

    hb_shape(hb_font, hb_buffer, null(), 0 as c_uint);

    let info_buf_len = 0 as c_uint;
    let info_buf = hb_buffer_get_glyph_infos(hb_buffer, to_unsafe_ptr(&info_buf_len));
    assert info_buf.is_not_null();
    let pos_buf_len = 0 as c_uint;
    let pos_buf = hb_buffer_get_glyph_positions(hb_buffer, to_unsafe_ptr(&pos_buf_len));
    assert pos_buf.is_not_null();

    assert info_buf_len == pos_buf_len;

    for uint::range(0u, info_buf_len as uint) |i| { unsafe {
        let hb_info: hb_glyph_info_t = *offset(info_buf, i);
        let hb_pos: hb_glyph_position_t = *offset(pos_buf, i);
        let codepoint = hb_info.codepoint as GlyphIndex;
        let advance: au = au::from_frac_px(fixed_to_float_hb(hb_pos.x_advance));
        let offset = match (hb_pos.x_offset, hb_pos.y_offset) {
            (0, 0) => None,
            (x, y) => Some(Point2D(au::from_frac_px(fixed_to_float_hb(x)),
                                    au::from_frac_px(fixed_to_float_hb(y))))
        };
        // TODO: convert pos.y_advance into offset adjustment
        // TODO: handle multiple glyphs per char, ligatures, etc.
        // See Issue #
        debug!("glyph %?: index %?, advance %?, offset %?",
               i, codepoint, advance, offset);

        let data = GlyphData(codepoint, advance, offset, false, false, false);
        run.glyphs.add_glyph_for_index(i, &data);
    } /* unsafe */ }

    hb_buffer_destroy(hb_buffer);
    hb_font_funcs_destroy(funcs);
    hb_font_destroy(hb_font);
    hb_face_destroy(hb_face);
    hb_blob_destroy(face_blob);
}

extern fn glyph_func(_font: *hb_font_t,
                     font_data: *c_void,
                     unicode: hb_codepoint_t,
                     _variant_selector: hb_codepoint_t,
                     glyph: *mut hb_codepoint_t,
                     _user_data: *c_void) -> hb_bool_t unsafe {

    let font: *Font = font_data as *Font;
    assert font.is_not_null();
    return match (*font).glyph_index(unicode as char) {
        Some(g) => { *glyph = g as hb_codepoint_t; true },
        None => false
    } as hb_bool_t;
}

extern fn glyph_h_advance_func(_font: *hb_font_t,
                               font_data: *c_void,
                               glyph: hb_codepoint_t,
                               _user_data: *c_void) -> hb_position_t unsafe {
    let font: *Font = font_data as *Font;
    assert font.is_not_null();
    debug!("font_data = %?", font_data);

    let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
    float_to_fixed_hb(advance)
}
<commit_msg>Remove spurious debug statement<commit_after>extern mod harfbuzz;

use au = gfx::geometry;
use au::au;
use core::num::from_int;
use font::Font;
use font_cache::FontCache;
use geom::point::Point2D;
use glyph::{GlyphStore, GlyphIndex, GlyphData};
use libc::types::common::c99::int32_t;
use libc::{c_uint, c_int, c_void, c_char};
use ptr::{null, to_unsafe_ptr, offset};
use std::arc;
use text_run::TextRun;
use util::*;

use cast::reinterpret_cast;
use harfbuzz::{HB_MEMORY_MODE_READONLY,
                  HB_DIRECTION_LTR};
use harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t, hb_buffer_t,
                  hb_codepoint_t, hb_bool_t, hb_glyph_position_t,
		  hb_glyph_info_t, hb_var_int_t, hb_position_t};
use harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
                           hb_face_create, hb_face_destroy,
                           hb_font_create, hb_font_destroy,
                           hb_buffer_create, hb_buffer_destroy,
                           hb_buffer_add_utf8, hb_shape,
                           hb_buffer_get_glyph_infos,
                           hb_buffer_get_glyph_positions,
                           hb_font_set_ppem, hb_font_set_scale,
                           hb_buffer_set_direction,
                           hb_font_funcs_create, hb_font_funcs_destroy,
                           hb_font_set_funcs,
                           hb_font_funcs_set_glyph_h_advance_func,
                           hb_font_funcs_set_glyph_func,
                           hb_font_funcs_set_glyph_h_kerning_func};

fn float_to_fixed_hb(f: float) -> i32 {
    util::float_to_fixed(16, f)
}

fn fixed_to_float_hb(i: hb_position_t) -> float {
    util::fixed_to_float(16, i)
}

fn fixed_to_rounded_int_hb(f: hb_position_t) -> int {
    util::fixed_to_rounded_int(16, f)
}

/**
Calculate the layout metrics associated with a some given text
when rendered in a specific font.
*/
pub fn shape_textrun(run: &TextRun) {
    debug!("shaping text '%s'", run.text);

    // TODO: harfbuzz fonts and faces should be cached on the Font object.
    // TODO: font tables should be stored in Font object and cached by FontCache (Issue #92)
    let face_blob: *hb_blob_t = vec::as_imm_buf(*(run.font).fontbuf, |buf: *u8, len: uint| {
        hb_blob_create(buf as *c_char,
                       len as c_uint,
                       HB_MEMORY_MODE_READONLY,
                       null(),
                       null())
    });

    let hb_face: *hb_face_t = hb_face_create(face_blob, 0 as c_uint);
    let hb_font: *hb_font_t = hb_font_create(hb_face);

    // TODO: set font size here, based on Font's size
    // Set points-per-em. if zero, performs no hinting in that direction.
    hb_font_set_ppem(hb_font, 21 as c_uint, 21 as c_uint);
    // Set scaling. Note that this takes 16.16 fixed point.
    hb_font_set_scale(hb_font, float_to_fixed_hb(21f) as c_int, float_to_fixed_hb(21f) as c_int);

    let funcs: *hb_font_funcs_t = hb_font_funcs_create();
    hb_font_funcs_set_glyph_func(funcs, glyph_func, null(), null());
    hb_font_funcs_set_glyph_h_advance_func(funcs, glyph_h_advance_func, null(), null());

    unsafe {
        let font_data: *c_void = core::ptr::addr_of(run.font) as *c_void;
        hb_font_set_funcs(hb_font, funcs, font_data, null());
    };

    let hb_buffer: *hb_buffer_t = hb_buffer_create();
    hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);

    // Using as_buf because it never does a copy - we don't need the trailing null
    str::as_buf(run.text, |ctext: *u8, _l: uint| {
        hb_buffer_add_utf8(hb_buffer,
                           ctext as *c_char,
                           run.text.len() as c_int,
                           0 as c_uint,
                           run.text.len() as c_int);
    });

    hb_shape(hb_font, hb_buffer, null(), 0 as c_uint);

    let info_buf_len = 0 as c_uint;
    let info_buf = hb_buffer_get_glyph_infos(hb_buffer, to_unsafe_ptr(&info_buf_len));
    assert info_buf.is_not_null();
    let pos_buf_len = 0 as c_uint;
    let pos_buf = hb_buffer_get_glyph_positions(hb_buffer, to_unsafe_ptr(&pos_buf_len));
    assert pos_buf.is_not_null();

    assert info_buf_len == pos_buf_len;

    for uint::range(0u, info_buf_len as uint) |i| { unsafe {
        let hb_info: hb_glyph_info_t = *offset(info_buf, i);
        let hb_pos: hb_glyph_position_t = *offset(pos_buf, i);
        let codepoint = hb_info.codepoint as GlyphIndex;
        let advance: au = au::from_frac_px(fixed_to_float_hb(hb_pos.x_advance));
        let offset = match (hb_pos.x_offset, hb_pos.y_offset) {
            (0, 0) => None,
            (x, y) => Some(Point2D(au::from_frac_px(fixed_to_float_hb(x)),
                                    au::from_frac_px(fixed_to_float_hb(y))))
        };
        // TODO: convert pos.y_advance into offset adjustment
        // TODO: handle multiple glyphs per char, ligatures, etc.
        // See Issue #
        debug!("glyph %?: index %?, advance %?, offset %?",
               i, codepoint, advance, offset);

        let data = GlyphData(codepoint, advance, offset, false, false, false);
        run.glyphs.add_glyph_for_index(i, &data);
    } /* unsafe */ }

    hb_buffer_destroy(hb_buffer);
    hb_font_funcs_destroy(funcs);
    hb_font_destroy(hb_font);
    hb_face_destroy(hb_face);
    hb_blob_destroy(face_blob);
}

extern fn glyph_func(_font: *hb_font_t,
                     font_data: *c_void,
                     unicode: hb_codepoint_t,
                     _variant_selector: hb_codepoint_t,
                     glyph: *mut hb_codepoint_t,
                     _user_data: *c_void) -> hb_bool_t unsafe {

    let font: *Font = font_data as *Font;
    assert font.is_not_null();
    return match (*font).glyph_index(unicode as char) {
        Some(g) => { *glyph = g as hb_codepoint_t; true },
        None => false
    } as hb_bool_t;
}

extern fn glyph_h_advance_func(_font: *hb_font_t,
                               font_data: *c_void,
                               glyph: hb_codepoint_t,
                               _user_data: *c_void) -> hb_position_t unsafe {
    let font: *Font = font_data as *Font;
    assert font.is_not_null();

    let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
    float_to_fixed_hb(advance)
}
<|endoftext|>