<commit_before>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset: u4,
    reserved: u4,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOption>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    tcp.get_data_offset() as usize - 5
}

/// Represents the TCP Option field
#[packet]
pub struct TcpOption {
    #[payload]
    data: Vec<u8>
}

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

    const TCP_HEADER_LEN: usize = 20;
    const PAYLOAD_LEN: usize = 4;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::MutableIpv4Packet;
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
        let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        {
            let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_level_protocol(next_level_protocol);
            ip_header.set_source(ipv4_source);
            ip_header.set_destination(ipv4_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV4_HEADER_LEN..]);
    }

    #[test]
    fn tcp_header_ipv6_test() {
        use packet::ip::{IpNextHeaderProtocols};
        use packet::ipv6::{MutableIpv6Packet};
        use std::net::{Ipv6Addr};

        const IPV6_HEADER_LEN: usize = 40;

        let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let next_header = IpNextHeaderProtocols::Tcp;
        let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        {
            let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_header(next_header);
            ip_header.set_source(ipv6_source);
            ip_header.set_destination(ipv6_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV6_HEADER_LEN..]);
    }

    fn generate_tcp_and_payload(packet: &mut [u8]) {

        // Set data
        packet[TCP_HEADER_LEN + 0] = 't' as u8;
        packet[TCP_HEADER_LEN + 1] = 'e' as u8;
        packet[TCP_HEADER_LEN + 2] = 's' as u8;
        packet[TCP_HEADER_LEN + 3] = 't' as u8;

        {
            let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
            tcp_header.set_source(12345);
            assert_eq!(tcp_header.get_source(), 12345);

            tcp_header.set_destination(54321);
            assert_eq!(tcp_header.get_destination(), 54321);

            tcp_header.set_sequence(3456);
            assert_eq!(tcp_header.get_sequence(), 3456);

            tcp_header.set_acknowledgement(7799);
            assert_eq!(tcp_header.get_acknowledgement(), 7799);

            tcp_header.set_data_offset(0x5);
            assert_eq!(tcp_header.get_data_offset(), 0x5);

            tcp_header.set_control_bits(0x03);
            assert_eq!(tcp_header.get_control_bits(), 0x03);

            tcp_header.set_window(0x4566);
            assert_eq!(tcp_header.get_window(), 0x4566);

            tcp_header.set_checksum(0x6699);
            assert_eq!(tcp_header.get_checksum(), 0x6699);

            tcp_header.set_urgent_pointer(0x1122);
            assert_eq!(tcp_header.get_urgent_pointer(), 0x1122);
        }

        let ref_packet = [0x30, 0x39,  // source
                          0xd4, 0x31,  // destination
                          0x00, 0x00,  // sequence
                          0x0d, 0x80,
                          0x00, 0x00,  // acknowledgement
                          0x1e, 0x77,
                          0x50,        // header length + reserved
                          0x03,        // control bits
                          0x45, 0x66,  // window
                          0x66, 0x99,  // checksum
                          0x11, 0x22]; // urgent pointer
        assert_eq!(&ref_packet[..], &packet[.. TCP_HEADER_LEN]);
    }
}
<commit_msg>Add test for reserved portion of TCP header<commit_after>// Copyright (c) 2015 David Stainton <dstainton415@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! TCP packet abstraction

use pnet_macros::types::*;

/// Represents a TCP Packet
#[packet]
pub struct Tcp {
    source: u16be,
    destination: u16be,
    sequence: u32be,
    acknowledgement: u32be,
    data_offset: u4,
    reserved: u4,
    control_bits: u8,
    window: u16be,
    checksum: u16be,
    urgent_pointer: u16be,
    #[length_fn = "tcp_options_length"]
    options: Vec<TcpOption>,
    #[payload]
    payload: Vec<u8>
}

fn tcp_options_length<'a>(tcp: &TcpPacket<'a>) -> usize {
    /* The data offset field specifies the total size of the TCP header
       in 32-bit words. The minimum size of a TCP header is 20 bytes and thus
       TCP headers must have data offset set to 5 or more.
     */
    tcp.get_data_offset() as usize - 5
}

/// Represents the TCP Option field
#[packet]
pub struct TcpOption {
    #[payload]
    data: Vec<u8>
}

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

    const TCP_HEADER_LEN: usize = 20;
    const PAYLOAD_LEN: usize = 4;

    #[test]
    fn tcp_header_ipv4_test() {
        use pnet::packet::ip::IpNextHeaderProtocols;
        use pnet::packet::ipv4::MutableIpv4Packet;
        use std::net::{Ipv4Addr};

        const IPV4_HEADER_LEN: usize = 20;

        let mut packet = [0u8; IPV4_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let ipv4_source = Ipv4Addr::new(192, 168, 0, 1);
        let ipv4_destination = Ipv4Addr::new(192, 168, 0, 199);
        let next_level_protocol = IpNextHeaderProtocols::Tcp;
        {
            let mut ip_header = MutableIpv4Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_level_protocol(next_level_protocol);
            ip_header.set_source(ipv4_source);
            ip_header.set_destination(ipv4_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV4_HEADER_LEN..]);
    }

    #[test]
    fn tcp_header_ipv6_test() {
        use packet::ip::{IpNextHeaderProtocols};
        use packet::ipv6::{MutableIpv6Packet};
        use std::net::{Ipv6Addr};

        const IPV6_HEADER_LEN: usize = 40;

        let mut packet = [0u8; IPV6_HEADER_LEN + TCP_HEADER_LEN + PAYLOAD_LEN];
        let next_header = IpNextHeaderProtocols::Tcp;
        let ipv6_source = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        let ipv6_destination = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
        {
            let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
            ip_header.set_next_header(next_header);
            ip_header.set_source(ipv6_source);
            ip_header.set_destination(ipv6_destination);
        }

        generate_tcp_and_payload(&mut packet[IPV6_HEADER_LEN..]);
    }

    fn generate_tcp_and_payload(packet: &mut [u8]) {

        // Set data
        packet[TCP_HEADER_LEN + 0] = 't' as u8;
        packet[TCP_HEADER_LEN + 1] = 'e' as u8;
        packet[TCP_HEADER_LEN + 2] = 's' as u8;
        packet[TCP_HEADER_LEN + 3] = 't' as u8;

        {
            let mut tcp_header = MutableTcpPacket::new(&mut packet[..]).unwrap();
            tcp_header.set_source(12345);
            assert_eq!(tcp_header.get_source(), 12345);

            tcp_header.set_destination(54321);
            assert_eq!(tcp_header.get_destination(), 54321);

            tcp_header.set_sequence(3456);
            assert_eq!(tcp_header.get_sequence(), 3456);

            tcp_header.set_acknowledgement(7799);
            assert_eq!(tcp_header.get_acknowledgement(), 7799);

            tcp_header.set_data_offset(0x5);
            assert_eq!(tcp_header.get_data_offset(), 0x5);

            tcp_header.set_reserved(0x0);
            assert_eq!(tcp_header.get_reserved(), 0x0);

            tcp_header.set_control_bits(0x03);
            assert_eq!(tcp_header.get_control_bits(), 0x03);

            tcp_header.set_window(0x4566);
            assert_eq!(tcp_header.get_window(), 0x4566);

            tcp_header.set_checksum(0x6699);
            assert_eq!(tcp_header.get_checksum(), 0x6699);

            tcp_header.set_urgent_pointer(0x1122);
            assert_eq!(tcp_header.get_urgent_pointer(), 0x1122);
        }

        let ref_packet = [0x30, 0x39,  // source
                          0xd4, 0x31,  // destination
                          0x00, 0x00,  // sequence
                          0x0d, 0x80,
                          0x00, 0x00,  // acknowledgement
                          0x1e, 0x77,
                          0x50,        // header length + reserved
                          0x03,        // control bits
                          0x45, 0x66,  // window
                          0x66, 0x99,  // checksum
                          0x11, 0x22]; // urgent pointer
        assert_eq!(&ref_packet[..], &packet[.. TCP_HEADER_LEN]);
    }
}
<|endoftext|>


