<commit_before>//! Provides functions to read and write segment registers.

#[cfg(docsrs)]
use crate::{registers::control::Cr4Flags, structures::gdt::GlobalDescriptorTable};
use crate::{
    registers::model_specific::{FsBase, GsBase, Msr},
    structures::gdt::SegmentSelector,
    VirtAddr,
};

/// An x86 segment
///
/// Segment registers on x86 are 16-bit [`SegmentSelector`]s, which index into
/// the [`GlobalDescriptorTable`]. The corresponding GDT entry is used to
/// configure the segment itself. Note that most segmentation functionality is
/// disabled in 64-bit mode. See the individual segments for more information.
pub trait Segment {
    /// Returns the current value of the segment register.
    fn get_reg() -> SegmentSelector;
    /// Reload the segment register. Depending on the segment, this may also
    /// reconfigure the corresponding segment.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that `sel`
    /// is a valid segment descriptor, and that reconfiguring the segment will
    /// not cause undefined behavior.
    unsafe fn set_reg(sel: SegmentSelector);
}

/// An x86 segment which is actually used in 64-bit mode
///
/// While most segments are unused in 64-bit mode, the FS and GS segments are
/// still partially used. Only the 64-bit segment base address is used, and this
/// address can be set via the GDT, or by using the `FSGSBASE` instructions.
pub trait Segment64: Segment {
    /// MSR containing the segment base. This MSR can be used to set the base
    /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is **not** set.
    const BASE: Msr;
    /// Reads the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    fn read_base() -> VirtAddr;
    /// Writes the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that this write operation has no unsafe side
    /// effects, as the segment base address might be in use.
    unsafe fn write_base(base: VirtAddr);
}

macro_rules! get_reg_impl {
    ($name:literal, $asm_get:ident) => {
        fn get_reg() -> SegmentSelector {
            let segment: u16;
            #[cfg(feature = "inline_asm")]
            unsafe {
                asm!(concat!("mov {0:x}, ", $name), out(reg) segment, options(nomem, nostack, preserves_flags));
            }
            #[cfg(not(feature = "inline_asm"))]
            unsafe {
                segment = crate::asm::$asm_get();
            }
            SegmentSelector(segment)
        }
    };
}

macro_rules! segment_impl {
    ($type:ty, $name:literal, $asm_get:ident, $asm_load:ident) => {
        impl Segment for $type {
            get_reg_impl!($name, $asm_get);

            unsafe fn set_reg(sel: SegmentSelector) {
                #[cfg(feature = "inline_asm")]
                asm!(concat!("mov ", $name, ", {0:x}"), in(reg) sel.0, options(nostack, preserves_flags));

                #[cfg(not(feature = "inline_asm"))]
                crate::asm::$asm_load(sel.0);
            }
        }
    };
}

macro_rules! segment64_impl {
    ($type:ty, $name:literal, $base:ty, $asm_rd:ident, $asm_wr:ident) => {
        impl Segment64 for $type {
            const BASE: Msr = <$base>::MSR;
            fn read_base() -> VirtAddr {
                #[cfg(feature = "inline_asm")]
                unsafe {
                    let val: u64;
                    asm!(concat!("rd", $name, "base {}"), out(reg) val, options(nomem, nostack, preserves_flags));
                    VirtAddr::new_unsafe(val)
                }
                #[cfg(not(feature = "inline_asm"))]
                unsafe {
                    VirtAddr::new_unsafe(crate::asm::$asm_rd())
                }
            }

            unsafe fn write_base(base: VirtAddr) {
                #[cfg(feature = "inline_asm")]
                asm!(concat!("wr", $name, "base {}"), in(reg) base.as_u64(), options(nostack, preserves_flags));

                #[cfg(not(feature = "inline_asm"))]
                crate::asm::$asm_wr(base.as_u64());
            }
        }
    };
}

/// Code Segment
///
/// The segment base and limit are unused in 64-bit mode. Only the L (long), D
/// (default operation size), and DPL (descriptor privilege-level) fields of the
/// descriptor are recognized. So changing the segment register can be used to
/// change privilege level or enable/disable long mode.
#[derive(Debug)]
pub struct CS;
impl Segment for CS {
    get_reg_impl!("cs", x86_64_asm_get_cs);

    /// Note this is special since we cannot directly move to [`CS`]. Instead we
    /// push the new segment selector and return value on the stack and use
    /// `retfq` to reload [`CS`] and continue at the end of our function.
    unsafe fn set_reg(sel: SegmentSelector) {
        #[cfg(feature = "inline_asm")]
        asm!(
            "push {sel}",
            "lea {tmp}, [1f + rip]",
            "push {tmp}",
            "retfq",
            "1:",
            sel = in(reg) u64::from(sel.0),
            tmp = lateout(reg) _,
            options(preserves_flags),
        );

        #[cfg(not(feature = "inline_asm"))]
        crate::asm::x86_64_asm_set_cs(u64::from(sel.0));
    }
}

/// Stack Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
/// However, this register is often set by the `syscall`/`sysret` and
/// `sysenter`/`sysexit` instructions (even on 64-bit transitions). This is to
/// maintain symmetry with 32-bit transitions where setting SS actually will
/// actually have an effect.
#[derive(Debug)]
pub struct SS;
segment_impl!(SS, "ss", x86_64_asm_get_ss, x86_64_asm_load_ss);

/// Data Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct DS;
segment_impl!(DS, "ds", x86_64_asm_get_ds, x86_64_asm_load_ds);

/// ES Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct ES;
segment_impl!(ES, "es", x86_64_asm_get_es, x86_64_asm_load_es);

/// FS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. This is often used in
/// user-mode for Thread-Local Storage (TLS).
#[derive(Debug)]
pub struct FS;
segment_impl!(FS, "fs", x86_64_asm_get_fs, x86_64_asm_load_fs);
segment64_impl!(FS, "fs", FsBase, x86_64_asm_rdfsbase, x86_64_asm_wrfsbase);

/// GS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. In kernel-mode, the GS
/// base often points to a per-cpu kernel data structure.
#[derive(Debug)]
pub struct GS;
segment_impl!(GS, "gs", x86_64_asm_get_gs, x86_64_asm_load_gs);
segment64_impl!(GS, "gs", GsBase, x86_64_asm_rdgsbase, x86_64_asm_wrgsbase);

impl GS {
    /// Swap `KernelGsBase` MSR and `GsBase` MSR.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that the
    /// swap operation cannot lead to undefined behavior.
    pub unsafe fn swap() {
        #[cfg(feature = "inline_asm")]
        asm!("swapgs", options(nostack, preserves_flags));

        #[cfg(not(feature = "inline_asm"))]
        crate::asm::x86_64_asm_swapgs();
    }
}

/// Alias for [`CS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `CS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn set_cs(sel: SegmentSelector) {
    CS::set_reg(sel)
}
/// Alias for [`SS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `SS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_ss(sel: SegmentSelector) {
    SS::set_reg(sel)
}
/// Alias for [`DS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `DS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_ds(sel: SegmentSelector) {
    DS::set_reg(sel)
}
/// Alias for [`ES::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `ES::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_es(sel: SegmentSelector) {
    ES::set_reg(sel)
}
/// Alias for [`FS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `FS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_fs(sel: SegmentSelector) {
    FS::set_reg(sel)
}
/// Alias for [`GS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `GS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_gs(sel: SegmentSelector) {
    GS::set_reg(sel)
}
/// Alias for [`GS::swap()`]
#[deprecated(since = "0.14.4", note = "use `GS::swap()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn swap_gs() {
    GS::swap()
}
/// Alias for [`CS::get_reg()`]
#[deprecated(since = "0.14.4", note = "use `CS::get_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub fn cs() -> SegmentSelector {
    CS::get_reg()
}
/// Alias for [`FS::write_base()`].
///
/// Panics if the provided address is non-canonical.
#[deprecated(since = "0.14.4", note = "use `FS::write_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn wrfsbase(val: u64) {
    FS::write_base(VirtAddr::new(val))
}
/// Alias for [`FS::read_base()`]
#[deprecated(since = "0.14.4", note = "use `FS::read_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn rdfsbase() -> u64 {
    FS::read_base().as_u64()
}
/// Alias for [`GS::write_base()`].
///
/// Panics if the provided address is non-canonical.
#[deprecated(since = "0.14.4", note = "use `GS::write_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn wrgsbase(val: u64) {
    GS::write_base(VirtAddr::new(val))
}
/// Alias for [`GS::read_base()`]
#[deprecated(since = "0.14.4", note = "use `GS::read_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn rdgsbase() -> u64 {
    GS::read_base().as_u64()
}
<commit_msg>Explain that SS must be set in Ring 3<commit_after>//! Provides functions to read and write segment registers.

#[cfg(docsrs)]
use crate::{
    registers::control::Cr4Flags,
    structures::gdt::{Descriptor, GlobalDescriptorTable},
};
use crate::{
    registers::model_specific::{FsBase, GsBase, Msr},
    structures::gdt::SegmentSelector,
    VirtAddr,
};