<commit_before>extern crate std;
use std::collections::HashMap;
use std::f64;

pub trait Node {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64>;
}

pub struct Num {
    pub num: f64
}

impl Node for Num {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        Some(self.num)
    }
}

pub struct Add {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Add {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l + r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Sub {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Sub {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l - r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Mul {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Mul {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l*r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Div {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Div {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l/r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Pow {
    pub base: Box<Node>,
    pub exponent: Box<Node>
}

impl Node for Pow {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.base.eval(env) {
            Some(b) => {
                match self.exponent.eval(env) {
                    Some(e) => Some(b.powf(e)),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Sin {
    pub arg: Box<Node>
}

impl Node for Sin {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.sin()),
            None => None
        }
    }
}
pub struct Cos {
    pub arg: Box<Node>
}

impl Node for Cos {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.cos()),
            None => None
        }
    }
}

pub struct Sqrt {
    pub arg: Box<Node>
}
impl Node for Sqrt {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.sqrt()),
            None => None
        }
    }
}

pub struct Print {
    pub arg: Box<Node>
}

impl Node for Print {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        let res = self.arg.eval(env);
        match res {
            Some(x) => println!("{}", x),
            None => {}
        }
        res
    }
}

pub struct Var {
    pub name: String
}

impl Node for Var {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match env.get(&(self.name)[..]) {
            Some(r) => Some(*r),
            None => None
        }
    }
}

pub struct Assignment {
    pub name: String,
    pub value: Box<Node>
}

impl Node for Assignment {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        let val = self.value.eval(env);
        match val {
            Some(x) => { env.insert(self.name.clone(), x); }
            None => {}
        }
        val
    }
}
<commit_msg>add underscore to silence unused argument<commit_after>extern crate std;
use std::collections::HashMap;
use std::f64;

pub trait Node {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64>;
}

pub struct Num {
    pub num: f64
}

impl Node for Num {
    fn eval(&self, _env: &mut HashMap<String, f64>) -> Option<f64> {
        Some(self.num)
    }
}

pub struct Add {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Add {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l + r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Sub {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Sub {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l - r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Mul {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Mul {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l*r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Div {
    pub left: Box<Node>,
    pub right: Box<Node>,
}

impl Node for Div {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.left.eval(env) {
            Some(l) => {
                match self.right.eval(env) {
                    Some(r) => Some(l/r),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Pow {
    pub base: Box<Node>,
    pub exponent: Box<Node>
}

impl Node for Pow {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.base.eval(env) {
            Some(b) => {
                match self.exponent.eval(env) {
                    Some(e) => Some(b.powf(e)),
                    None => None
                }
            }
            None => None
        }
    }
}

pub struct Sin {
    pub arg: Box<Node>
}

impl Node for Sin {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.sin()),
            None => None
        }
    }
}
pub struct Cos {
    pub arg: Box<Node>
}

impl Node for Cos {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.cos()),
            None => None
        }
    }
}

pub struct Sqrt {
    pub arg: Box<Node>
}
impl Node for Sqrt {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match self.arg.eval(env) {
            Some(x) => Some(x.sqrt()),
            None => None
        }
    }
}

pub struct Print {
    pub arg: Box<Node>
}

impl Node for Print {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        let res = self.arg.eval(env);
        match res {
            Some(x) => println!("{}", x),
            None => {}
        }
        res
    }
}

pub struct Var {
    pub name: String
}

impl Node for Var {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        match env.get(&(self.name)[..]) {
            Some(r) => Some(*r),
            None => None
        }
    }
}

pub struct Assignment {
    pub name: String,
    pub value: Box<Node>
}

impl Node for Assignment {
    fn eval(&self, env: &mut HashMap<String, f64>) -> Option<f64> {
        let val = self.value.eval(env);
        match val {
            Some(x) => { env.insert(self.name.clone(), x); }
            None => {}
        }
        val
    }
}
<|endoftext|>


<commit_before>use redox::Box;
use redox::fs::file::File;
use redox::io::{Read, Write, Seek, SeekFrom};
use redox::mem;
use redox::net::*;
use redox::ptr;
use redox::rand;
use redox::slice;
use redox::str;
use redox::{String, ToString};
use redox::to_num::*;
use redox::Vec;

#[derive(Copy, Clone)]
#[repr(packed)]
pub struct UDPHeader {
    pub src: n16,
    pub dst: n16,
    pub len: n16,
    pub checksum: Checksum,
}

pub struct UDP {
    pub header: UDPHeader,
    pub data: Vec<u8>,
}

impl FromBytes for UDP {
    fn from_bytes(bytes: Vec<u8>) -> Option<Self> {
        if bytes.len() >= mem::size_of::<UDPHeader>() {
            unsafe {
                return Option::Some(UDP {
                    header: ptr::read(bytes.as_ptr() as *const UDPHeader),
                    data: bytes[mem::size_of::<UDPHeader>().. bytes.len()].to_vec(),
                });
            }
        }
        Option::None
    }
}

impl ToBytes for UDP {
    fn to_bytes(&self) -> Vec<u8> {
        unsafe {
            let header_ptr: *const UDPHeader = &self.header;
            let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8, mem::size_of::<UDPHeader>()));
            ret.push_all(&self.data);
            ret
        }
    }
}

/// UDP resource
pub struct Resource {
    ip: File,
    data: Vec<u8>,
    peer_addr: IPv4Addr,
    peer_port: u16,
    host_port: u16,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Resource>> {
        match self.ip.dup() {
            Some(ip) => Some(box Resource {
                ip: ip,
                data: self.data.clone(),
                peer_addr: self.peer_addr,
                peer_port: self.peer_port,
                host_port: self.host_port,
            }),
            None => None
        }
    }

    pub fn path(&self, buf: &mut [u8]) -> Option<usize> {
        let path = format!("udp://{}:{}/{}", self.peer_addr.to_string(), self.peer_port, self.host_port);

        let mut i = 0;
        for b in path.bytes() {
            if i < buf.len() {
                buf[i] = b;
                i += 1;
            } else {
                break;
            }
        }

        Some(i)
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        /*

            if self.data.len() > 0 {
                let mut bytes: Vec<u8> = Vec::new();
                mem::swap(&mut self.data, &mut bytes);
                vec.push_all(&bytes);
                return Some(bytes.len());
            }

            loop {
                let mut bytes: Vec<u8> = Vec::new();
                match self.ip.read_to_end(&mut bytes) {
                    Some(_) => {
                        if let Some(datagram) = UDP::from_bytes(bytes) {
                            if datagram.header.dst.get() == self.host_port &&
                               datagram.header.src.get() == self.peer_port {
                                vec.push_all(&datagram.data);
                                return Some(datagram.data.len());
                            }
                        }
                    }
                    None => return None,
                }
            }
            */
        None
    }

    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let udp_data = Vec::from(buf);

        let mut udp = UDP {
            header: UDPHeader {
                src: n16::new(self.host_port),
                dst: n16::new(self.peer_port),
                len: n16::new((mem::size_of::<UDPHeader>() + udp_data.len()) as u16),
                checksum: Checksum { data: 0 },
            },
            data: udp_data,
        };

        unsafe {
            let proto = n16::new(0x11);
            let datagram_len = n16::new((mem::size_of::<UDPHeader>() + udp.data.len()) as u16);
            udp.header.checksum.data =
                Checksum::compile(Checksum::sum((&IP_ADDR as *const IPv4Addr) as usize,
                                                mem::size_of::<IPv4Addr>()) +
                                  Checksum::sum((&self.peer_addr as *const IPv4Addr) as usize,
                                                mem::size_of::<IPv4Addr>()) +
                                  Checksum::sum((&proto as *const n16) as usize,
                                                mem::size_of::<n16>()) +
                                  Checksum::sum((&datagram_len as *const n16) as usize,
                                                mem::size_of::<n16>()) +
                                  Checksum::sum((&udp.header as *const UDPHeader) as usize,
                                                mem::size_of::<UDPHeader>()) +
                                  Checksum::sum(udp.data.as_ptr() as usize, udp.data.len()));
        }

        match self.ip.write(udp.to_bytes().as_slice()) {
            Some(_) => return Some(buf.len()),
            None => return None,
        }
    }

    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        return None;
    }

    pub fn sync(&mut self) -> bool {
        self.ip.sync()
    }
}

/// UDP scheme
pub struct Scheme;

impl Scheme {
    pub fn new() -> Box<Self> {
        box Scheme
    }