/// An x86 segment
///
/// Segment registers on x86 are 16-bit [`SegmentSelector`]s, which index into
/// the [`GlobalDescriptorTable`]. The corresponding GDT entry is used to
/// configure the segment itself. Note that most segmentation functionality is
/// disabled in 64-bit mode. See the individual segments for more information.
pub trait Segment {
    /// Returns the current value of the segment register.
    fn get_reg() -> SegmentSelector;
    /// Reload the segment register. Depending on the segment, this may also
    /// reconfigure the corresponding segment.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that `sel`
    /// is a valid segment descriptor, and that reconfiguring the segment will
    /// not cause undefined behavior.
    unsafe fn set_reg(sel: SegmentSelector);
}

/// An x86 segment which is actually used in 64-bit mode
///
/// While most segments are unused in 64-bit mode, the FS and GS segments are
/// still partially used. Only the 64-bit segment base address is used, and this
/// address can be set via the GDT, or by using the `FSGSBASE` instructions.
pub trait Segment64: Segment {
    /// MSR containing the segment base. This MSR can be used to set the base
    /// when [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is **not** set.
    const BASE: Msr;
    /// Reads the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    fn read_base() -> VirtAddr;
    /// Writes the segment base address
    ///
    /// ## Exceptions
    ///
    /// If [`CR4.FSGSBASE`][Cr4Flags::FSGSBASE] is not set, this instruction will throw a `#UD`.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that this write operation has no unsafe side
    /// effects, as the segment base address might be in use.
    unsafe fn write_base(base: VirtAddr);
}

macro_rules! get_reg_impl {
    ($name:literal, $asm_get:ident) => {
        fn get_reg() -> SegmentSelector {
            let segment: u16;
            #[cfg(feature = "inline_asm")]
            unsafe {
                asm!(concat!("mov {0:x}, ", $name), out(reg) segment, options(nomem, nostack, preserves_flags));
            }
            #[cfg(not(feature = "inline_asm"))]
            unsafe {
                segment = crate::asm::$asm_get();
            }
            SegmentSelector(segment)
        }
    };
}

macro_rules! segment_impl {
    ($type:ty, $name:literal, $asm_get:ident, $asm_load:ident) => {
        impl Segment for $type {
            get_reg_impl!($name, $asm_get);

            unsafe fn set_reg(sel: SegmentSelector) {
                #[cfg(feature = "inline_asm")]
                asm!(concat!("mov ", $name, ", {0:x}"), in(reg) sel.0, options(nostack, preserves_flags));

                #[cfg(not(feature = "inline_asm"))]
                crate::asm::$asm_load(sel.0);
            }
        }
    };
}

macro_rules! segment64_impl {
    ($type:ty, $name:literal, $base:ty, $asm_rd:ident, $asm_wr:ident) => {
        impl Segment64 for $type {
            const BASE: Msr = <$base>::MSR;
            fn read_base() -> VirtAddr {
                #[cfg(feature = "inline_asm")]
                unsafe {
                    let val: u64;
                    asm!(concat!("rd", $name, "base {}"), out(reg) val, options(nomem, nostack, preserves_flags));
                    VirtAddr::new_unsafe(val)
                }
                #[cfg(not(feature = "inline_asm"))]
                unsafe {
                    VirtAddr::new_unsafe(crate::asm::$asm_rd())
                }
            }

            unsafe fn write_base(base: VirtAddr) {
                #[cfg(feature = "inline_asm")]
                asm!(concat!("wr", $name, "base {}"), in(reg) base.as_u64(), options(nostack, preserves_flags));

                #[cfg(not(feature = "inline_asm"))]
                crate::asm::$asm_wr(base.as_u64());
            }
        }
    };
}

/// Code Segment
///
/// The segment base and limit are unused in 64-bit mode. Only the L (long), D
/// (default operation size), and DPL (descriptor privilege-level) fields of the
/// descriptor are recognized. So changing the segment register can be used to
/// change privilege level or enable/disable long mode.
#[derive(Debug)]
pub struct CS;
impl Segment for CS {
    get_reg_impl!("cs", x86_64_asm_get_cs);

    /// Note this is special since we cannot directly move to [`CS`]. Instead we
    /// push the new segment selector and return value on the stack and use
    /// `retfq` to reload [`CS`] and continue at the end of our function.
    unsafe fn set_reg(sel: SegmentSelector) {
        #[cfg(feature = "inline_asm")]
        asm!(
            "push {sel}",
            "lea {tmp}, [1f + rip]",
            "push {tmp}",
            "retfq",
            "1:",
            sel = in(reg) u64::from(sel.0),
            tmp = lateout(reg) _,
            options(preserves_flags),
        );

        #[cfg(not(feature = "inline_asm"))]
        crate::asm::x86_64_asm_set_cs(u64::from(sel.0));
    }
}

/// Stack Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
/// However, in ring 3, the SS register still has to point to a valid
/// [`Descriptor`] (it cannot be zero). This means a user-mode read/write
/// segment descriptor must be present in the GDT.
///
/// This register is also set by the `syscall`/`sysret` and
/// `sysenter`/`sysexit` instructions (even on 64-bit transitions). This is to
/// maintain symmetry with 32-bit transitions where setting SS actually will
/// actually have an effect.
#[derive(Debug)]
pub struct SS;
segment_impl!(SS, "ss", x86_64_asm_get_ss, x86_64_asm_load_ss);

/// Data Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct DS;
segment_impl!(DS, "ds", x86_64_asm_get_ds, x86_64_asm_load_ds);

/// ES Segment
///
/// Entirely unused in 64-bit mode; setting the segment register does nothing.
#[derive(Debug)]
pub struct ES;
segment_impl!(ES, "es", x86_64_asm_get_es, x86_64_asm_load_es);

/// FS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. This is often used in
/// user-mode for Thread-Local Storage (TLS).
#[derive(Debug)]
pub struct FS;
segment_impl!(FS, "fs", x86_64_asm_get_fs, x86_64_asm_load_fs);
segment64_impl!(FS, "fs", FsBase, x86_64_asm_rdfsbase, x86_64_asm_wrfsbase);

/// GS Segment
///
/// Only base is used in 64-bit mode, see [`Segment64`]. In kernel-mode, the GS
/// base often points to a per-cpu kernel data structure.
#[derive(Debug)]
pub struct GS;
segment_impl!(GS, "gs", x86_64_asm_get_gs, x86_64_asm_load_gs);
segment64_impl!(GS, "gs", GsBase, x86_64_asm_rdgsbase, x86_64_asm_wrgsbase);

impl GS {
    /// Swap `KernelGsBase` MSR and `GsBase` MSR.
    ///
    /// ## Safety
    ///
    /// This function is unsafe because the caller must ensure that the
    /// swap operation cannot lead to undefined behavior.
    pub unsafe fn swap() {
        #[cfg(feature = "inline_asm")]
        asm!("swapgs", options(nostack, preserves_flags));

        #[cfg(not(feature = "inline_asm"))]
        crate::asm::x86_64_asm_swapgs();
    }
}

/// Alias for [`CS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `CS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn set_cs(sel: SegmentSelector) {
    CS::set_reg(sel)
}
/// Alias for [`SS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `SS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_ss(sel: SegmentSelector) {
    SS::set_reg(sel)
}
/// Alias for [`DS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `DS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_ds(sel: SegmentSelector) {
    DS::set_reg(sel)
}
/// Alias for [`ES::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `ES::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_es(sel: SegmentSelector) {
    ES::set_reg(sel)
}
/// Alias for [`FS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `FS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_fs(sel: SegmentSelector) {
    FS::set_reg(sel)
}
/// Alias for [`GS::set_reg()`]
#[deprecated(since = "0.14.4", note = "use `GS::set_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn load_gs(sel: SegmentSelector) {
    GS::set_reg(sel)
}
/// Alias for [`GS::swap()`]
#[deprecated(since = "0.14.4", note = "use `GS::swap()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn swap_gs() {
    GS::swap()
}
/// Alias for [`CS::get_reg()`]
#[deprecated(since = "0.14.4", note = "use `CS::get_reg()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub fn cs() -> SegmentSelector {
    CS::get_reg()
}
/// Alias for [`FS::write_base()`].
///
/// Panics if the provided address is non-canonical.
#[deprecated(since = "0.14.4", note = "use `FS::write_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn wrfsbase(val: u64) {
    FS::write_base(VirtAddr::new(val))
}
/// Alias for [`FS::read_base()`]
#[deprecated(since = "0.14.4", note = "use `FS::read_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn rdfsbase() -> u64 {
    FS::read_base().as_u64()
}
/// Alias for [`GS::write_base()`].
///
/// Panics if the provided address is non-canonical.
#[deprecated(since = "0.14.4", note = "use `GS::write_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn wrgsbase(val: u64) {
    GS::write_base(VirtAddr::new(val))
}
/// Alias for [`GS::read_base()`]
#[deprecated(since = "0.14.4", note = "use `GS::read_base()` instead")]
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn rdgsbase() -> u64 {
    GS::read_base().as_u64()
}
<|endoftext|>


<commit_before>/*!

Things for the construction and sending of HTTP requests.

If you want to make a request, `RequestWriter::new` is where you start, and
`RequestWriter.read_response` is where you will send the request and read the response.

```rust
use http::client::RequestWriter;
use http::method::Get;

fn main() {
    let request = RequestWriter::new(Get, from_str("http://example.com/").unwrap());
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err((_request, error)) => fail!(":-( {}", error),
    };
    // Now you have a `ResponseReader`; see http::client::response for docs on that.
}
```

If you wish to send a request body (e.g. POST requests), I'm sorry to have to tell you that there is
not *good* support for this yet. However, it can be done; here is an example:

```rust
let data: &[u8];
let mut request: RequestWriter;

request.headers.content_length = Some(data.len());
request.write(data);
let response = match request.read_response() {
    Ok(response) => response,
    Err((_request, error)) => fail!(":-( {}", error),
};
```

*/