    pub fn open(&mut self, url: &str) -> Option<Box<Resource>> {
        //Split scheme from the rest of the URL
        let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

        //Remove the starting two slashes
        if not_scheme.starts_with("//") {
            not_scheme = &not_scheme[2..not_scheme.len() - 2];
        }

        //Check host and port vs path
        if not_scheme.starts_with("/") {
            let host_port = not_scheme[1..not_scheme.len() - 1].to_string().to_num();
            if host_port > 0 && host_port < 65536 {
                if let Some(mut ip) = File::open("ip:///11") {
                    let mut bytes: Vec<u8> = Vec::new();
                    if ip.read_to_end(&mut bytes).is_some() {
                        if let Some(datagram) = UDP::from_bytes(bytes) {
                            if datagram.header.dst.get() as usize == host_port {
                                let mut url_bytes = [0; 4096];
                                if let Some(count) = ip.path(&mut url_bytes) {
                                    let url = unsafe { str::from_utf8_unchecked(&url_bytes[0..count]) };

                                    //Split scheme from the rest of the URL
                                    let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

                                    //Remove the starting two slashes
                                    if not_scheme.starts_with("//") {
                                        not_scheme = &not_scheme[2..not_scheme.len() - 2];
                                    }

                                    let (host, port) = not_scheme.split_at(not_scheme.find(':').unwrap_or(not_scheme.len()));

                                    let peer_addr = IPv4Addr::from_string(&host.to_string());

                                    return Some(box Resource {
                                        ip: ip,
                                        data: datagram.data,
                                        peer_addr: peer_addr,
                                        peer_port: datagram.header.src.get(),
                                        host_port: host_port as u16,
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }else{
            let (host, port) = not_scheme.split_at(not_scheme.find(':').unwrap_or(not_scheme.len()));

            let peer_port = port.to_string().to_num();
            if peer_port > 0 && peer_port < 65536 {
                let host_port = (rand() % 32768 + 32768) as u16;

                if let Some(ip) = File::open(&format!("ip://{}/11", host)) {
                    return Some(box Resource {
                        ip: ip,
                        data: Vec::new(),
                        peer_addr: IPv4Addr::from_string(&host.to_string()),
                        peer_port: peer_port as u16,
                        host_port: host_port,
                    });
                }
            }
        }

        None
    }
}
<commit_msg>For UDP scheme, return `Self` in `Resource::dup()` and remove unneeded return statements<commit_after>use redox::Box;
use redox::fs::file::File;
use redox::io::{Read, Write, Seek, SeekFrom};
use redox::mem;
use redox::net::*;
use redox::ptr;
use redox::rand;
use redox::slice;
use redox::str;
use redox::{String, ToString};
use redox::to_num::*;
use redox::Vec;

#[derive(Copy, Clone)]
#[repr(packed)]
pub struct UDPHeader {
    pub src: n16,
    pub dst: n16,
    pub len: n16,
    pub checksum: Checksum,
}

pub struct UDP {
    pub header: UDPHeader,
    pub data: Vec<u8>,
}

impl FromBytes for UDP {
    fn from_bytes(bytes: Vec<u8>) -> Option<Self> {
        if bytes.len() >= mem::size_of::<UDPHeader>() {
            unsafe {
                return Option::Some(UDP {
                    header: ptr::read(bytes.as_ptr() as *const UDPHeader),
                    data: bytes[mem::size_of::<UDPHeader>().. bytes.len()].to_vec(),
                });
            }
        }
        Option::None
    }
}

impl ToBytes for UDP {
    fn to_bytes(&self) -> Vec<u8> {
        unsafe {
            let header_ptr: *const UDPHeader = &self.header;
            let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8, mem::size_of::<UDPHeader>()));
            ret.push_all(&self.data);
            ret
        }
    }
}

/// UDP resource
pub struct Resource {
    ip: File,
    data: Vec<u8>,
    peer_addr: IPv4Addr,
    peer_port: u16,
    host_port: u16,
}

impl Resource {
    pub fn dup(&self) -> Option<Box<Self>> {
        match self.ip.dup() {
            Some(ip) => Some(box Resource {
                ip: ip,
                data: self.data.clone(),
                peer_addr: self.peer_addr,
                peer_port: self.peer_port,
                host_port: self.host_port,
            }),
            None => None
        }
    }

    pub fn path(&self, buf: &mut [u8]) -> Option<usize> {
        let path = format!("udp://{}:{}/{}", self.peer_addr.to_string(), self.peer_port, self.host_port);

        let mut i = 0;
        for b in path.bytes() {
            if i < buf.len() {
                buf[i] = b;
                i += 1;
            } else {
                break;
            }
        }

        Some(i)
    }

    pub fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        /*

            if self.data.len() > 0 {
                let mut bytes: Vec<u8> = Vec::new();
                mem::swap(&mut self.data, &mut bytes);
                vec.push_all(&bytes);
                return Some(bytes.len());
            }

            loop {
                let mut bytes: Vec<u8> = Vec::new();
                match self.ip.read_to_end(&mut bytes) {
                    Some(_) => {
                        if let Some(datagram) = UDP::from_bytes(bytes) {
                            if datagram.header.dst.get() == self.host_port &&
                               datagram.header.src.get() == self.peer_port {
                                vec.push_all(&datagram.data);
                                return Some(datagram.data.len());
                            }
                        }
                    }
                    None => return None,
                }
            }
            */
        None
    }

    pub fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let udp_data = Vec::from(buf);

        let mut udp = UDP {
            header: UDPHeader {
                src: n16::new(self.host_port),
                dst: n16::new(self.peer_port),
                len: n16::new((mem::size_of::<UDPHeader>() + udp_data.len()) as u16),
                checksum: Checksum { data: 0 },
            },
            data: udp_data,
        };

        unsafe {
            let proto = n16::new(0x11);
            let datagram_len = n16::new((mem::size_of::<UDPHeader>() + udp.data.len()) as u16);
            udp.header.checksum.data =
                Checksum::compile(Checksum::sum((&IP_ADDR as *const IPv4Addr) as usize,
                                                mem::size_of::<IPv4Addr>()) +
                                  Checksum::sum((&self.peer_addr as *const IPv4Addr) as usize,
                                                mem::size_of::<IPv4Addr>()) +
                                  Checksum::sum((&proto as *const n16) as usize,
                                                mem::size_of::<n16>()) +
                                  Checksum::sum((&datagram_len as *const n16) as usize,
                                                mem::size_of::<n16>()) +
                                  Checksum::sum((&udp.header as *const UDPHeader) as usize,
                                                mem::size_of::<UDPHeader>()) +
                                  Checksum::sum(udp.data.as_ptr() as usize, udp.data.len()));
        }

        match self.ip.write(udp.to_bytes().as_slice()) {
            Some(_) => return Some(buf.len()),
            None => return None,
        }
    }

    pub fn seek(&mut self, pos: SeekFrom) -> Option<usize> {
        None
    }

    pub fn sync(&mut self) -> bool {
        self.ip.sync()
    }
}

/// UDP scheme
pub struct Scheme;

impl Scheme {
    pub fn new() -> Box<Self> {
        box Scheme
    }

    pub fn open(&mut self, url: &str) -> Option<Box<Resource>> {
        //Split scheme from the rest of the URL
        let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

        //Remove the starting two slashes
        if not_scheme.starts_with("//") {
            not_scheme = &not_scheme[2..not_scheme.len() - 2];
        }

        //Check host and port vs path
        if not_scheme.starts_with("/") {
            let host_port = not_scheme[1..not_scheme.len() - 1].to_string().to_num();
            if host_port > 0 && host_port < 65536 {
                if let Some(mut ip) = File::open("ip:///11") {
                    let mut bytes: Vec<u8> = Vec::new();
                    if ip.read_to_end(&mut bytes).is_some() {
                        if let Some(datagram) = UDP::from_bytes(bytes) {
                            if datagram.header.dst.get() as usize == host_port {
                                let mut url_bytes = [0; 4096];
                                if let Some(count) = ip.path(&mut url_bytes) {
                                    let url = unsafe { str::from_utf8_unchecked(&url_bytes[0..count]) };

                                    //Split scheme from the rest of the URL
                                    let (scheme, mut not_scheme) = url.split_at(url.find(':').unwrap_or(url.len()));

                                    //Remove the starting two slashes
                                    if not_scheme.starts_with("//") {
                                        not_scheme = &not_scheme[2..not_scheme.len() - 2];
                                    }

                                    let (host, port) = not_scheme.split_at(not_scheme.find(':').unwrap_or(not_scheme.len()));

                                    let peer_addr = IPv4Addr::from_string(&host.to_string());

                                    return Some(box Resource {
                                        ip: ip,
                                        data: datagram.data,
                                        peer_addr: peer_addr,
                                        peer_port: datagram.header.src.get(),
                                        host_port: host_port as u16,
                                    });
                                }
                            }
                        }
                    }
                }
            }
        } else {
            let (host, port) = not_scheme.split_at(not_scheme.find(':').unwrap_or(not_scheme.len()));

            let peer_port = port.to_string().to_num();
            if peer_port > 0 && peer_port < 65536 {
                let host_port = (rand() % 32768 + 32768) as u16;

                if let Some(ip) = File::open(&format!("ip://{}/11", host)) {
                    return Some(box Resource {
                        ip: ip,
                        data: Vec::new(),
                        peer_addr: IPv4Addr::from_string(&host.to_string()),
                        peer_port: peer_port as u16,
                        host_port: host_port,
                    });
                }
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use crate::error::Result;

use crowbook_text_processing::escape;

#[cfg(feature="syntect")]
use syntect;

/// Wrapper around syntect, so it can be more easily optionally compiled.
#[cfg(feature="syntect")]
pub struct Syntax {
    syntax_set: syntect::parsing::SyntaxSet,
    theme: syntect::highlighting::Theme,
}

#[cfg(not(feature="syntect"))]
pub struct Syntax {}

#[cfg(feature="syntect")]
impl Syntax {
    /// Creates a new Syntax wrapper
    pub fn new(theme_name: &str) -> Syntax {
        let mut theme_set = syntect::highlighting::ThemeSet::load_defaults();
        let theme = match theme_set.themes.remove(theme_name) {
            Some(theme) => theme,
            None => {
                error!("{}", lformat!("could not set syntect theme to {theme}, defaulting to \"InspiredGithub\"",
                                           theme = theme_name));
                info!("{}", lformat!("valid theme names are: {themes}",
                                          themes = theme_set.themes
                                          .keys()
                                          .map(|s| s.to_owned())
                                          .collect::<Vec<_>>()
                                          .join(", ")));
                theme_set.themes.remove("InspiredGitHub").unwrap()
            }
        };
        Syntax {
            syntax_set: syntect::parsing::SyntaxSet::load_defaults_nonewlines(),
            theme: theme,
        }
    }

    /// Convert a string containing code to HTML
    pub fn to_html(&self, code: &str, language: &str) -> Result<String> {
        let language = strip_language(language);
        let syntax = self.syntax_set.find_syntax_by_name(language)
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
        let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme);
        let regions = h.highlight(code, &self.syntax_set);
        let bg = syntect::html::IncludeBackground::No;
        Ok(format!("
{}
",
                   syntect::html::styled_line_to_highlighted_html(&regions[..], bg)))
    }

    pub fn to_tex(&self, code: &str, language: &str) -> Result<String> {
        let language = strip_language(language);
        use crate::latex::insert_breaks;
        use syntect::highlighting::{Color, FontStyle};
        let syntax = self.syntax_set.find_syntax_by_name(language)
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
        let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme);
        let regions = h.highlight(code, &self.syntax_set);

        let mut result = String::with_capacity(code.len());
        for (style, text) in regions {
            let mut content = escape::tex(text).into_owned();
            content = insert_breaks(&content);
            content = content.replace('\n', "\\\\{}\n")
                .replace(' ', "\\hphantom{ }\\allowbreak{}");
            content = format!("\\texttt{{{}}}", content);
            if style.foreground != Color::BLACK {
                let r = style.foreground.r as f32 / 255.0;
                let g = style.foreground.g as f32 / 255.0;
                let b = style.foreground.b as f32 / 255.0;
                content = format!("\\textcolor[rgb]{{{r}, {g}, {b}}}{{{text}}}",
                                  r = r,
                                  g = g,
                                  b = b,
                                  text = content);
            }
            if style.font_style.contains(FontStyle::BOLD) {
                content = format!("\\textbf{{{}}}", content);
            }
            if style.font_style.contains(FontStyle::ITALIC) {
                content = format!("\\emph{{{}}}", content);
            }
            if style.font_style.contains(FontStyle::UNDERLINE) {
                content = format!("\\underline{{{}}}", content);
            }
            result.push_str(&content);
        }
        Ok(format!("{{\\sloppy {}}}", result))
    }
}

/// Strip language name of possible other infos, e.g. "rust,ignore" -> "rust"
/// Currently only ',' is done
fn strip_language(language: &str) -> &str {
    let splits: Vec<_> = language
        .split(|c: char| match c {
            ',' => true,
            _ => false
        })
        .collect();
    splits[0].trim()
}

#[cfg(not(feature="syntect"))]
impl Syntax {
    pub fn new( _: &str) -> Syntax {
        error!("{}", lformat!("crowbook was compiled without syntect support, syntax highlighting will be disabled"));
        Syntax {}
    }

    pub fn to_html(&self, code: &str, language: &str) -> Result<String> {
        Ok(format!("
{code}
",
                code = escape::html(code),
                lang = language))
    }

    pub fn to_tex(&self, code: &str, _: &str) -> Result<String> {
        Ok(format!("\\begin{{spverbatim}}{}\\end{{spverbatim}}\n",
                code))
    }
}
<commit_msg>Fix syntax highlighting<commit_after>// Copyright (C) 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use crate::error::Result;

use crowbook_text_processing::escape;

#[cfg(feature="syntect")]
use syntect;

/// Wrapper around syntect, so it can be more easily optionally compiled.
#[cfg(feature="syntect")]
pub struct Syntax {
    syntax_set: syntect::parsing::SyntaxSet,
    theme: syntect::highlighting::Theme,
}

#[cfg(not(feature="syntect"))]
pub struct Syntax {}

#[cfg(feature="syntect")]
impl Syntax {
    /// Creates a new Syntax wrapper
    pub fn new(theme_name: &str) -> Syntax {
        let mut theme_set = syntect::highlighting::ThemeSet::load_defaults();
        let theme = match theme_set.themes.remove(theme_name) {
            Some(theme) => theme,
            None => {
                error!("{}", lformat!("could not set syntect theme to {theme}, defaulting to \"InspiredGithub\"",
                                           theme = theme_name));
                info!("{}", lformat!("valid theme names are: {themes}",
                                          themes = theme_set.themes
                                          .keys()
                                          .map(|s| s.to_owned())
                                          .collect::<Vec<_>>()
                                          .join(", ")));
                theme_set.themes.remove("InspiredGitHub").unwrap()
            }
        };
        Syntax {
            syntax_set: syntect::parsing::SyntaxSet::load_defaults_nonewlines(),
            theme: theme,
        }
    }

    /// Convert a string containing code to HTML
    pub fn to_html(&self, code: &str, language: &str) -> Result<String> {
        let language = strip_language(language);
        let syntax = self.syntax_set.find_syntax_by_token(language)
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
        let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme);
        let regions = h.highlight(code, &self.syntax_set);
        let bg = syntect::html::IncludeBackground::No;
        Ok(format!("
{}
",
                   syntect::html::styled_line_to_highlighted_html(&regions[..], bg)))
    }

    pub fn to_tex(&self, code: &str, language: &str) -> Result<String> {
        let language = strip_language(language);
        use crate::latex::insert_breaks;
        use syntect::highlighting::{Color, FontStyle};
        let syntax = self.syntax_set.find_syntax_by_token(language)
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
        let mut h = syntect::easy::HighlightLines::new(syntax, &self.theme);
        let regions = h.highlight(code, &self.syntax_set);

        let mut result = String::with_capacity(code.len());
        for (style, text) in regions {
            let mut content = escape::tex(text).into_owned();
            content = insert_breaks(&content);
            content = content.replace('\n', "\\\\{}\n")
                .replace(' ', "\\hphantom{ }\\allowbreak{}");
            content = format!("\\texttt{{{}}}", content);
            if style.foreground != Color::BLACK {
                let r = style.foreground.r as f32 / 255.0;
                let g = style.foreground.g as f32 / 255.0;
                let b = style.foreground.b as f32 / 255.0;
                content = format!("\\textcolor[rgb]{{{r}, {g}, {b}}}{{{text}}}",
                                  r = r,
                                  g = g,
                                  b = b,
                                  text = content);
            }
            if style.font_style.contains(FontStyle::BOLD) {
                content = format!("\\textbf{{{}}}", content);
            }
            if style.font_style.contains(FontStyle::ITALIC) {
                content = format!("\\emph{{{}}}", content);
            }
            if style.font_style.contains(FontStyle::UNDERLINE) {
                content = format!("\\underline{{{}}}", content);
            }
            result.push_str(&content);
        }
        Ok(format!("{{\\sloppy {}}}", result))
    }
}

/// Strip language name of possible other infos, e.g. "rust,ignore" -> "rust"
/// Currently only ',' is done
fn strip_language(language: &str) -> &str {
    let splits: Vec<_> = language
        .split(|c: char| match c {
            ',' => true,
            _ => false
        })
        .collect();
    splits[0].trim()
}

#[cfg(not(feature="syntect"))]
impl Syntax {
    pub fn new( _: &str) -> Syntax {
        error!("{}", lformat!("crowbook was compiled without syntect support, syntax highlighting will be disabled"));
        Syntax {}
    }

    pub fn to_html(&self, code: &str, language: &str) -> Result<String> {
        Ok(format!("
{code}
",
                code = escape::html(code),
                lang = language))
    }

    pub fn to_tex(&self, code: &str, _: &str) -> Result<String> {
        Ok(format!("\\begin{{spverbatim}}{}\\end{{spverbatim}}\n",
                code))
    }
}
<|endoftext|>


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

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`kinds`](kinds/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an
//! array, lives in the [`vec`](vec/index.html) module. References to
//! arrays, `&[T]`, more commonly called "slices", are built-in types
//! for which the [`slice`](slice/index.html) module defines many
//! methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](from_str/index.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes modules for interoperating with the
//! C language: [`c_str`](c_str/index.html) and
//! [`c_vec`](c_vec/index.html).
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`task`](task/index.html) module contains Rust's threading abstractions,
//! while [`comm`](comm/index.html) contains the channel types for message
//! passing. [`sync`](sync/index.html) contains further, primitive, shared
//! memory types, including [`atomics`](sync/atomics/index.html).
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the [`io`](io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.

#![crate_name = "std"]
#![unstable]
#![comment = "The Rust standard library"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![allow(unknown_features)]
#![feature(macro_rules, globs, linkage)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
#![feature(import_shadowing, slicing_syntax)]

// Don't link to std. We are std.
#![no_std]

#![deny(missing_docs)]

#![reexport_test_harness_main = "test_main"]

#[cfg(test)] extern crate green;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

extern crate alloc;
extern crate unicode;
extern crate core;
extern crate "collections" as core_collections;
extern crate "rand" as core_rand;
extern crate "sync" as core_sync;
extern crate libc;
extern crate rustrt;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::kinds;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::bool;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
pub use core::finally;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::kinds;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::tuple;
// FIXME #15320: primitive documentation needs top-level modules, this
// should be `std::tuple::unit`.
pub use core::unit;
pub use core::result;
pub use core::option;

pub use alloc::boxed;

pub use alloc::rc;

pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;

pub use rustrt::c_str;
pub use rustrt::local_data;

pub use unicode::char;

pub use core_sync::comm;

/* Exported macros */

pub mod macros;
pub mod bitflags;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod rand;

pub mod ascii;

pub mod time;

/* Common traits */

pub mod from_str;
pub mod num;
pub mod to_string;

/* Common data structures */

pub mod collections;
pub mod hash;

/* Tasks and communication */

pub mod task;
pub mod sync;

/* Runtime and platform support */

pub mod c_vec;
pub mod dynamic_lib;
pub mod os;
pub mod io;
pub mod path;
pub mod fmt;

// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
pub mod rt;
mod failure;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    // mods used for deriving
    pub use clone;
    pub use cmp;
    pub use hash;

    pub use comm; // used for select!()
    pub use fmt; // used for any formatting strings
    pub use io; // used for println!()
    pub use local_data; // used for local_data_key!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]

    // The test runner calls ::std::os::args() but really wants realstd
    #[cfg(test)] pub use realstd::os as os;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<commit_msg>Fix dead link (s/task/thread/)<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`kinds`](kinds/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an
//! array, lives in the [`vec`](vec/index.html) module. References to
//! arrays, `&[T]`, more commonly called "slices", are built-in types
//! for which the [`slice`](slice/index.html) module defines many
//! methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](from_str/index.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes modules for interoperating with the
//! C language: [`c_str`](c_str/index.html) and
//! [`c_vec`](c_vec/index.html).
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`thread`](thread/index.html) module contains Rust's threading abstractions,
//! while [`comm`](comm/index.html) contains the channel types for message
//! passing. [`sync`](sync/index.html) contains further, primitive, shared
//! memory types, including [`atomics`](sync/atomics/index.html).
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the [`io`](io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.

#![crate_name = "std"]
#![unstable]
#![comment = "The Rust standard library"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![allow(unknown_features)]
#![feature(macro_rules, globs, linkage)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
#![feature(import_shadowing, slicing_syntax)]

// Don't link to std. We are std.
#![no_std]

#![deny(missing_docs)]

#![reexport_test_harness_main = "test_main"]

#[cfg(test)] extern crate green;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

extern crate alloc;
extern crate unicode;
extern crate core;
extern crate "collections" as core_collections;
extern crate "rand" as core_rand;
extern crate "sync" as core_sync;
extern crate libc;
extern crate rustrt;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::kinds;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::bool;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
pub use core::finally;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::kinds;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::tuple;
// FIXME #15320: primitive documentation needs top-level modules, this
// should be `std::tuple::unit`.
pub use core::unit;
pub use core::result;
pub use core::option;

pub use alloc::boxed;

pub use alloc::rc;

pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;

pub use rustrt::c_str;
pub use rustrt::local_data;

pub use unicode::char;

pub use core_sync::comm;

/* Exported macros */

pub mod macros;
pub mod bitflags;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

#[path = "num/float_macros.rs"] mod float_macros;
#[path = "num/int_macros.rs"]   mod int_macros;
#[path = "num/uint_macros.rs"]  mod uint_macros;

#[path = "num/int.rs"]  pub mod int;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/uint.rs"] pub mod uint;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod rand;

pub mod ascii;

pub mod time;

/* Common traits */

pub mod from_str;
pub mod num;
pub mod to_string;

/* Common data structures */

pub mod collections;
pub mod hash;

/* Tasks and communication */

pub mod task;
pub mod sync;

/* Runtime and platform support */

pub mod c_vec;
pub mod dynamic_lib;
pub mod os;
pub mod io;
pub mod path;
pub mod fmt;

// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
pub mod rt;
mod failure;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    // mods used for deriving
    pub use clone;
    pub use cmp;
    pub use hash;

    pub use comm; // used for select!()
    pub use fmt; // used for any formatting strings
    pub use io; // used for println!()
    pub use local_data; // used for local_data_key!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]

    // The test runner calls ::std::os::args() but really wants realstd
    #[cfg(test)] pub use realstd::os as os;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<|endoftext|>


<commit_before>use std::sync::mpsc::Receiver;
use std::sync::{Arc, Weak, RwLock};
use std::thread::Thread;
use subject::Subject;

/// Thread keeps internal subject alive
fn spawn_over<A, B, C, F>(source: Receiver<A>, subject: Weak<RwLock<B>>, keep_alive: Arc<RwLock<C>>, f: F)
    where F: Fn(&mut B, A) + Send,
          A: Send + Sync,
          B: Send + Sync,
          C: Send + Sync,
{
    Thread::spawn(move || {
        // This reference is only here to keep the subject observed by our
        // source alive, as long as this thread is running.
        let _ = keep_alive;
        for a in source.iter() {
            match subject.upgrade() {
                Some(subject) => f(&mut *subject.write().unwrap(), a),
                None => break,
            }
        }
    });
}

pub struct Event<A> {
    subject: Arc<RwLock<Subject<A>>>,
}

impl<A: Send + Sync + Clone> Event<A> {
    pub fn new() -> Event<A> {
        Event { subject: Arc::new(RwLock::new(Subject::new())) }
    }

    pub fn send(&self, a: A) {
        self.subject.write().unwrap().send(a);
    }

    pub fn listen(&self) -> Receiver<A> {
        self.subject.write().unwrap().listen()
    }

    fn spawn_over<B, F>(&self, subject: Weak<RwLock<B>>, f: F)
        where F: Fn(&mut B, A) + Send,
              B: Send + Sync,
    {
        spawn_over(self.listen(), subject, self.subject.clone(), f);
    }

    pub fn map<B: Send + Sync + Clone, F: Fn(A) -> B + Send>(&self, f: F) -> Event<B> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), move |mut subject, a| subject.send(f(a)));
        event
    }

    pub fn filter<F: Fn(&A) -> bool + Send>(&self, f: F) -> Event<A> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), move |mut subject, a| if f(&a) { subject.send(a) });
        event
    }

    /// Note: the specific order of the merge is not guaranteed to be consistent
    /// with the order, in which they were fired.
    pub fn merge(&self, other: &Event<A>) -> Event<A> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), |mut subject, a| subject.send(a));
        other.spawn_over(event.subject.downgrade(), |mut subject, a| subject.send(a));
        event
    }

    pub fn hold(&self, a: A) -> Behaviour<A> {
        Behaviour::hold(a, self)
    }
}

pub struct Behaviour<A> {
    state: Arc<RwLock<(A, Subject<A>)>>,
}

impl<A: Send + Sync + Clone> Behaviour<A> {
    pub fn constant(initial: A) -> Behaviour<A> {
        Behaviour {
            state: Arc::new(RwLock::new((initial, Subject::new())))
        }
    }

    pub fn hold(initial: A, event: &Event<A>) -> Behaviour<A> {
        let behaviour = Behaviour::constant(initial);
        event.spawn_over(
            behaviour.state.downgrade(),
            move |&mut (ref mut state, ref mut subject), a| {
                *state = a.clone();
                subject.send(a);
            }
        );
        behaviour
    }

    pub fn snapshot<B: Send + Sync + Clone>(&self, event: &Event<B>) -> Event<(A, B)> {
        let snap = Event::new();
        let b_state = self.state.clone();
        event.spawn_over(
            snap.subject.downgrade(),
            move |subject, a| {
                subject.send((b_state.read().unwrap().0.clone(), a))
            },
        );
        snap
    }

    pub fn sample(&self) -> A {
        self.state.read().unwrap().0.clone()
    }
}

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

    #[test]
    fn sink() {
        let sink = Event::new();
        let r = sink.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(1))
    }

    #[test]
    fn map() {
        let sink = Event::new();
        let triple = sink.map(|x| 3 * x);
        let r = triple.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn filter() {
        let sink: Event<i32> = Event::new();
        let positive = sink.filter(|&x| x > 0);
        let r = positive.listen();
        sink.send(-2);
        sink.send(3);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn merge() {
        let sink1 = Event::new();
        let sink2 = Event::new();
        let merge = sink1.merge(&sink2);
        let r = merge.listen();
        sink1.send(3);
        sink2.send(4);
        let result = (r.recv(), r.recv());
        // We cannot be certain about the ordering
        assert!((result == (Ok(3), Ok(4))) || (result == (Ok(4), Ok(3))));
    }

    #[test]
    fn snapshot() {
        let sink = Event::new();
        let behaviour = Event::new().hold(1);
        let snap = behaviour.snapshot(&sink);
        let r = snap.listen();
        sink.send(4);
        assert_eq!(r.recv(), Ok((1, 4)));
    }

    #[test]
    fn chain() {
        let sink: Event<i32> = Event::new();
        let chain = sink.map(|x| x + 2).filter(|&x| x > 10);
        let r = chain.listen();
        sink.send(9);
        assert_eq!(r.recv(), Ok(11));
    }

    #[test]
    fn chain_more() {
        let sink: Event<i32> = Event::new();
        let chain = sink
            .map(|x| x + 2)
            .filter(|&x| x > 10)
            .merge(&sink.filter(|&x| x < -3))
            .map(|x| x - 4);
        let r = chain.listen();
        sink.send(9);
        assert_eq!(r.recv(), Ok(7));
        sink.send(-5);
        assert_eq!(r.recv(), Ok(-9));
    }
}
<commit_msg>Test preservation of sink.send order<commit_after>use std::sync::mpsc::Receiver;
use std::sync::{Arc, Weak, RwLock};
use std::thread::Thread;
use subject::Subject;

/// Thread keeps internal subject alive
fn spawn_over<A, B, C, F>(source: Receiver<A>, subject: Weak<RwLock<B>>, keep_alive: Arc<RwLock<C>>, f: F)
    where F: Fn(&mut B, A) + Send,
          A: Send + Sync,
          B: Send + Sync,
          C: Send + Sync,
{
    Thread::spawn(move || {
        // This reference is only here to keep the subject observed by our
        // source alive, as long as this thread is running.
        let _ = keep_alive;
        for a in source.iter() {
            match subject.upgrade() {
                Some(subject) => f(&mut *subject.write().unwrap(), a),
                None => break,
            }
        }
    });
}

pub struct Event<A> {
    subject: Arc<RwLock<Subject<A>>>,
}

impl<A: Send + Sync + Clone> Event<A> {
    pub fn new() -> Event<A> {
        Event { subject: Arc::new(RwLock::new(Subject::new())) }
    }

    pub fn send(&self, a: A) {
        self.subject.write().unwrap().send(a);
    }

    pub fn listen(&self) -> Receiver<A> {
        self.subject.write().unwrap().listen()
    }

    fn spawn_over<B, F>(&self, subject: Weak<RwLock<B>>, f: F)
        where F: Fn(&mut B, A) + Send,
              B: Send + Sync,
    {
        spawn_over(self.listen(), subject, self.subject.clone(), f);
    }

    pub fn map<B: Send + Sync + Clone, F: Fn(A) -> B + Send>(&self, f: F) -> Event<B> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), move |mut subject, a| subject.send(f(a)));
        event
    }

    pub fn filter<F: Fn(&A) -> bool + Send>(&self, f: F) -> Event<A> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), move |mut subject, a| if f(&a) { subject.send(a) });
        event
    }

    /// Note: the specific order of the merge is not guaranteed to be consistent
    /// with the order, in which they were fired.
    pub fn merge(&self, other: &Event<A>) -> Event<A> {
        let event = Event::new();
        self.spawn_over(event.subject.downgrade(), |mut subject, a| subject.send(a));
        other.spawn_over(event.subject.downgrade(), |mut subject, a| subject.send(a));
        event
    }

    pub fn hold(&self, a: A) -> Behaviour<A> {
        Behaviour::hold(a, self)
    }
}