use url;
use url::Url;
use method::Method;
use std::io::{IoError, IoResult};
use std::io::net::get_host_addresses;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use buffer::BufferedStream;
use headers::request::HeaderCollection;
use headers::host::Host;
use connecter::Connecter;

use client::response::ResponseReader;

/*impl ResponseReader {
    {
        let mut buf = [0u8, ..2000];
        match stream.read(buf) {
            None => fail!("Read error :-("),  // conditions for error interception, again
            Some(bytes_read) => {
                println!(str::from_bytes(buf.slice_to(bytes_read)));
            }
        }

        match response {
            Some(response) => Ok(response),
            None => Err(self),
        }
    }
}*/

pub struct RequestWriter<S = super::NetworkStream> {
    // The place to write to (typically a network stream, which is
    // io::net::tcp::TcpStream or an SSL wrapper around that)
    stream: Option<BufferedStream<S>>,
    headers_written: bool,

    /// The originating IP address of the request.
    pub remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Host,  // Now headers.host

    /// The headers sent with the request.
    pub headers: Box<HeaderCollection>,

    /// The HTTP method for the request.
    pub method: Method,

    /// The URL being requested.
    pub url: Url,

    /// Should we use SSL?
    use_ssl: bool,
}

/// Low-level HTTP request writing support
///
/// Moderately hacky, and due to current limitations in the TcpStream arrangement reading cannot
/// take place until writing is completed.
///
/// At present, this only supports making one request per connection.
impl<S: Reader + Writer = super::NetworkStream> RequestWriter<S> {
    /// Create a `RequestWriter` writing to the specified location
    pub fn new(method: Method, url: Url) -> IoResult<RequestWriter<S>> {
        RequestWriter::new_request(method, url, false, true)
    }

    pub fn new_request(method: Method, url: Url, use_ssl: bool, auto_detect_ssl: bool) -> IoResult<RequestWriter<S>> {
        let host = match url.port {
            None => Host {
                name: url.host.clone(),
                port: None,
            },
            Some(p) => Host {
                name: url.host.clone(),
                port: Some(p),
            },
        };

        let remote_addr = try!(url_to_socket_addr(&url));
        info!("using ip address {}:{} for {}", remote_addr.ip, remote_addr.port, url.host.as_slice());

        fn url_to_socket_addr(url: &Url) -> IoResult<SocketAddr> {
            // Just grab the first IPv4 address
            let addrs = try!(get_host_addresses(url.host.as_slice()));
            let addr = addrs.move_iter().find(|&a| {
                match a {
                    Ipv4Addr(..) => true,
                    _ => false
                }
            });

            // TODO: Error handling
            let addr = addr.unwrap();

            // Default to 80, using the port specified or 443 if the protocol is HTTPS.
            let port = match url.port {
                Some(p) => p,
                // FIXME: case insensitivity?
                None => if url.scheme.as_slice() == "https" { 443 } else { 80 },
            };

            Ok(SocketAddr {
                ip: addr,
                port: port
            })
        }

        let mut request = RequestWriter {
            stream: None,
            headers_written: false,
            remote_addr: Some(remote_addr),
            headers: box HeaderCollection::new(),
            method: method,
            url: url,
            use_ssl: use_ssl,
        };

        if auto_detect_ssl {
            // FIXME: case insensitivity?
            request.use_ssl = request.url.scheme.as_slice() == "https";
        }

        request.headers.host = Some(host);
        Ok(request)
    }
}

impl<S: Connecter + Reader + Writer = super::NetworkStream> RequestWriter<S> {

    /// Connect to the remote host if not already connected.
    pub fn try_connect(&mut self) -> IoResult<()> {
        if self.stream.is_none() {
            self.connect()
        } else {
            Ok(())
        }
    }

    /// Connect to the remote host; fails if already connected.
    /// Returns ``true`` upon success and ``false`` upon failure (also use conditions).
    pub fn connect(&mut self) -> IoResult<()> {
        if !self.stream.is_none() {
            fail!("I don't think you meant to call connect() twice, you know.");
        }

        self.stream = match self.remote_addr {
            Some(addr) => {
                let stream = try!(Connecter::connect(addr, self.url.host.as_slice(), self.use_ssl));
                Some(BufferedStream::new(stream))
            },
            None => fail!("connect() called before remote_addr was set"),
        };
        Ok(())
    }

    /// Write the Request-Line and headers of the response, if we have not already done so.
    pub fn try_write_headers(&mut self) -> IoResult<()> {
        if !self.headers_written {
            self.write_headers()
        } else {
            Ok(())
        }
    }

    /// Write the Status-Line and headers of the response, in preparation for writing the body.
    ///
    /// If the headers have already been written, this will fail. See also `try_write_headers`.
    pub fn write_headers(&mut self) -> IoResult<()> {
        // This marks the beginning of the response (RFC2616 §5)
        if self.headers_written {
            fail!("RequestWriter.write_headers() called, but headers already written");
        }
        if self.stream.is_none() {
            try!(self.connect());
        }

        let ref path = self.url.path;

        // Write the Request-Line (RFC2616 §5.1)
        // TODO: get to the point where we can say HTTP/1.1 with good conscience
        try!(write!(self.stream.get_mut_ref() as &mut Writer,
            "{} {}{}{} HTTP/1.0\r\n",
            self.method,
            if path.path.len()  > 0 { path.path.as_slice() } else { "/" },
            if path.query.len() > 0 { "?" } else { "" },
            url::query_to_str(&path.query)));

        try!(self.headers.write_all(self.stream.get_mut_ref()));
        self.headers_written = true;
        Ok(())
    }

    /**
     * Send the request and construct a `ResponseReader` out of it.
     *
     * If the request sending fails in any way, a condition will be raised; if handled, the original
     * request will be returned as an `Err`.
     */
    pub fn read_response(mut self) -> Result<ResponseReader<S>, (RequestWriter<S>, IoError)> {
        match self.try_write_headers() {
            Ok(()) => (),
            Err(err) => return Err((self, err)),
        };
        match self.flush() {
            Ok(()) => (),
            Err(err) => return Err((self, err)),
        };
        match self.stream.take() {
            Some(stream) => ResponseReader::construct(stream, self),
            None => unreachable!(), // TODO: is it genuinely unreachable?
        }
    }
}

/// Write the request body. Note that any calls to `write()` will cause the headers to be sent.
impl<S: Reader + Writer + Connecter = super::NetworkStream> Writer for RequestWriter<S> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        if !self.headers_written {
            try!(self.write_headers());
        }
        // TODO: decide whether using get_mut_ref() is sound
        // (it will cause failure if None)
        self.stream.get_mut_ref().write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        // TODO: ditto
        self.stream.get_mut_ref().flush()
    }
}
<commit_msg>Use std's SocktAddr::fmt<commit_after>/*!

Things for the construction and sending of HTTP requests.

If you want to make a request, `RequestWriter::new` is where you start, and
`RequestWriter.read_response` is where you will send the request and read the response.

```rust
use http::client::RequestWriter;
use http::method::Get;

fn main() {
    let request = RequestWriter::new(Get, from_str("http://example.com/").unwrap());
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err((_request, error)) => fail!(":-( {}", error),
    };
    // Now you have a `ResponseReader`; see http::client::response for docs on that.
}
```

If you wish to send a request body (e.g. POST requests), I'm sorry to have to tell you that there is
not *good* support for this yet. However, it can be done; here is an example:

```rust
let data: &[u8];
let mut request: RequestWriter;

request.headers.content_length = Some(data.len());
request.write(data);
let response = match request.read_response() {
    Ok(response) => response,
    Err((_request, error)) => fail!(":-( {}", error),
};
```

*/

use url;
use url::Url;
use method::Method;
use std::io::{IoError, IoResult};
use std::io::net::get_host_addresses;
use std::io::net::ip::{SocketAddr, Ipv4Addr};
use buffer::BufferedStream;
use headers::request::HeaderCollection;
use headers::host::Host;
use connecter::Connecter;

use client::response::ResponseReader;

/*impl ResponseReader {
    {
        let mut buf = [0u8, ..2000];
        match stream.read(buf) {
            None => fail!("Read error :-("),  // conditions for error interception, again
            Some(bytes_read) => {
                println!(str::from_bytes(buf.slice_to(bytes_read)));
            }
        }

        match response {
            Some(response) => Ok(response),
            None => Err(self),
        }
    }
}*/

pub struct RequestWriter<S = super::NetworkStream> {
    // The place to write to (typically a network stream, which is
    // io::net::tcp::TcpStream or an SSL wrapper around that)
    stream: Option<BufferedStream<S>>,
    headers_written: bool,

    /// The originating IP address of the request.
    pub remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Host,  // Now headers.host

    /// The headers sent with the request.
    pub headers: Box<HeaderCollection>,

    /// The HTTP method for the request.
    pub method: Method,

    /// The URL being requested.
    pub url: Url,

    /// Should we use SSL?
    use_ssl: bool,
}