pub struct Behaviour<A> {
    state: Arc<RwLock<(A, Subject<A>)>>,
}

impl<A: Send + Sync + Clone> Behaviour<A> {
    pub fn constant(initial: A) -> Behaviour<A> {
        Behaviour {
            state: Arc::new(RwLock::new((initial, Subject::new())))
        }
    }

    pub fn hold(initial: A, event: &Event<A>) -> Behaviour<A> {
        let behaviour = Behaviour::constant(initial);
        event.spawn_over(
            behaviour.state.downgrade(),
            move |&mut (ref mut state, ref mut subject), a| {
                *state = a.clone();
                subject.send(a);
            }
        );
        behaviour
    }

    pub fn snapshot<B: Send + Sync + Clone>(&self, event: &Event<B>) -> Event<(A, B)> {
        let snap = Event::new();
        let b_state = self.state.clone();
        event.spawn_over(
            snap.subject.downgrade(),
            move |subject, a| {
                subject.send((b_state.read().unwrap().0.clone(), a))
            },
        );
        snap
    }

    pub fn sample(&self) -> A {
        self.state.read().unwrap().0.clone()
    }
}

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

    #[test]
    fn sink() {
        let sink = Event::new();
        let r = sink.listen();
        sink.send(1);
        sink.send(2);
        assert_eq!(r.recv(), Ok(1));
        assert_eq!(r.recv(), Ok(2));
    }

    #[test]
    fn map() {
        let sink = Event::new();
        let triple = sink.map(|x| 3 * x);
        let r = triple.listen();
        sink.send(1);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn filter() {
        let sink: Event<i32> = Event::new();
        let positive = sink.filter(|&x| x > 0);
        let r = positive.listen();
        sink.send(-2);
        sink.send(3);
        assert_eq!(r.recv(), Ok(3));
    }

    #[test]
    fn merge() {
        let sink1 = Event::new();
        let sink2 = Event::new();
        let merge = sink1.merge(&sink2);
        let r = merge.listen();
        sink1.send(3);
        sink2.send(4);
        let result = (r.recv(), r.recv());
        // We cannot be certain about the ordering
        assert!((result == (Ok(3), Ok(4))) || (result == (Ok(4), Ok(3))));
    }

    #[test]
    fn snapshot() {
        let sink = Event::new();
        let behaviour = Event::new().hold(1);
        let snap = behaviour.snapshot(&sink);
        let r = snap.listen();
        sink.send(4);
        assert_eq!(r.recv(), Ok((1, 4)));
    }

    #[test]
    fn chain() {
        let sink: Event<i32> = Event::new();
        let chain = sink.map(|x| x + 2).filter(|&x| x > 10);
        let r = chain.listen();
        sink.send(9);
        assert_eq!(r.recv(), Ok(11));
    }

    #[test]
    fn chain_more() {
        let sink: Event<i32> = Event::new();
        let chain = sink
            .map(|x| x + 2)
            .filter(|&x| x > 10)
            .merge(&sink.filter(|&x| x < -3))
            .map(|x| x - 4);
        let r = chain.listen();
        sink.send(9);
        assert_eq!(r.recv(), Ok(7));
        sink.send(-5);
        assert_eq!(r.recv(), Ok(-9));
    }
}
<|endoftext|>


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

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#[allow(missing_doc)]; // FIXME

use cast;
use ptr;
use unstable::intrinsics;
use unstable::intrinsics::{bswap16, bswap32, bswap64};

/// Returns the size of a type
#[inline]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to
#[inline]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the size of a type, or 1 if the actual size is zero.
///
/// Useful for building structures containing variable-length arrays.
#[inline]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size of the type of the value that `_val` points to
#[inline]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline]
pub fn pref_align_of<T>() -> uint {
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Create a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
/// which is unsafe unless T is Pod.
#[inline]
pub unsafe fn init<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
#[inline]
pub unsafe fn uninit<T>() -> T {
    intrinsics::uninit()
}

/// Move a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
#[inline]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
    intrinsics::move_val_init(dst, src)
}

#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be64(x: i64) -> i64 { x }

#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be64(x: i64) -> i64 { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninit();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(t);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
#[inline]
pub fn drop<T>(_x: T) { }

#[cfg(test)]
mod tests {
    use mem::*;
    use option::{Some,None};

    #[test]
    fn size_of_basic() {
        assert_eq!(size_of::<u8>(), 1u);
        assert_eq!(size_of::<u16>(), 2u);
        assert_eq!(size_of::<u32>(), 4u);
        assert_eq!(size_of::<u64>(), 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert_eq!(size_of::<uint>(), 4u);
        assert_eq!(size_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert_eq!(size_of::<uint>(), 8u);
        assert_eq!(size_of::<*uint>(), 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert_eq!(size_of::<Z>(), 0u);
        assert_eq!(nonzero_size_of::<Z>(), 1u);
        assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert_eq!(pref_align_of::<u8>(), 1u);
        assert_eq!(pref_align_of::<u16>(), 2u);
        assert_eq!(pref_align_of::<u32>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert_eq!(pref_align_of::<uint>(), 4u);
        assert_eq!(pref_align_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert_eq!(pref_align_of::<uint>(), 8u);
        assert_eq!(pref_align_of::<*uint>(), 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(~"test");
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }
}

/// Completely miscellaneous language-construct benchmarks.
#[cfg(test)]
mod bench {

    use extra::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method()
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method()
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            match x {
                Some(y) => y,
                None => 11
            }
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            match x {
                [1,2,3,..] => 10,
                _ => 11
            }
        });
    }
}
<commit_msg>Clarify unit of size in docs for size_of functions. Changed the docs in mem.rs to clarify the fact the the size functions return sizes in bytes.<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#[allow(missing_doc)]; // FIXME

use cast;
use ptr;
use unstable::intrinsics;
use unstable::intrinsics::{bswap16, bswap32, bswap64};

/// Returns the size of a type in bytes.
#[inline]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to in bytes.
#[inline]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the size of a type in bytes, or 1 if the actual size is zero.
///
/// Useful for building structures containing variable-length arrays.
#[inline]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size in bytes of the type of the value that `_val` points to.
#[inline]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline]
pub fn pref_align_of<T>() -> uint {
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Create a value initialized to zero.
///
/// `init` is unsafe because it returns a zeroed-out datum,
/// which is unsafe unless T is Pod.
#[inline]
pub unsafe fn init<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
#[inline]
pub unsafe fn uninit<T>() -> T {
    intrinsics::uninit()
}

/// Move a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
#[inline]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
    intrinsics::move_val_init(dst, src)
}

#[cfg(target_endian = "little")] #[inline] pub fn to_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn to_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn to_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn to_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn to_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn to_be64(x: i64) -> i64 { x }

#[cfg(target_endian = "little")] #[inline] pub fn from_le16(x: i16) -> i16 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le32(x: i32) -> i32 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "little")] #[inline] pub fn from_le64(x: i64) -> i64 { x }
#[cfg(target_endian = "big")]    #[inline] pub fn from_le64(x: i64) -> i64 { unsafe { bswap64(x) } }

#[cfg(target_endian = "little")] #[inline] pub fn from_be16(x: i16) -> i16 { unsafe { bswap16(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be16(x: i16) -> i16 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be32(x: i32) -> i32 { unsafe { bswap32(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be32(x: i32) -> i32 { x }
#[cfg(target_endian = "little")] #[inline] pub fn from_be64(x: i64) -> i64 { unsafe { bswap64(x) } }
#[cfg(target_endian = "big")]    #[inline] pub fn from_be64(x: i64) -> i64 { x }

/**
 * Swap the values at two mutable locations of the same type, without
 * deinitialising or copying either one.
 */
#[inline]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninit();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `tmp`
        // because it's no longer relevant.
        cast::forget(t);
    }
}

/**
 * Replace the value at a mutable location with a new one, returning the old
 * value, without deinitialising or copying either one.
 */
#[inline]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
#[inline]
pub fn drop<T>(_x: T) { }

#[cfg(test)]
mod tests {
    use mem::*;
    use option::{Some,None};