/// Low-level HTTP request writing support
///
/// Moderately hacky, and due to current limitations in the TcpStream arrangement reading cannot
/// take place until writing is completed.
///
/// At present, this only supports making one request per connection.
impl<S: Reader + Writer = super::NetworkStream> RequestWriter<S> {
    /// Create a `RequestWriter` writing to the specified location
    pub fn new(method: Method, url: Url) -> IoResult<RequestWriter<S>> {
        RequestWriter::new_request(method, url, false, true)
    }

    pub fn new_request(method: Method, url: Url, use_ssl: bool, auto_detect_ssl: bool) -> IoResult<RequestWriter<S>> {
        let host = match url.port {
            None => Host {
                name: url.host.clone(),
                port: None,
            },
            Some(p) => Host {
                name: url.host.clone(),
                port: Some(p),
            },
        };

        let remote_addr = try!(url_to_socket_addr(&url));
        info!("using ip address {} for {}", remote_addr, url.host.as_slice());

        fn url_to_socket_addr(url: &Url) -> IoResult<SocketAddr> {
            // Just grab the first IPv4 address
            let addrs = try!(get_host_addresses(url.host.as_slice()));
            let addr = addrs.move_iter().find(|&a| {
                match a {
                    Ipv4Addr(..) => true,
                    _ => false
                }
            });

            // TODO: Error handling
            let addr = addr.unwrap();

            // Default to 80, using the port specified or 443 if the protocol is HTTPS.
            let port = match url.port {
                Some(p) => p,
                // FIXME: case insensitivity?
                None => if url.scheme.as_slice() == "https" { 443 } else { 80 },
            };

            Ok(SocketAddr {
                ip: addr,
                port: port
            })
        }

        let mut request = RequestWriter {
            stream: None,
            headers_written: false,
            remote_addr: Some(remote_addr),
            headers: box HeaderCollection::new(),
            method: method,
            url: url,
            use_ssl: use_ssl,
        };

        if auto_detect_ssl {
            // FIXME: case insensitivity?
            request.use_ssl = request.url.scheme.as_slice() == "https";
        }

        request.headers.host = Some(host);
        Ok(request)
    }
}

impl<S: Connecter + Reader + Writer = super::NetworkStream> RequestWriter<S> {

    /// Connect to the remote host if not already connected.
    pub fn try_connect(&mut self) -> IoResult<()> {
        if self.stream.is_none() {
            self.connect()
        } else {
            Ok(())
        }
    }

    /// Connect to the remote host; fails if already connected.
    /// Returns ``true`` upon success and ``false`` upon failure (also use conditions).
    pub fn connect(&mut self) -> IoResult<()> {
        if !self.stream.is_none() {
            fail!("I don't think you meant to call connect() twice, you know.");
        }

        self.stream = match self.remote_addr {
            Some(addr) => {
                let stream = try!(Connecter::connect(addr, self.url.host.as_slice(), self.use_ssl));
                Some(BufferedStream::new(stream))
            },
            None => fail!("connect() called before remote_addr was set"),
        };
        Ok(())
    }

    /// Write the Request-Line and headers of the response, if we have not already done so.
    pub fn try_write_headers(&mut self) -> IoResult<()> {
        if !self.headers_written {
            self.write_headers()
        } else {
            Ok(())
        }
    }

    /// Write the Status-Line and headers of the response, in preparation for writing the body.
    ///
    /// If the headers have already been written, this will fail. See also `try_write_headers`.
    pub fn write_headers(&mut self) -> IoResult<()> {
        // This marks the beginning of the response (RFC2616 §5)
        if self.headers_written {
            fail!("RequestWriter.write_headers() called, but headers already written");
        }
        if self.stream.is_none() {
            try!(self.connect());
        }

        let ref path = self.url.path;

        // Write the Request-Line (RFC2616 §5.1)
        // TODO: get to the point where we can say HTTP/1.1 with good conscience
        try!(write!(self.stream.get_mut_ref() as &mut Writer,
            "{} {}{}{} HTTP/1.0\r\n",
            self.method,
            if path.path.len()  > 0 { path.path.as_slice() } else { "/" },
            if path.query.len() > 0 { "?" } else { "" },
            url::query_to_str(&path.query)));

        try!(self.headers.write_all(self.stream.get_mut_ref()));
        self.headers_written = true;
        Ok(())
    }

    /**
     * Send the request and construct a `ResponseReader` out of it.
     *
     * If the request sending fails in any way, a condition will be raised; if handled, the original
     * request will be returned as an `Err`.
     */
    pub fn read_response(mut self) -> Result<ResponseReader<S>, (RequestWriter<S>, IoError)> {
        match self.try_write_headers() {
            Ok(()) => (),
            Err(err) => return Err((self, err)),
        };
        match self.flush() {
            Ok(()) => (),
            Err(err) => return Err((self, err)),
        };
        match self.stream.take() {
            Some(stream) => ResponseReader::construct(stream, self),
            None => unreachable!(), // TODO: is it genuinely unreachable?
        }
    }
}

/// Write the request body. Note that any calls to `write()` will cause the headers to be sent.
impl<S: Reader + Writer + Connecter = super::NetworkStream> Writer for RequestWriter<S> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        if !self.headers_written {
            try!(self.write_headers());
        }
        // TODO: decide whether using get_mut_ref() is sound
        // (it will cause failure if None)
        self.stream.get_mut_ref().write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        // TODO: ditto
        self.stream.get_mut_ref().flush()
    }
}
<|endoftext|>


<commit_before>use super::common::Context;
use super::ast::*;
use super::tokens::{Number, Boolean, NodeImpl, Node, Operator};
use super::types::{Type, TypeTable};
use super::scope::ScopedTable;
use super::ident::Identifier;

use llvm;
use llvm::{Compile, ExecutionEngine};
use cbox::*;
use std::cell::{RefCell, RefMut};

const GLOBAL_INIT_FN_NAME: &'static str = "__global_init";

pub fn codegen<'a>(ctxt: &'a Context<'a>) {
    CodeGenerator::new(ctxt).codegen();
}

struct CodeGenerator<'a> {
    ctxt: &'a Context<'a>,
    types: RefMut<'a, TypeTable>,
    llvm: &'a llvm::Context,
    module: CSemiBox<'a, llvm::Module>,
    builder: CSemiBox<'a, llvm::Builder>,
    values: RefCell<ScopedTable<*const llvm::Value>>,
}