    #[test]
    fn size_of_basic() {
        assert_eq!(size_of::<u8>(), 1u);
        assert_eq!(size_of::<u16>(), 2u);
        assert_eq!(size_of::<u32>(), 4u);
        assert_eq!(size_of::<u64>(), 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert_eq!(size_of::<uint>(), 4u);
        assert_eq!(size_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert_eq!(size_of::<uint>(), 8u);
        assert_eq!(size_of::<*uint>(), 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert_eq!(size_of::<Z>(), 0u);
        assert_eq!(nonzero_size_of::<Z>(), 1u);
        assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert_eq!(pref_align_of::<u8>(), 1u);
        assert_eq!(pref_align_of::<u16>(), 2u);
        assert_eq!(pref_align_of::<u32>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert_eq!(pref_align_of::<uint>(), 4u);
        assert_eq!(pref_align_of::<*uint>(), 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert_eq!(pref_align_of::<uint>(), 8u);
        assert_eq!(pref_align_of::<*uint>(), 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn test_swap() {
        let mut x = 31337;
        let mut y = 42;
        swap(&mut x, &mut y);
        assert_eq!(x, 42);
        assert_eq!(y, 31337);
    }

    #[test]
    fn test_replace() {
        let mut x = Some(~"test");
        let y = replace(&mut x, None);
        assert!(x.is_none());
        assert!(y.is_some());
    }
}

/// Completely miscellaneous language-construct benchmarks.
#[cfg(test)]
mod bench {

    use extra::test::BenchHarness;
    use option::{Some,None};

    // Static/dynamic method dispatch

    struct Struct {
        field: int
    }

    trait Trait {
        fn method(&self) -> int;
    }

    impl Trait for Struct {
        fn method(&self) -> int {
            self.field
        }
    }

    #[bench]
    fn trait_vtable_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        let t = &s as &Trait;
        bh.iter(|| {
            t.method()
        });
    }

    #[bench]
    fn trait_static_method_call(bh: &mut BenchHarness) {
        let s = Struct { field: 10 };
        bh.iter(|| {
            s.method()
        });
    }

    // Overhead of various match forms

    #[bench]
    fn match_option_some(bh: &mut BenchHarness) {
        let x = Some(10);
        bh.iter(|| {
            match x {
                Some(y) => y,
                None => 11
            }
        });
    }

    #[bench]
    fn match_vec_pattern(bh: &mut BenchHarness) {
        let x = [1,2,3,4,5,6];
        bh.iter(|| {
            match x {
                [1,2,3,..] => 10,
                _ => 11
            }
        });
    }
}
<|endoftext|>