impl<'a> CodeGenerator<'a> {
    fn new(ctxt: &'a Context<'a>) -> CodeGenerator<'a> {
        CodeGenerator {
            ctxt: ctxt,
            types: ctxt.types.borrow_mut(),
            llvm: &ctxt.llvm,
            module: llvm::Module::new(&ctxt.filename, &ctxt.llvm),
            builder: llvm::Builder::new(&ctxt.llvm),
            values: RefCell::new(ScopedTable::new()),
        }
    }

    fn codegen(&self) {
        self.codegen_root(&self.ctxt.ast.borrow());

        println!("{:?}", self.module);
        self.module.verify().unwrap();

        {
            let func = self.module.get_function(GLOBAL_INIT_FN_NAME).unwrap();
            let ee = llvm::JitEngine::new(&self.module, llvm::JitOptions { opt_level: 0 }).unwrap();
            //let ee = llvm::Interpreter::new(&self.module, ()).unwrap();
            ee.with_function(func, |func: extern fn(())| {
                func(());
            });
        }
    }

    fn codegen_root(&self, root: &Root) {
        let unit_ty = llvm::Type::get::<()>(self.llvm);
        let init_fn = self.module.add_function(GLOBAL_INIT_FN_NAME,
                                               llvm::Type::new_function(unit_ty, &[]));
        //init_fn.add_attributes(&[llvm::Attribute::NoUnwind]);
        let block = init_fn.append("entry");
        self.builder.position_at_end(block);

        for item in root {
            match *item {
                Item::Assignment(ref x) => {
                    self.codegen_assignment(x, init_fn);
                },
                _ => { }
            }
        }

        self.builder.build_ret_void();
    }

    fn codegen_assignment(&self, assign: &Assignment, func: &llvm::Function) {
        let synt_ty = self.types.get_symbol(assign.ident()).unwrap().val;
        let ty = self.type_to_llvm(synt_ty);
        let name = &self.ctxt.lookup_name(assign.ident());
        let global = self.module.add_global_in_addr_space(name, ty, llvm::AddressSpace::Generic);
        global.set_initializer(self.default_for_type(synt_ty));
        //let init_fn = self.module.get_function(GLOBAL_INIT_FN_NAME)
            //.expect("global init fn should be been created in codegen()");
        //let block = init_fn.get_entry().unwrap();
        //self.builder.position_at_end(block);
        let val = self.codegen_expr(assign.expr(), func);
        self.builder.build_store(val, global);

        // hopefully there's some way to make this not use raw pointers.
        self.values.borrow_mut().set_val(assign.ident(), assign.ident_pos().index, global as *const llvm::Value);
    }

    fn codegen_expr(&self, expr: &Expression, func: &llvm::Function) -> &llvm::Value {
        match *expr {
            Expression::Constant(Node(v, _)) => v.compile(self.llvm),
            Expression::Boolean(Node(v, _)) => v.compile(self.llvm),
            Expression::Infix(ref v) => self.codegen_infix(v.item(), func),
            Expression::Prefix(ref v) => self.codegen_prefix(v.item(), func),
            Expression::Variable(ref v) => self.codegen_var(*v.item(), func),
            Expression::Conditional(ref v) => self.codegen_conditional(v.item(), func),
            Expression::Block(ref v) => self.codegen_block(v, func),
            _ => unimplemented!(),
        }
    }

    fn codegen_block(&self, block: &Node<Block>, func: &llvm::Function) -> &llvm::Value {
        self.values.borrow_mut().push(block.pos().index);
        let mut value = None;
        for stmnt in block.item() {
            match *stmnt {
                Statement::Assignment(ref v) => {
                    self.codegen_assignment(v, func);
                },
                Statement::Expression(ref v) => {
                    let expr = self.codegen_expr(v, func);
                    if expr.get_type().is_float() {
                        value = match value {
                            None => Some(expr),
                            Some(v) => Some(self.builder.build_add(v, expr)),
                        };
                    } else {
                        value = Some(expr);
                    }
                },
            }
        }
        self.values.borrow_mut().pop();
        value.unwrap()
    }

    fn codegen_var(&self, ident: Identifier, _: &llvm::Function) -> &llvm::Value {
        let values = self.values.borrow();
        let sym = values.get_symbol(ident).unwrap();
        self.builder.build_load(unsafe { &*sym.val })
    }

    fn codegen_conditional(&self, cond: &Conditional, func: &llvm::Function) -> &llvm::Value {
        let cond_val = self.codegen_expr(cond.cond(), func);
        let then_block = func.append("then");
        let else_block = func.append("else");
        self.builder.build_cond_br(cond_val, then_block, Some(else_block));

        let merge_block = func.append("merge");

        self.builder.position_at_end(then_block);
        let then_val = self.codegen_expr(cond.then(), func);
        self.builder.build_br(merge_block);
        let then_block = self.builder.get_position();

        self.builder.position_at_end(else_block);
        let else_val = self.codegen_expr(cond.els(), func);
        self.builder.build_br(merge_block);
        let else_block = self.builder.get_position();

        self.builder.position_at_end(merge_block);
        assert!(then_val.get_type() == else_val.get_type());
        let phi = self.builder.build_phi(then_val.get_type(), "iftmp");
        phi.add_incoming(then_val, then_block);
        phi.add_incoming(else_val, else_block);
        phi
    }

    fn codegen_infix(&self, infix: &Infix, func: &llvm::Function) -> &llvm::Value {
        let lhs = self.codegen_expr(infix.left(), func);
        let rhs = self.codegen_expr(infix.right(), func);
        match infix.op() {
            Operator::Add => self.builder.build_add(lhs, rhs),
            Operator::Sub => self.builder.build_sub(lhs, rhs),
            Operator::Mul => self.builder.build_mul(lhs, rhs),
            Operator::Div => self.builder.build_div(lhs, rhs),
            Operator::Less => self.builder.build_cmp(lhs, rhs, llvm::Predicate::LessThan),
            Operator::Greater => self.builder.build_cmp(lhs, rhs, llvm::Predicate::GreaterThan),
            Operator::LessEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::LessThanOrEqual),
            Operator::GreaterEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::GreaterThanOrEqual),
            Operator::Equal => self.builder.build_cmp(lhs, rhs, llvm::Predicate::Equal),
            Operator::NotEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::NotEqual),
            Operator::Or => self.builder.build_or(lhs, rhs),
            Operator::And => self.builder.build_and(lhs, rhs),
            Operator::Xor => unimplemented!(),
            _ => unreachable!(),
        }
    }

    fn codegen_prefix(&self, prefix: &Prefix, func: &llvm::Function) -> &llvm::Value {
        let expr = self.codegen_expr(prefix.expr(), func);
        match prefix.op() {
            Operator::Sub => self.builder.build_sub(0f32.compile(self.llvm), expr),
            Operator::Not => self.builder.build_not(expr),
            _ => unreachable!(),
        }
    }

    fn type_to_llvm(&self, ty: Type) -> &llvm::Type {
        match ty {
            Type::Number => llvm::Type::get::<Number>(self.llvm),
            Type::Boolean => llvm::Type::get::<Boolean>(self.llvm),
            _ => unimplemented!(),
        }
    }
    fn default_for_type(&self, ty: Type) -> &llvm::Value {
        match ty {
            Type::Number => 0f32.compile(self.llvm),
            Type::Boolean => false.compile(self.llvm),
            _ => unimplemented!(),
        }
    }
}

<commit_msg>Remove old commented out stuff<commit_after>use super::common::Context;
use super::ast::*;
use super::tokens::{Number, Boolean, NodeImpl, Node, Operator};
use super::types::{Type, TypeTable};
use super::scope::ScopedTable;
use super::ident::Identifier;

use llvm;
use llvm::{Compile, ExecutionEngine};
use cbox::*;
use std::cell::{RefCell, RefMut};

const GLOBAL_INIT_FN_NAME: &'static str = "__global_init";

pub fn codegen<'a>(ctxt: &'a Context<'a>) {
    CodeGenerator::new(ctxt).codegen();
}

struct CodeGenerator<'a> {
    ctxt: &'a Context<'a>,
    types: RefMut<'a, TypeTable>,
    llvm: &'a llvm::Context,
    module: CSemiBox<'a, llvm::Module>,
    builder: CSemiBox<'a, llvm::Builder>,
    values: RefCell<ScopedTable<*const llvm::Value>>,
}

impl<'a> CodeGenerator<'a> {
    fn new(ctxt: &'a Context<'a>) -> CodeGenerator<'a> {
        CodeGenerator {
            ctxt: ctxt,
            types: ctxt.types.borrow_mut(),
            llvm: &ctxt.llvm,
            module: llvm::Module::new(&ctxt.filename, &ctxt.llvm),
            builder: llvm::Builder::new(&ctxt.llvm),
            values: RefCell::new(ScopedTable::new()),
        }
    }

    fn codegen(&self) {
        self.codegen_root(&self.ctxt.ast.borrow());

        println!("{:?}", self.module);
        self.module.verify().unwrap();

        {
            let func = self.module.get_function(GLOBAL_INIT_FN_NAME).unwrap();
            let ee = llvm::JitEngine::new(&self.module, llvm::JitOptions { opt_level: 0 }).unwrap();
            //let ee = llvm::Interpreter::new(&self.module, ()).unwrap();
            ee.with_function(func, |func: extern fn(())| {
                func(());
            });
        }
    }

    fn codegen_root(&self, root: &Root) {
        let unit_ty = llvm::Type::get::<()>(self.llvm);
        let init_fn = self.module.add_function(GLOBAL_INIT_FN_NAME,
                                               llvm::Type::new_function(unit_ty, &[]));
        let block = init_fn.append("entry");
        self.builder.position_at_end(block);

        for item in root {
            match *item {
                Item::Assignment(ref x) => {
                    self.codegen_assignment(x, init_fn);
                },
                _ => { }
            }
        }

        self.builder.build_ret_void();
    }

    fn codegen_assignment(&self, assign: &Assignment, func: &llvm::Function) {
        let synt_ty = self.types.get_symbol(assign.ident()).unwrap().val;
        let ty = self.type_to_llvm(synt_ty);
        let name = &self.ctxt.lookup_name(assign.ident());
        let global = self.module.add_global_in_addr_space(name, ty, llvm::AddressSpace::Generic);
        global.set_initializer(self.default_for_type(synt_ty));
        let val = self.codegen_expr(assign.expr(), func);
        self.builder.build_store(val, global);

        // hopefully there's some way to make this not use raw pointers.
        self.values.borrow_mut().set_val(assign.ident(), assign.ident_pos().index, global as *const llvm::Value);
    }

    fn codegen_expr(&self, expr: &Expression, func: &llvm::Function) -> &llvm::Value {
        match *expr {
            Expression::Constant(Node(v, _)) => v.compile(self.llvm),
            Expression::Boolean(Node(v, _)) => v.compile(self.llvm),
            Expression::Infix(ref v) => self.codegen_infix(v.item(), func),
            Expression::Prefix(ref v) => self.codegen_prefix(v.item(), func),
            Expression::Variable(ref v) => self.codegen_var(*v.item(), func),
            Expression::Conditional(ref v) => self.codegen_conditional(v.item(), func),
            Expression::Block(ref v) => self.codegen_block(v, func),
            _ => unimplemented!(),
        }
    }

    fn codegen_block(&self, block: &Node<Block>, func: &llvm::Function) -> &llvm::Value {
        self.values.borrow_mut().push(block.pos().index);
        let mut value = None;
        for stmnt in block.item() {
            match *stmnt {
                Statement::Assignment(ref v) => {
                    self.codegen_assignment(v, func);
                },
                Statement::Expression(ref v) => {
                    let expr = self.codegen_expr(v, func);
                    if expr.get_type().is_float() {
                        value = match value {
                            None => Some(expr),
                            Some(v) => Some(self.builder.build_add(v, expr)),
                        };
                    } else {
                        value = Some(expr);
                    }
                },
            }
        }
        self.values.borrow_mut().pop();
        value.unwrap()
    }

    fn codegen_var(&self, ident: Identifier, _: &llvm::Function) -> &llvm::Value {
        let values = self.values.borrow();
        let sym = values.get_symbol(ident).unwrap();
        self.builder.build_load(unsafe { &*sym.val })
    }

    fn codegen_conditional(&self, cond: &Conditional, func: &llvm::Function) -> &llvm::Value {
        let cond_val = self.codegen_expr(cond.cond(), func);
        let then_block = func.append("then");
        let else_block = func.append("else");
        self.builder.build_cond_br(cond_val, then_block, Some(else_block));

        let merge_block = func.append("merge");

        self.builder.position_at_end(then_block);
        let then_val = self.codegen_expr(cond.then(), func);
        self.builder.build_br(merge_block);
        let then_block = self.builder.get_position();

        self.builder.position_at_end(else_block);
        let else_val = self.codegen_expr(cond.els(), func);
        self.builder.build_br(merge_block);
        let else_block = self.builder.get_position();

        self.builder.position_at_end(merge_block);
        assert!(then_val.get_type() == else_val.get_type());
        let phi = self.builder.build_phi(then_val.get_type(), "iftmp");
        phi.add_incoming(then_val, then_block);
        phi.add_incoming(else_val, else_block);
        phi
    }

    fn codegen_infix(&self, infix: &Infix, func: &llvm::Function) -> &llvm::Value {
        let lhs = self.codegen_expr(infix.left(), func);
        let rhs = self.codegen_expr(infix.right(), func);
        match infix.op() {
            Operator::Add => self.builder.build_add(lhs, rhs),
            Operator::Sub => self.builder.build_sub(lhs, rhs),
            Operator::Mul => self.builder.build_mul(lhs, rhs),
            Operator::Div => self.builder.build_div(lhs, rhs),
            Operator::Less => self.builder.build_cmp(lhs, rhs, llvm::Predicate::LessThan),
            Operator::Greater => self.builder.build_cmp(lhs, rhs, llvm::Predicate::GreaterThan),
            Operator::LessEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::LessThanOrEqual),
            Operator::GreaterEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::GreaterThanOrEqual),
            Operator::Equal => self.builder.build_cmp(lhs, rhs, llvm::Predicate::Equal),
            Operator::NotEqual => self.builder.build_cmp(lhs, rhs, llvm::Predicate::NotEqual),
            Operator::Or => self.builder.build_or(lhs, rhs),
            Operator::And => self.builder.build_and(lhs, rhs),
            Operator::Xor => unimplemented!(),
            _ => unreachable!(),
        }
    }

    fn codegen_prefix(&self, prefix: &Prefix, func: &llvm::Function) -> &llvm::Value {
        let expr = self.codegen_expr(prefix.expr(), func);
        match prefix.op() {
            Operator::Sub => self.builder.build_sub(0f32.compile(self.llvm), expr),
            Operator::Not => self.builder.build_not(expr),
            _ => unreachable!(),
        }
    }

    fn type_to_llvm(&self, ty: Type) -> &llvm::Type {
        match ty {
            Type::Number => llvm::Type::get::<Number>(self.llvm),
            Type::Boolean => llvm::Type::get::<Boolean>(self.llvm),
            _ => unimplemented!(),
        }
    }
    fn default_for_type(&self, ty: Type) -> &llvm::Value {
        match ty {
            Type::Number => 0f32.compile(self.llvm),
            Type::Boolean => false.compile(self.llvm),
            _ => unimplemented!(),
        }
    }
}

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

//! Generic hashing support.
//!
//! This module provides a generic way to compute the hash of a value. The
//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
//!
//! # Examples
//!
//! ```rust
//! use std::hash::{hash, Hash, SipHasher};
//!
//! #[derive(Hash)]
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
//! ```
//!
//! If you need more control over how a value is hashed, you need to implement
//! the trait `Hash`:
//!
//! ```rust
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! impl Hash for Person {
//!     fn hash<H: Hasher>(&self, state: &mut H) {
//!         self.id.hash(state);
//!         self.phone.hash(state);
//!     }
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;

use default::Default;
use mem;

pub use self::sip::SipHasher;

mod sip;

/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
    /// Feeds this value into the state given, updating the hasher as necessary.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
        for piece in data {
            piece.hash(state);
        }
    }
}

/// A trait which represents the ability to hash an arbitrary stream of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
    /// Completes a round of hashing, producing the output hash generated.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn finish(&self) -> u64;

    /// Writes some data into this `Hasher`
    #[stable(feature = "rust1", since = "1.0.0")]
    fn write(&mut self, bytes: &[u8]);

    /// Write a single `u8` into this hasher
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u8(&mut self, i: u8) { self.write(&[i]) }
    /// Write a single `u16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u16(&mut self, i: u16) {
        self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
    }
    /// Write a single `u32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u32(&mut self, i: u32) {
        self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
    }
    /// Write a single `u64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u64(&mut self, i: u64) {
        self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
    }
    /// Write a single `usize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_usize(&mut self, i: usize) {
        if cfg!(target_pointer_width = "32") {
            self.write_u32(i as u32)
        } else {
            self.write_u64(i as u64)
        }
    }

    /// Write a single `i8` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
    /// Write a single `i16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
    /// Write a single `i32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
    /// Write a single `i64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
    /// Write a single `isize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
}

/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[unstable(feature = "hash", reason = "module was recently redesigned")]
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
    let mut h: H = Default::default();
    value.hash(&mut h);
    h.finish()
}

//////////////////////////////////////////////////////////////////////////////

mod impls {
    use prelude::*;

    use slice;
    use super::*;

    macro_rules! impl_write {
        ($(($ty:ident, $meth:ident),)*) => {$(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for $ty {
                fn hash<H: Hasher>(&self, state: &mut H) {
                    state.$meth(*self)
                }

                fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
                    let newlen = data.len() * ::$ty::BYTES as usize;
                    let ptr = data.as_ptr() as *const u8;
                    state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
                }
            }
        )*}
    }

    impl_write! {
        (u8, write_u8),
        (u16, write_u16),
        (u32, write_u32),
        (u64, write_u64),
        (usize, write_usize),
        (i8, write_i8),
        (i16, write_i16),
        (i32, write_i32),
        (i64, write_i64),
        (isize, write_isize),
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for bool {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u8(*self as u8)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for char {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u32(*self as u32)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for str {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write(self.as_bytes());
            state.write_u8(0xff)
        }
    }

    macro_rules! impl_hash_tuple {
        () => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for () {
                fn hash<H: Hasher>(&self, _state: &mut H) {}
            }
        );

        ( $($name:ident)+) => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<$($name: Hash),*> Hash for ($($name,)*) {
                #[allow(non_snake_case)]
                fn hash<S: Hasher>(&self, state: &mut S) {
                    let ($(ref $name,)*) = *self;
                    $($name.hash(state);)*
                }
            }
        );
    }

    impl_hash_tuple! {}
    impl_hash_tuple! { A }
    impl_hash_tuple! { A B }
    impl_hash_tuple! { A B C }
    impl_hash_tuple! { A B C D }
    impl_hash_tuple! { A B C D E }
    impl_hash_tuple! { A B C D E F }
    impl_hash_tuple! { A B C D E F G }
    impl_hash_tuple! { A B C D E F G H }
    impl_hash_tuple! { A B C D E F G H I }
    impl_hash_tuple! { A B C D E F G H I J }
    impl_hash_tuple! { A B C D E F G H I J K }
    impl_hash_tuple! { A B C D E F G H I J K L }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: Hash> Hash for [T] {
        fn hash<H: Hasher>(&self, state: &mut H) {
            self.len().hash(state);
            Hash::hash_slice(self, state)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *const T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }
}
<commit_msg>std: Stabilize the `Hasher::finish` method<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.

//! Generic hashing support.
//!
//! This module provides a generic way to compute the hash of a value. The
//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
//!
//! # Examples
//!
//! ```rust
//! use std::hash::{hash, Hash, SipHasher};
//!
//! #[derive(Hash)]
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
//! ```
//!
//! If you need more control over how a value is hashed, you need to implement
//! the trait `Hash`:
//!
//! ```rust
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//!     id: u32,
//!     name: String,
//!     phone: u64,
//! }
//!
//! impl Hash for Person {
//!     fn hash<H: Hasher>(&self, state: &mut H) {
//!         self.id.hash(state);
//!         self.phone.hash(state);
//!     }
//! }
//!
//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
//!
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;

use default::Default;
use mem;

pub use self::sip::SipHasher;

mod sip;

/// A hashable type.
///
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
    /// Feeds this value into the state given, updating the hasher as necessary.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn hash<H: Hasher>(&self, state: &mut H);

    /// Feeds a slice of this type into the state provided.
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
        for piece in data {
            piece.hash(state);
        }
    }
}

/// A trait which represents the ability to hash an arbitrary stream of bytes.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
    /// Completes a round of hashing, producing the output hash generated.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn finish(&self) -> u64;

    /// Writes some data into this `Hasher`
    #[stable(feature = "rust1", since = "1.0.0")]
    fn write(&mut self, bytes: &[u8]);

    /// Write a single `u8` into this hasher
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u8(&mut self, i: u8) { self.write(&[i]) }
    /// Write a single `u16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u16(&mut self, i: u16) {
        self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
    }
    /// Write a single `u32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u32(&mut self, i: u32) {
        self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
    }
    /// Write a single `u64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_u64(&mut self, i: u64) {
        self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
    }
    /// Write a single `usize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_usize(&mut self, i: usize) {
        if cfg!(target_pointer_width = "32") {
            self.write_u32(i as u32)
        } else {
            self.write_u64(i as u64)
        }
    }

    /// Write a single `i8` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
    /// Write a single `i16` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
    /// Write a single `i32` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
    /// Write a single `i64` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
    /// Write a single `isize` into this hasher.
    #[inline]
    #[unstable(feature = "hash", reason = "module was recently redesigned")]
    fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
}

/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
///
/// The specified value will be hashed with this hasher and then the resulting
/// hash will be returned.
#[unstable(feature = "hash", reason = "module was recently redesigned")]
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
    let mut h: H = Default::default();
    value.hash(&mut h);
    h.finish()
}

//////////////////////////////////////////////////////////////////////////////

mod impls {
    use prelude::*;

    use slice;
    use super::*;

    macro_rules! impl_write {
        ($(($ty:ident, $meth:ident),)*) => {$(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for $ty {
                fn hash<H: Hasher>(&self, state: &mut H) {
                    state.$meth(*self)
                }

                fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
                    let newlen = data.len() * ::$ty::BYTES as usize;
                    let ptr = data.as_ptr() as *const u8;
                    state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
                }
            }
        )*}
    }

    impl_write! {
        (u8, write_u8),
        (u16, write_u16),
        (u32, write_u32),
        (u64, write_u64),
        (usize, write_usize),
        (i8, write_i8),
        (i16, write_i16),
        (i32, write_i32),
        (i64, write_i64),
        (isize, write_isize),
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for bool {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u8(*self as u8)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for char {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_u32(*self as u32)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl Hash for str {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write(self.as_bytes());
            state.write_u8(0xff)
        }
    }

    macro_rules! impl_hash_tuple {
        () => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl Hash for () {
                fn hash<H: Hasher>(&self, _state: &mut H) {}
            }
        );

        ( $($name:ident)+) => (
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<$($name: Hash),*> Hash for ($($name,)*) {
                #[allow(non_snake_case)]
                fn hash<S: Hasher>(&self, state: &mut S) {
                    let ($(ref $name,)*) = *self;
                    $($name.hash(state);)*
                }
            }
        );
    }

    impl_hash_tuple! {}
    impl_hash_tuple! { A }
    impl_hash_tuple! { A B }
    impl_hash_tuple! { A B C }
    impl_hash_tuple! { A B C D }
    impl_hash_tuple! { A B C D E }
    impl_hash_tuple! { A B C D E F }
    impl_hash_tuple! { A B C D E F G }
    impl_hash_tuple! { A B C D E F G H }
    impl_hash_tuple! { A B C D E F G H I }
    impl_hash_tuple! { A B C D E F G H I J }
    impl_hash_tuple! { A B C D E F G H I J K }
    impl_hash_tuple! { A B C D E F G H I J K L }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T: Hash> Hash for [T] {
        fn hash<H: Hasher>(&self, state: &mut H) {
            self.len().hash(state);
            Hash::hash_slice(self, state)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            (**self).hash(state);
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *const T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }

    #[stable(feature = "rust1", since = "1.0.0")]
    impl<T> Hash for *mut T {
        fn hash<H: Hasher>(&self, state: &mut H) {
            state.write_usize(*self as usize)
        }
    }
}
<|endoftext|>


<commit_before>
use assembler::data_range::DataRange;

enum Record<'a> {
  /// A data record. Supported in i8, i16 and i32.
  Data { address: u16, value: &'a [u8] },
  /// An end-of-file record. Supported in i8, i16 and i32.
  EndOfFile
}

mod type_codes {
  /// Type code for a Data record.
  pub const DATA_TYPE_CODE: u8 = 0x00;
  /// Type code for an End-of-File record.
  pub const END_OF_FILE_TYPE_CODE: u8 = 0x01;
}

impl<'a> Record<'a> {
  /**
   @return String value of the Intel HEX record for the receiver, excluding a trailing newline.
   */
  pub fn as_formatted_string(&self) -> String {
    match self {
      &Record::Data {address, value} => format_record(address, value, type_codes::DATA_TYPE_CODE),
      &Record::EndOfFile             => format_record(0x0000 , &[],   type_codes::END_OF_FILE_TYPE_CODE)
    }
  }
}

/**
 An Intel HEX record is composed of the following elements:
 +----------------+-----------------+---------------+-----------+---------+---------------+
 | Start Code (:) | Byte Count (u8) | Address (u16) | Type (u8) | Data... | Checksum (u8) |
 +----------------+-----------------+---------------+-----------+---------+---------------+
 */
fn format_record<'a>(address: u16, data: &'a [u8], type_code: u8) -> String {
  assert!(data.len() <= 255);

  // Construct the checksum region.
  let length_of_checksum_region = 4 + data.len();
  let mut checksum_region = Vec::<u8>::with_capacity(length_of_checksum_region);
  checksum_region.push(data.len() as u8);
  checksum_region.push(((address & 0xFF00) >> 8) as u8);
  checksum_region.push(((address & 0x00FF) >> 0) as u8);
  checksum_region.push(type_code);
  checksum_region.extend_from_slice(data);
  let checksum = ihex_checksum(checksum_region.as_slice());

  // Construct the record, excluding the start code and checksum.
  let checksum_region_string =
    checksum_region
      .iter()
      .map(|byte: &u8| format!("{:02X}", byte))
      .fold(String::new(), |acc, value| acc + &value);

  // Construct the formatted version of the record.
  format!(":{}{:02X}", checksum_region_string, checksum)
}

/**
 The Intel HEX checksum is computed as the two's complement of the sum of all
 elements preceding, excluding the Start Code. This is the Byte Count, Address,
 Record Type and Data.
 @param data Slice view of the checksum region.
 @return The Intel HEX checksum of the supplied region.
 */
fn ihex_checksum<'a>(data: &'a [u8]) -> u8 {
  let sum: usize = data.iter().fold(0, |acc, &value| acc.wrapping_add(value as usize));
  (((sum & 0xFF) as u8) ^ 0xFF).wrapping_add(1)
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use super::*;
  use super::{format_record, ihex_checksum, type_codes};

  #[test]
  fn test_ihex_checksum() {
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x00,0x00,0x21,0x46,0x01,0x36,0x01,0x21,0x47,0x01,0x36,0x00,0x7E,0xFE,0x09,0xD2,0x19,0x01]), 0x40);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x10,0x00,0x21,0x46,0x01,0x7E,0x17,0xC2,0x00,0x01,0xFF,0x5F,0x16,0x00,0x21,0x48,0x01,0x19]), 0x28);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x20,0x00,0x19,0x4E,0x79,0x23,0x46,0x23,0x96,0x57,0x78,0x23,0x9E,0xDA,0x3F,0x01,0xB2,0xCA]), 0xA7);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x30,0x00,0x3F,0x01,0x56,0x70,0x2B,0x5E,0x71,0x2B,0x72,0x2B,0x73,0x21,0x46,0x01,0x34,0x21]), 0xC7);
    assert_eq!(ihex_checksum(&vec![0x00,0x00,0x00,0x01]), 0xFF);
  }

  #[test]
  fn test_format_record() {
    assert_eq!(format_record(0x0100, &vec![0x21,0x46,0x01,0x36,0x01,0x21,0x47,0x01,0x36,0x00,0x7E,0xFE,0x09,0xD2,0x19,0x01], type_codes::DATA_TYPE_CODE), String::from(":10010000214601360121470136007EFE09D2190140"));
    assert_eq!(format_record(0x0110, &vec![0x21,0x46,0x01,0x7E,0x17,0xC2,0x00,0x01,0xFF,0x5F,0x16,0x00,0x21,0x48,0x01,0x19], type_codes::DATA_TYPE_CODE), String::from(":100110002146017E17C20001FF5F16002148011928"));
    assert_eq!(format_record(0x0120, &vec![0x19,0x4E,0x79,0x23,0x46,0x23,0x96,0x57,0x78,0x23,0x9E,0xDA,0x3F,0x01,0xB2,0xCA], type_codes::DATA_TYPE_CODE), String::from(":10012000194E79234623965778239EDA3F01B2CAA7"));
    assert_eq!(format_record(0x0130, &vec![0x3F,0x01,0x56,0x70,0x2B,0x5E,0x71,0x2B,0x72,0x2B,0x73,0x21,0x46,0x01,0x34,0x21], type_codes::DATA_TYPE_CODE), String::from(":100130003F0156702B5E712B722B732146013421C7"));
    assert_eq!(format_record(0x0000, &[], type_codes::END_OF_FILE_TYPE_CODE), String::from(":00000001FF"));
  }

}
<commit_msg>Additional tests for Record::as_formatted_string()<commit_after>
use assembler::data_range::DataRange;

enum Record<'a> {
  /// A data record. Supported in i8, i16 and i32.
  Data { address: u16, value: &'a [u8] },
  /// An end-of-file record. Supported in i8, i16 and i32.
  EndOfFile
}

mod type_codes {
  /// Type code for a Data record.
  pub const DATA_TYPE_CODE: u8 = 0x00;
  /// Type code for an End-of-File record.
  pub const END_OF_FILE_TYPE_CODE: u8 = 0x01;
}

impl<'a> Record<'a> {
  /**
   @return String value of the Intel HEX record for the receiver, excluding a trailing newline.
   */
  pub fn as_formatted_string(&self) -> String {
    match self {
      &Record::Data {address, value} => format_record(address, value, type_codes::DATA_TYPE_CODE),
      &Record::EndOfFile             => format_record(0x0000 , &[],   type_codes::END_OF_FILE_TYPE_CODE)
    }
  }
}

/**
 An Intel HEX record is composed of the following elements:
 +----------------+-----------------+---------------+-----------+---------+---------------+
 | Start Code (:) | Byte Count (u8) | Address (u16) | Type (u8) | Data... | Checksum (u8) |
 +----------------+-----------------+---------------+-----------+---------+---------------+
 */
fn format_record<'a>(address: u16, data: &'a [u8], type_code: u8) -> String {
  assert!(data.len() <= 255);

  // Construct the checksum region.
  let length_of_checksum_region = 4 + data.len();
  let mut checksum_region = Vec::<u8>::with_capacity(length_of_checksum_region);
  checksum_region.push(data.len() as u8);
  checksum_region.push(((address & 0xFF00) >> 8) as u8);
  checksum_region.push(((address & 0x00FF) >> 0) as u8);
  checksum_region.push(type_code);
  checksum_region.extend_from_slice(data);
  let checksum = ihex_checksum(checksum_region.as_slice());

  // Construct the record, excluding the start code and checksum.
  let checksum_region_string =
    checksum_region
      .iter()
      .map(|byte: &u8| format!("{:02X}", byte))
      .fold(String::new(), |acc, value| acc + &value);

  // Construct the formatted version of the record.
  format!(":{}{:02X}", checksum_region_string, checksum)
}

/**
 The Intel HEX checksum is computed as the two's complement of the sum of all
 elements preceding, excluding the Start Code. This is the Byte Count, Address,
 Record Type and Data.
 @param data Slice view of the checksum region.
 @return The Intel HEX checksum of the supplied region.
 */
fn ihex_checksum<'a>(data: &'a [u8]) -> u8 {
  let sum: usize = data.iter().fold(0, |acc, &value| acc.wrapping_add(value as usize));
  (((sum & 0xFF) as u8) ^ 0xFF).wrapping_add(1)
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use super::Record;
  use super::{format_record, ihex_checksum};
  use super::type_codes;

  #[test]
  fn test_ihex_checksum() {
    assert_eq!(ihex_checksum(&vec![]), 0x00);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x00,0x00,0x21,0x46,0x01,0x36,0x01,0x21,0x47,0x01,0x36,0x00,0x7E,0xFE,0x09,0xD2,0x19,0x01]), 0x40);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x10,0x00,0x21,0x46,0x01,0x7E,0x17,0xC2,0x00,0x01,0xFF,0x5F,0x16,0x00,0x21,0x48,0x01,0x19]), 0x28);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x20,0x00,0x19,0x4E,0x79,0x23,0x46,0x23,0x96,0x57,0x78,0x23,0x9E,0xDA,0x3F,0x01,0xB2,0xCA]), 0xA7);
    assert_eq!(ihex_checksum(&vec![0x10,0x01,0x30,0x00,0x3F,0x01,0x56,0x70,0x2B,0x5E,0x71,0x2B,0x72,0x2B,0x73,0x21,0x46,0x01,0x34,0x21]), 0xC7);
    assert_eq!(ihex_checksum(&vec![0x00,0x00,0x00,0x01]), 0xFF);
  }

  #[test]
  fn test_format_record() {
    assert_eq!(format_record(0x0100, &vec![0x21,0x46,0x01,0x36,0x01,0x21,0x47,0x01,0x36,0x00,0x7E,0xFE,0x09,0xD2,0x19,0x01], type_codes::DATA_TYPE_CODE), String::from(":10010000214601360121470136007EFE09D2190140"));
    assert_eq!(format_record(0x0110, &vec![0x21,0x46,0x01,0x7E,0x17,0xC2,0x00,0x01,0xFF,0x5F,0x16,0x00,0x21,0x48,0x01,0x19], type_codes::DATA_TYPE_CODE), String::from(":100110002146017E17C20001FF5F16002148011928"));
    assert_eq!(format_record(0x0120, &vec![0x19,0x4E,0x79,0x23,0x46,0x23,0x96,0x57,0x78,0x23,0x9E,0xDA,0x3F,0x01,0xB2,0xCA], type_codes::DATA_TYPE_CODE), String::from(":10012000194E79234623965778239EDA3F01B2CAA7"));
    assert_eq!(format_record(0x0130, &vec![0x3F,0x01,0x56,0x70,0x2B,0x5E,0x71,0x2B,0x72,0x2B,0x73,0x21,0x46,0x01,0x34,0x21], type_codes::DATA_TYPE_CODE), String::from(":100130003F0156702B5E712B722B732146013421C7"));
    assert_eq!(format_record(0x0000, &[], type_codes::END_OF_FILE_TYPE_CODE), String::from(":00000001FF"));
  }

  #[test]
  fn test_record_as_formatted_string() {
    let eof_record = Record::EndOfFile;
    assert_eq!(eof_record.as_formatted_string(), String::from(":00000001FF"));

    let data_record = Record::Data { address: 0x0100, value: &vec![0x21,0x46,0x01,0x36,0x01,0x21,0x47,0x01,0x36,0x00,0x7E,0xFE,0x09,0xD2,0x19,0x01] };
    assert_eq!(data_record.as_formatted_string(), String::from(":10010000214601360121470136007EFE09D2190140"));
  }

}
<|endoftext|>


<commit_before>use backend::obj;
use core::color::Rgba;
use core::geometry::Transform;
use core::geometry::Position;
use core::geometry::Velocity;
use core::clock::Seconds;

enum Shape {
	Round,
	Spark,
}

pub struct Emitter {
	id: usize,
	transform: Transform,
	attached_to: Option<obj::Id>,
	phase: Seconds,
	rate: Seconds,
	cluster_size: usize,
}

pub struct Particle {
	transform: Transform,
	direction: Velocity,
	trail: Box<[Position]>,
	shape: Shape,
}

impl Particle {
	pub fn new(transform: Transform, direction: Velocity, trail: Box<[Position]>) -> Particle {
		Particle {
			transform,
			direction,
			trail,
			shape: Shape::Round,
		}
	}

	pub fn transform(&self) -> Transform {
		self.transform.clone()
	}

	pub fn color(&self) -> Rgba<f32> {
		[1., 1., 1., 1.]
	}
}<commit_msg>HDR particle test<commit_after>use backend::obj;
use core::color::Rgba;
use core::geometry::Transform;
use core::geometry::Position;
use core::geometry::Velocity;
use core::clock::Seconds;

enum Shape {
	Round,
	Spark,
}

pub struct Emitter {
	id: usize,
	transform: Transform,
	attached_to: Option<obj::Id>,
	phase: Seconds,
	rate: Seconds,
	cluster_size: usize,
}

pub struct Particle {
	transform: Transform,
	direction: Velocity,
	trail: Box<[Position]>,
	shape: Shape,
}

impl Particle {
	pub fn new(transform: Transform, direction: Velocity, trail: Box<[Position]>) -> Particle {
		Particle {
			transform,
			direction,
			trail,
			shape: Shape::Round,
		}
	}

	pub fn transform(&self) -> Transform {
		self.transform.clone()
	}

	pub fn color(&self) -> Rgba<f32> {
		[10., 10., 10., 1.]
	}
}<|endoftext|>


<commit_before>use std::time::Duration;

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn frame(&self) -> u32 {
        self.current.as_ref().map_or(0, |i| i.frame)
    }

    pub fn is_active(&self) -> bool {
        self.current.is_some()
    }

    pub fn animate(&mut self, delta: Duration) {
        self.current =
            self.current.as_ref().map_or(Some(FrameInfo::default()), |i| self.advance(i, delta));
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    fn advance(&self, current: &FrameInfo, delta: Duration) -> Option<FrameInfo> {
        let elapsed = current.elapsed + delta;
        let remaining = elapsed.checked_sub(self.duration);
        remaining.map_or(Some(FrameInfo::new(current.frame, elapsed)),
                         |r| self.next(current, r))
    }

    fn next(&self, current: &FrameInfo, remaining: Duration) -> Option<FrameInfo> {
        let frame = (current.frame + 1) % self.max;
        if frame > 0 || self.repeat {
            Some(FrameInfo::new(frame, remaining))
        } else {
            None
        }
    }
}
<commit_msg>adding elapse method to frameinfo<commit_after>use std::time::Duration;

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }

    fn elapse(&self, elapsed: Duration) -> Self {
        FrameInfo::new(self.frame, elapsed)
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn frame(&self) -> u32 {
        self.current.as_ref().map_or(0, |i| i.frame)
    }

    pub fn is_active(&self) -> bool {
        self.current.is_some()
    }

    pub fn animate(&mut self, delta: Duration) {
        self.current =
            self.current.as_ref().map_or(Some(FrameInfo::default()), |i| self.advance(i, delta));
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    fn advance(&self, current: &FrameInfo, delta: Duration) -> Option<FrameInfo> {
        let elapsed = current.elapsed + delta;
        elapsed.checked_sub(self.duration)
            .map_or(Some(current.elapse(elapsed)), |r| self.next(current, r))
    }

    fn next(&self, current: &FrameInfo, remaining: Duration) -> Option<FrameInfo> {
        let frame = (current.frame + 1) % self.max;
        if frame > 0 || self.repeat {
            Some(FrameInfo::new(frame, remaining))
        } else {
            None
        }
    }
}
<|endoftext|>