<commit_before>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry: *const (),
    owned: bool,
}

impl Geometry {
    pub unsafe fn from_gdal_ptr(c_geometry: *const ()) -> Geometry {
        // c_geometry is owned by a Feature. The Feature must own this
        // Geometry and destroy it when the Feature is destroyed.
        return Geometry{c_geometry: c_geometry, owned: false};
    }

    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry: c_geom, owned: true};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(&format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ))
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry()) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry(), &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry;
    }

    pub fn set_point_2d(&mut self, i: i32, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry(),
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: i32) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry(), i, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry()) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        if self.owned {
            unsafe { ogr::OGR_G_DestroyGeometry(self.c_geometry as *mut ()) };
        }
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<commit_msg>wrap c_geometry in a RefCell<commit_after>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use std::cell::RefCell;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry_ref: RefCell<Option<*const ()>>,
    owned: bool,
}

impl Geometry {
    pub unsafe fn from_gdal_ptr(c_geometry: *const ()) -> Geometry {
        // c_geometry is owned by a Feature. The Feature must own this
        // Geometry and destroy it when the Feature is destroyed.
        return Geometry{c_geometry_ref: RefCell::new(Some(c_geometry)), owned: false};
    }

    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry_ref: RefCell::new(Some(c_geom)), owned: true};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry_ref: RefCell::new(Some(c_geom)), owned: true};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(&format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ))
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry()) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry(), &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry_ref.borrow().unwrap();
    }

    pub fn set_point_2d(&mut self, i: i32, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry(),
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: i32) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry(), i, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry()) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        if self.owned {
            let c_geometry = self.c_geometry_ref.borrow();
            unsafe { ogr::OGR_G_DestroyGeometry(c_geometry.unwrap() as *mut ()) };
        }
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<|endoftext|>


<commit_before>use core::marker::PhantomData;

use {Stream, Poll, Async};

/// A stream combinator to change the error type of a stream.
///
/// This is created by the `Stream::from_err` method.
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct FromErr<S, E> where S: Stream {
    stream: S,
    f: PhantomData<E>
}

pub fn new<S, E>(stream: S) -> FromErr<S, E>
    where S: Stream
{
    FromErr {
        stream: stream,
        f: PhantomData
    }
}

impl<S: Stream, E: From<S::Error>> Stream for FromErr<S, E> {
    type Item = S::Item;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<S::Item>, E> {
        let e = match self.stream.poll() {
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            other => other,
        };
        e.map_err(From::from)
    }
}
<commit_msg>Added a `Sink` implementation for where `stream::FromErr` also wraps a `Sink`.<commit_after>use core::marker::PhantomData;

use {Stream, Poll, Async, Sink, StartSend};

/// A stream combinator to change the error type of a stream.
///
/// This is created by the `Stream::from_err` method.
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct FromErr<S, E> where S: Stream {
    stream: S,
    f: PhantomData<E>
}

pub fn new<S, E>(stream: S) -> FromErr<S, E>
    where S: Stream
{
    FromErr {
        stream: stream,
        f: PhantomData
    }
}

impl<S: Stream, E: From<S::Error>> Stream for FromErr<S, E> {
    type Item = S::Item;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<S::Item>, E> {
        let e = match self.stream.poll() {
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            other => other,
        };
        e.map_err(From::from)
    }
}

impl<S: Stream + Sink, E: From<S::SinkError>> Sink for FromErr<S, E> {
    type SinkItem = S::SinkItem;
    type SinkError = E;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.stream.start_send(item).map_err(|e| e.into())
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.stream.poll_complete().map_err(|e| e.into())
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        self.stream.close().map_err(|e| e.into())
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use gj::{Promise, PromiseFulfiller};
use std::cell::{RefCell};
use std::rc::Rc;
use handle_table::{HandleTable, Handle};

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

impl Observer {
    pub fn when_read_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        promise
    }

    pub fn when_write_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        promise
    }
}

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                let token = status.token();
                let overlapped = status.overlapped();
                let bytes_transferred = status.bytes_transferred();
                let handle = Handle { val: token };
                if self.observers[handle].read_overlapped == overlapped {
                    match self.observers[handle].read_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }
                if self.observers[handle].write_overlapped == overlapped {
                    match self.observers[handle].write_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }

            }
        }
        Ok(())
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(pry!(SocketStreamInner::new(self.reactor.clone(), stream)))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        SocketListenerInner::new(self.reactor.clone(), listener, self.addr)
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: Box<::miow::Overlapped>,
    handle: Handle,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> Result<SocketListenerInner, ::std::io::Error>
    {
        let mut read_overlapped = Box::new(::miow::Overlapped::zero());
        let handle = try!(
            reactor.borrow_mut().add_socket(&listener, &mut *read_overlapped,
                                            ::std::ptr::null_mut()));

        Ok(SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: read_overlapped,
            handle: handle,
            queue: None,
        })
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            reactor: ref reactor,
            listener: ref mut listener,
            read_overlapped: ref mut read_overlapped,
            handle: handle,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, _ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        let reactor2 = reactor.clone();
        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
            println!("accepted!");
            SocketStreamInner::new(reactor2, stream)
        });

        result
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    read_overlapped: Box<::miow::Overlapped>,
    write_overlapped: Box<::miow::Overlapped>,
    handle: Handle,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream)
           -> Result<SocketStreamInner, ::std::io::Error>
    {
        let mut read_overlapped = Box::new(::miow::Overlapped::zero());
        let mut write_overlapped = Box::new(::miow::Overlapped::zero());
        let handle = try!(
            reactor.borrow_mut().add_socket(&stream, &mut *read_overlapped,
                                            &mut *write_overlapped));
        Ok(SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            handle: handle,
            read_queue: None,
            write_queue: None,
        })
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            reactor: ref reactor,
            stream: ref mut stream,
            read_overlapped: ref mut read_overlapped,
            handle: handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.read_overlapped(buf.as_mut(), read_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |n| {
            println!("read transferred this many bytes: {}", n);
            Ok((buf, n as usize))
        });

        result
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            reactor: ref reactor,
            stream: ref mut stream,
            write_overlapped: ref mut write_overlapped,
            handle: handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.write_overlapped(buf.as_ref(), write_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_write_done().map(move |n| {
            println!("write transferred this many bytes: {}", n);
            Ok(buf)
        });

        result
    }
}
<commit_msg>syntactic sugar<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use gj::{Promise, PromiseFulfiller};
use std::cell::{RefCell};
use std::rc::Rc;
use handle_table::{HandleTable, Handle};

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

impl Observer {
    pub fn when_read_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        promise
    }

    pub fn when_write_done(&mut self) -> Promise<u32, ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        promise
    }
}

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                let token = status.token();
                let overlapped = status.overlapped();
                let bytes_transferred = status.bytes_transferred();
                let handle = Handle { val: token };
                if self.observers[handle].read_overlapped == overlapped {
                    match self.observers[handle].read_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }
                if self.observers[handle].write_overlapped == overlapped {
                    match self.observers[handle].write_fulfiller.take() {
                        None => (),
                        Some(f) => f.fulfill(bytes_transferred),
                    }
                }

            }
        }
        Ok(())
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(pry!(SocketStreamInner::new(self.reactor.clone(), stream)))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        SocketListenerInner::new(self.reactor.clone(), listener, self.addr)
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: Box<::miow::Overlapped>,
    handle: Handle,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> Result<SocketListenerInner, ::std::io::Error>
    {
        let mut read_overlapped = Box::new(::miow::Overlapped::zero());
        let handle = try!(
            reactor.borrow_mut().add_socket(&listener, &mut *read_overlapped,
                                            ::std::ptr::null_mut()));

        Ok(SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: read_overlapped,
            handle: handle,
            queue: None,
        })
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            ref reactor, ref mut listener, ref mut read_overlapped, handle,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, _ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        let reactor2 = reactor.clone();
        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
            println!("accepted!");
            SocketStreamInner::new(reactor2, stream)
        });

        result
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    read_overlapped: Box<::miow::Overlapped>,
    write_overlapped: Box<::miow::Overlapped>,
    handle: Handle,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream)
           -> Result<SocketStreamInner, ::std::io::Error>
    {
        let mut read_overlapped = Box::new(::miow::Overlapped::zero());
        let mut write_overlapped = Box::new(::miow::Overlapped::zero());
        let handle = try!(
            reactor.borrow_mut().add_socket(&stream, &mut *read_overlapped,
                                            &mut *write_overlapped));
        Ok(SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            handle: handle,
            read_queue: None,
            write_queue: None,
        })
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            ref reactor, ref mut stream,
            ref mut read_overlapped, handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.read_overlapped(buf.as_mut(), read_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_read_done().map(move |n| {
            println!("read transferred this many bytes: {}", n);
            Ok((buf, n as usize))
        });

        result
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;

        let &mut SocketStreamInner {
            ref reactor,
            ref stream,
            ref mut write_overlapped, handle,
            ..
        } =  &mut *inner.borrow_mut();

        let _done = unsafe {
            pry!(stream.write_overlapped(buf.as_ref(), write_overlapped))
        };

        let result = reactor.borrow_mut().observers[handle].when_write_done().map(move |n| {
            println!("write transferred this many bytes: {}", n);
            Ok(buf)
        });

        result
    }
}
<|endoftext|>


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

use std::cell::RefCell;
use std::sync::mpsc::channel;
use std::dynamic_lib::DynamicLibrary;
use std::io::{Command, TempDir};
use std::io;
use std::os;
use std::str;
use std::thread::Thread;
use std::thunk::Thunk;

use std::collections::{HashSet, HashMap};
use testing;
use rustc::session::{self, config};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_driver::get_unstable_features_setting;
use rustc_driver::driver;
use syntax::ast;
use syntax::codemap::{CodeMap, dummy_spanned};
use syntax::diagnostic;
use syntax::parse::token;
use syntax::ptr::P;

use core;
use clean;
use clean::Clean;
use fold::DocFolder;
use html::markdown;
use passes;
use visit_ast::RustdocVisitor;

pub fn run(input: &str,
           cfgs: Vec<String>,
           libs: SearchPaths,
           externs: core::Externs,
           mut test_args: Vec<String>,
           crate_name: Option<String>)
           -> int {
    let input_path = Path::new(input);
    let input = config::Input::File(input_path.clone());

    let sessopts = config::Options {
        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
        search_paths: libs.clone(),
        crate_types: vec!(config::CrateTypeDylib),
        externs: externs.clone(),
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
    let span_diagnostic_handler =
    diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      Some(input_path.clone()),
                                      span_diagnostic_handler);

    let mut cfg = config::build_configuration(&sess);
    cfg.extend(cfgs.into_iter().map(|cfg_| {
        let cfg_ = token::intern_and_get_ident(cfg_.as_slice());
        P(dummy_spanned(ast::MetaWord(cfg_)))
    }));
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);
    let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                     "rustdoc-test", None)
        .expect("phase_2_configure_and_expand aborted in rustdoc!");

    let ctx = core::DocContext {
        krate: &krate,
        maybe_typed: core::NotTyped(sess),
        src: input_path,
        external_paths: RefCell::new(Some(HashMap::new())),
        external_traits: RefCell::new(None),
        external_typarams: RefCell::new(None),
        inlined: RefCell::new(None),
        populated_crate_impls: RefCell::new(HashSet::new()),
    };

    let mut v = RustdocVisitor::new(&ctx, None);
    v.visit(ctx.krate);
    let mut krate = v.clean(&ctx);
    match crate_name {
        Some(name) => krate.name = name,
        None => {}
    }
    let (krate, _) = passes::collapse_docs(krate);
    let (krate, _) = passes::unindent_comments(krate);

    let mut collector = Collector::new(krate.name.to_string(),
                                       libs,
                                       externs,
                                       false);
    collector.fold_crate(krate);

    test_args.insert(0, "rustdoctest".to_string());

    testing::test_main(test_args.as_slice(),
                       collector.tests.into_iter().collect());
    0
}

fn runtest(test: &str, cratename: &str, libs: SearchPaths,
           externs: core::Externs,
           should_fail: bool, no_run: bool, as_test_harness: bool) {
    // the test harness wants its own `main` & top level functions, so
    // never wrap the test in `fn main() { ... }`
    let test = maketest(test, Some(cratename), true, as_test_harness);
    let input = config::Input::Str(test.to_string());

    let sessopts = config::Options {
        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
        search_paths: libs,
        crate_types: vec!(config::CrateTypeExecutable),
        output_types: vec!(config::OutputTypeExe),
        no_trans: no_run,
        externs: externs,
        cg: config::CodegenOptions {
            prefer_dynamic: true,
            .. config::basic_codegen_options()
        },
        test: as_test_harness,
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    // Shuffle around a few input and output handles here. We're going to pass
    // an explicit handle into rustc to collect output messages, but we also
    // want to catch the error message that rustc prints when it fails.
    //
    // We take our task-local stderr (likely set by the test runner), and move
    // it into another task. This helper task then acts as a sink for both the
    // stderr of this task and stderr of rustc itself, copying all the info onto
    // the stderr channel we originally started with.
    //
    // The basic idea is to not use a default_handler() for rustc, and then also
    // not print things by default to the actual stderr.
    let (tx, rx) = channel();
    let w1 = io::ChanWriter::new(tx);
    let w2 = w1.clone();
    let old = io::stdio::set_stderr(box w1);
    Thread::spawn(move |:| {
        let mut p = io::ChanReader::new(rx);
        let mut err = match old {
            Some(old) => {
                // Chop off the `Send` bound.
                let old: Box<Writer> = old;
                old
            }
            None => box io::stderr() as Box<Writer>,
        };
        io::util::copy(&mut p, &mut err).unwrap();
    });
    let emitter = diagnostic::EmitterWriter::new(box w2, None);

    // Compile the code
    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::mk_handler(box emitter);
    let span_diagnostic_handler =
        diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      None,
                                      span_diagnostic_handler);

    let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
    let out = Some(outdir.path().clone());
    let cfg = config::build_configuration(&sess);
    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
    driver::compile_input(sess, cfg, &input, &out, &None, None);

    if no_run { return }

    // Run the code!
    //
    // We're careful to prepend the *target* dylib search path to the child's
    // environment to ensure that the target loads the right libraries at
    // runtime. It would be a sad day if the *host* libraries were loaded as a
    // mistake.
    let mut cmd = Command::new(outdir.path().join("rust-out"));
    let newpath = {
        let mut path = DynamicLibrary::search_path();
        path.insert(0, libdir.clone());
        DynamicLibrary::create_path(path.as_slice())
    };
    cmd.env(DynamicLibrary::envvar(), newpath.as_slice());

    match cmd.output() {
        Err(e) => panic!("couldn't run the test: {}{}", e,
                        if e.kind == io::PermissionDenied {
                            " - maybe your tempdir is mounted with noexec?"
                        } else { "" }),
        Ok(out) => {
            if should_fail && out.status.success() {
                panic!("test executable succeeded when it should have failed");
            } else if !should_fail && !out.status.success() {
                panic!("test executable failed:\n{:?}",
                      str::from_utf8(out.error.as_slice()));
            }
        }
    }
}

pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String {
    let mut prog = String::new();
    if lints {
        prog.push_str(r"
#![deny(warnings)]
#![allow(unused_variables, unused_assignments, unused_mut, unused_attributes, dead_code)]
");
    }

    // Don't inject `extern crate std` because it's already injected by the
    // compiler.
    if !s.contains("extern crate") && cratename != Some("std") {
        match cratename {
            Some(cratename) => {
                if s.contains(cratename) {
                    prog.push_str(format!("extern crate {};\n",
                                          cratename).as_slice());
                }
            }
            None => {}
        }
    }
    if dont_insert_main || s.contains("fn main") {
        prog.push_str(s);
    } else {
        prog.push_str("fn main() {\n    ");
        prog.push_str(s.replace("\n", "\n    ").as_slice());
        prog.push_str("\n}");
    }

    return prog
}

pub struct Collector {
    pub tests: Vec<testing::TestDescAndFn>,
    names: Vec<String>,
    libs: SearchPaths,
    externs: core::Externs,
    cnt: uint,
    use_headers: bool,
    current_header: Option<String>,
    cratename: String,
}

impl Collector {
    pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
               use_headers: bool) -> Collector {
        Collector {
            tests: Vec::new(),
            names: Vec::new(),
            libs: libs,
            externs: externs,
            cnt: 0,
            use_headers: use_headers,
            current_header: None,
            cratename: cratename,
        }
    }

    pub fn add_test(&mut self, test: String,
                    should_fail: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) {
        let name = if self.use_headers {
            let s = self.current_header.as_ref().map(|s| s.as_slice()).unwrap_or("");
            format!("{}_{}", s, self.cnt)
        } else {
            format!("{}_{}", self.names.connect("::"), self.cnt)
        };
        self.cnt += 1;
        let libs = self.libs.clone();
        let externs = self.externs.clone();
        let cratename = self.cratename.to_string();
        debug!("Creating test {}: {}", name, test);
        self.tests.push(testing::TestDescAndFn {
            desc: testing::TestDesc {
                name: testing::DynTestName(name),
                ignore: should_ignore,
                should_fail: testing::ShouldFail::No, // compiler failures are test failures
            },
            testfn: testing::DynTestFn(Thunk::new(move|| {
                runtest(test.as_slice(),
                        cratename.as_slice(),
                        libs,
                        externs,
                        should_fail,
                        no_run,
                        as_test_harness);
            }))
        });
    }

    pub fn register_header(&mut self, name: &str, level: u32) {
        if self.use_headers && level == 1 {
            // we use these headings as test names, so it's good if
            // they're valid identifiers.
            let name = name.chars().enumerate().map(|(i, c)| {
                    if (i == 0 && c.is_xid_start()) ||
                        (i != 0 && c.is_xid_continue()) {
                        c
                    } else {
                        '_'
                    }
                }).collect::<String>();

            // new header => reset count.
            self.cnt = 0;
            self.current_header = Some(name);
        }
    }
}

impl DocFolder for Collector {
    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
        let pushed = match item.name {
            Some(ref name) if name.len() == 0 => false,
            Some(ref name) => { self.names.push(name.to_string()); true }
            None => false
        };
        match item.doc_value() {
            Some(doc) => {
                self.cnt = 0;
                markdown::find_testable_code(doc, &mut *self);
            }
            None => {}
        }
        let ret = self.fold_item_recur(item);
        if pushed {
            self.names.pop();
        }
        return ret;
    }
}
<commit_msg>rustdoc: Stop adding #[deny(warnings)] to all tests<commit_after>// Copyright 2013-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.

use std::cell::RefCell;
use std::sync::mpsc::channel;
use std::dynamic_lib::DynamicLibrary;
use std::io::{Command, TempDir};
use std::io;
use std::os;
use std::str;
use std::thread::Thread;
use std::thunk::Thunk;

use std::collections::{HashSet, HashMap};
use testing;
use rustc::session::{self, config};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_driver::get_unstable_features_setting;
use rustc_driver::driver;
use syntax::ast;
use syntax::codemap::{CodeMap, dummy_spanned};
use syntax::diagnostic;
use syntax::parse::token;
use syntax::ptr::P;

use core;
use clean;
use clean::Clean;
use fold::DocFolder;
use html::markdown;
use passes;
use visit_ast::RustdocVisitor;

pub fn run(input: &str,
           cfgs: Vec<String>,
           libs: SearchPaths,
           externs: core::Externs,
           mut test_args: Vec<String>,
           crate_name: Option<String>)
           -> int {
    let input_path = Path::new(input);
    let input = config::Input::File(input_path.clone());

    let sessopts = config::Options {
        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
        search_paths: libs.clone(),
        crate_types: vec!(config::CrateTypeDylib),
        externs: externs.clone(),
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
    let span_diagnostic_handler =
    diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      Some(input_path.clone()),
                                      span_diagnostic_handler);

    let mut cfg = config::build_configuration(&sess);
    cfg.extend(cfgs.into_iter().map(|cfg_| {
        let cfg_ = token::intern_and_get_ident(cfg_.as_slice());
        P(dummy_spanned(ast::MetaWord(cfg_)))
    }));
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);
    let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                     "rustdoc-test", None)
        .expect("phase_2_configure_and_expand aborted in rustdoc!");

    let ctx = core::DocContext {
        krate: &krate,
        maybe_typed: core::NotTyped(sess),
        src: input_path,
        external_paths: RefCell::new(Some(HashMap::new())),
        external_traits: RefCell::new(None),
        external_typarams: RefCell::new(None),
        inlined: RefCell::new(None),
        populated_crate_impls: RefCell::new(HashSet::new()),
    };

    let mut v = RustdocVisitor::new(&ctx, None);
    v.visit(ctx.krate);
    let mut krate = v.clean(&ctx);
    match crate_name {
        Some(name) => krate.name = name,
        None => {}
    }
    let (krate, _) = passes::collapse_docs(krate);
    let (krate, _) = passes::unindent_comments(krate);

    let mut collector = Collector::new(krate.name.to_string(),
                                       libs,
                                       externs,
                                       false);
    collector.fold_crate(krate);

    test_args.insert(0, "rustdoctest".to_string());

    testing::test_main(test_args.as_slice(),
                       collector.tests.into_iter().collect());
    0
}

fn runtest(test: &str, cratename: &str, libs: SearchPaths,
           externs: core::Externs,
           should_fail: bool, no_run: bool, as_test_harness: bool) {
    // the test harness wants its own `main` & top level functions, so
    // never wrap the test in `fn main() { ... }`
    let test = maketest(test, Some(cratename), true, as_test_harness);
    let input = config::Input::Str(test.to_string());

    let sessopts = config::Options {
        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
        search_paths: libs,
        crate_types: vec!(config::CrateTypeExecutable),
        output_types: vec!(config::OutputTypeExe),
        no_trans: no_run,
        externs: externs,
        cg: config::CodegenOptions {
            prefer_dynamic: true,
            .. config::basic_codegen_options()
        },
        test: as_test_harness,
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    // Shuffle around a few input and output handles here. We're going to pass
    // an explicit handle into rustc to collect output messages, but we also
    // want to catch the error message that rustc prints when it fails.
    //
    // We take our task-local stderr (likely set by the test runner), and move
    // it into another task. This helper task then acts as a sink for both the
    // stderr of this task and stderr of rustc itself, copying all the info onto
    // the stderr channel we originally started with.
    //
    // The basic idea is to not use a default_handler() for rustc, and then also
    // not print things by default to the actual stderr.
    let (tx, rx) = channel();
    let w1 = io::ChanWriter::new(tx);
    let w2 = w1.clone();
    let old = io::stdio::set_stderr(box w1);
    Thread::spawn(move |:| {
        let mut p = io::ChanReader::new(rx);
        let mut err = match old {
            Some(old) => {
                // Chop off the `Send` bound.
                let old: Box<Writer> = old;
                old
            }
            None => box io::stderr() as Box<Writer>,
        };
        io::util::copy(&mut p, &mut err).unwrap();
    });
    let emitter = diagnostic::EmitterWriter::new(box w2, None);

    // Compile the code
    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::mk_handler(box emitter);
    let span_diagnostic_handler =
        diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      None,
                                      span_diagnostic_handler);

    let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
    let out = Some(outdir.path().clone());
    let cfg = config::build_configuration(&sess);
    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
    driver::compile_input(sess, cfg, &input, &out, &None, None);

    if no_run { return }

    // Run the code!
    //
    // We're careful to prepend the *target* dylib search path to the child's
    // environment to ensure that the target loads the right libraries at
    // runtime. It would be a sad day if the *host* libraries were loaded as a
    // mistake.
    let mut cmd = Command::new(outdir.path().join("rust-out"));
    let newpath = {
        let mut path = DynamicLibrary::search_path();
        path.insert(0, libdir.clone());
        DynamicLibrary::create_path(path.as_slice())
    };
    cmd.env(DynamicLibrary::envvar(), newpath.as_slice());

    match cmd.output() {
        Err(e) => panic!("couldn't run the test: {}{}", e,
                        if e.kind == io::PermissionDenied {
                            " - maybe your tempdir is mounted with noexec?"
                        } else { "" }),
        Ok(out) => {
            if should_fail && out.status.success() {
                panic!("test executable succeeded when it should have failed");
            } else if !should_fail && !out.status.success() {
                panic!("test executable failed:\n{:?}",
                      str::from_utf8(out.error.as_slice()));
            }
        }
    }
}

pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String {
    let mut prog = String::new();
    if lints {
        prog.push_str(r"
#![allow(unused_variables, unused_assignments, unused_mut, unused_attributes, dead_code)]
");
    }

    // Don't inject `extern crate std` because it's already injected by the
    // compiler.
    if !s.contains("extern crate") && cratename != Some("std") {
        match cratename {
            Some(cratename) => {
                if s.contains(cratename) {
                    prog.push_str(format!("extern crate {};\n",
                                          cratename).as_slice());
                }
            }
            None => {}
        }
    }
    if dont_insert_main || s.contains("fn main") {
        prog.push_str(s);
    } else {
        prog.push_str("fn main() {\n    ");
        prog.push_str(s.replace("\n", "\n    ").as_slice());
        prog.push_str("\n}");
    }

    return prog
}

pub struct Collector {
    pub tests: Vec<testing::TestDescAndFn>,
    names: Vec<String>,
    libs: SearchPaths,
    externs: core::Externs,
    cnt: uint,
    use_headers: bool,
    current_header: Option<String>,
    cratename: String,
}

impl Collector {
    pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
               use_headers: bool) -> Collector {
        Collector {
            tests: Vec::new(),
            names: Vec::new(),
            libs: libs,
            externs: externs,
            cnt: 0,
            use_headers: use_headers,
            current_header: None,
            cratename: cratename,
        }
    }

    pub fn add_test(&mut self, test: String,
                    should_fail: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) {
        let name = if self.use_headers {
            let s = self.current_header.as_ref().map(|s| s.as_slice()).unwrap_or("");
            format!("{}_{}", s, self.cnt)
        } else {
            format!("{}_{}", self.names.connect("::"), self.cnt)
        };
        self.cnt += 1;
        let libs = self.libs.clone();
        let externs = self.externs.clone();
        let cratename = self.cratename.to_string();
        debug!("Creating test {}: {}", name, test);
        self.tests.push(testing::TestDescAndFn {
            desc: testing::TestDesc {
                name: testing::DynTestName(name),
                ignore: should_ignore,
                should_fail: testing::ShouldFail::No, // compiler failures are test failures
            },
            testfn: testing::DynTestFn(Thunk::new(move|| {
                runtest(test.as_slice(),
                        cratename.as_slice(),
                        libs,
                        externs,
                        should_fail,
                        no_run,
                        as_test_harness);
            }))
        });
    }

    pub fn register_header(&mut self, name: &str, level: u32) {
        if self.use_headers && level == 1 {
            // we use these headings as test names, so it's good if
            // they're valid identifiers.
            let name = name.chars().enumerate().map(|(i, c)| {
                    if (i == 0 && c.is_xid_start()) ||
                        (i != 0 && c.is_xid_continue()) {
                        c
                    } else {
                        '_'
                    }
                }).collect::<String>();

            // new header => reset count.
            self.cnt = 0;
            self.current_header = Some(name);
        }
    }
}

impl DocFolder for Collector {
    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
        let pushed = match item.name {
            Some(ref name) if name.len() == 0 => false,
            Some(ref name) => { self.names.push(name.to_string()); true }
            None => false
        };
        match item.doc_value() {
            Some(doc) => {
                self.cnt = 0;
                markdown::find_testable_code(doc, &mut *self);
            }
            None => {}
        }
        let ret = self.fold_item_recur(item);
        if pushed {
            self.names.pop();
        }
        return ret;
    }
}
<|endoftext|>


<commit_before>//! Samurai Sudoku.
//!
//! https://en.wikipedia.org/wiki/Sudoku#Variants
//! http://www.samurai-sudoku.com/#ai

extern crate puzzle_solver;

use puzzle_solver::{Puzzle,Solution,VarToken};

const SQRT_SIZE: usize = 3;
const SIZE: usize = 9;
const X: i32 = -1;
type Board = [[i32; SIZE + SQRT_SIZE + SIZE]; SIZE + SQRT_SIZE + SIZE];
type SudokuVars = Vec<Vec<VarToken>>;
type SamuraiVars = (SudokuVars, SudokuVars, SudokuVars, SudokuVars, SudokuVars);

fn make_sudoku(sys: &mut Puzzle) -> SudokuVars {
    let vars = sys.new_vars_with_candidates_2d(SIZE, SIZE, &[1,2,3,4,5,6,7,8,9]);

    for y in 0..SIZE {
        sys.all_different(&vars[y]);
    }

    for x in 0..SIZE {
        sys.all_different(vars.iter().map(|row| &row[x]));
    }

    for block in 0..SIZE {
        let x0 = SQRT_SIZE * (block % SQRT_SIZE);
        let y0 = SQRT_SIZE * (block / SQRT_SIZE);
        sys.all_different((0..SIZE).map(|n|
                &vars[y0 + (n / SQRT_SIZE)][x0 + (n % SQRT_SIZE)]));
    }

    vars
}

fn make_samurai_sudoku(board: &Board) -> (Puzzle, SamuraiVars) {
    let set = |sys: &mut Puzzle, var, val| if val != 0 { sys.set_value(var, val) };

    let mut sys = Puzzle::new();
    let tl = make_sudoku(&mut sys);
    let tr = make_sudoku(&mut sys);
    let bl = make_sudoku(&mut sys);
    let br = make_sudoku(&mut sys);
    let mid = make_sudoku(&mut sys);

    for y in 0..SQRT_SIZE {
        for x in 0..SQRT_SIZE {
            sys.equals(mid[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x], tl[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.equals(mid[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x], tr[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
            sys.equals(mid[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x], bl[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.equals(mid[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x], br[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
        }
    }

    for y in 0..SIZE {
        for x in 0..SIZE {
            set(&mut sys, tl[y][x], board[y][x]);
            set(&mut sys, tr[y][x], board[y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, bl[y][x], board[SIZE + SQRT_SIZE + y][x]);
            set(&mut sys, br[y][x], board[SIZE + SQRT_SIZE + y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, mid[y][x], board[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
        }
    }

    (sys, (tl, tr, bl, br, mid))
}

fn print_samurai_sudoku(dict: &Solution, vars: &SamuraiVars) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    let pr3 = |a: &[VarToken], j| print!(" {}{}{}", dict[a[j]], dict[a[j + 1]], dict[a[j + 2]]);
    let pr9 = |a| { pr3(a, 0); pr3(a, 3); pr3(a, 6); };
    let gap = || print!("    ");

    for i in 0..SIZE {
        pr9(&tl[i]);
        if 2 * SQRT_SIZE <= i {
            pr3(&mid[i - 2 * SQRT_SIZE], 3);
        } else {
            gap();
        }
        pr9(&tr[i]);
        println!();
    }

    for i in SQRT_SIZE..(2 * SQRT_SIZE) {
        gap();
        gap();
        pr9(&mid[i]);
        println!();
    }

    for i in 0..SIZE {
        pr9(&bl[i]);
        if i < SQRT_SIZE {
            pr3(&mid[2 * SQRT_SIZE + i], 3);
        } else {
            gap();
        }
        pr9(&br[i]);
        println!();
    }
}

fn verify_samurai_sudoku(dict: &Solution, vars: &SamuraiVars, expected: &Board) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    for i in 0..SIZE {
        for j in 0..SIZE {
            assert_eq!(dict[tl[i][j]], expected[i][j]);
            assert_eq!(dict[tr[i][j]], expected[i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[bl[i][j]], expected[SIZE + SQRT_SIZE + i][j]);
            assert_eq!(dict[br[i][j]], expected[SIZE + SQRT_SIZE + i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[mid[i][j]], expected[2 * SQRT_SIZE + i][2 * SQRT_SIZE + j]);
        }
    }
}

#[test]
fn samuraisudoku_easy() {
    let puzzle = [
        [ 0,0,3,  0,0,0,  2,0,0,  X,X,X,  0,0,6,  0,0,0,  2,0,0 ],
        [ 0,2,0,  4,0,8,  0,3,0,  X,X,X,  0,3,0,  4,0,2,  0,8,0 ],
        [ 8,0,0,  0,9,0,  0,0,4,  X,X,X,  8,0,0,  0,1,0,  0,0,4 ],

        [ 0,5,0,  6,0,1,  0,2,0,  X,X,X,  0,2,0,  1,0,7,  0,9,0 ],
        [ 0,0,8,  0,0,0,  6,0,0,  X,X,X,  0,0,9,  0,0,0,  8,0,0 ],
        [ 0,7,0,  8,0,4,  0,1,0,  X,X,X,  0,8,0,  5,0,9,  0,4,0 ],

        [ 1,0,0,  0,7,0,  0,0,0,  0,0,0,  0,0,0,  0,7,0,  0,0,5 ],
        [ 0,4,0,  1,0,2,  0,0,0,  0,0,0,  0,0,0,  2,0,8,  0,7,0 ],
        [ 0,0,9,  0,0,0,  0,0,0,  0,6,0,  0,0,0,  0,0,0,  1,0,0 ],

        [ X,X,X,  X,X,X,  0,0,0,  5,0,1,  0,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,9,  0,0,0,  6,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,0,  3,0,6,  0,0,0,  X,X,X,  X,X,X ],

        [ 0,0,8,  0,0,0,  0,0,0,  0,7,0,  0,0,0,  0,0,0,  4,0,0 ],
        [ 0,4,0,  5,0,1,  0,0,0,  0,0,0,  0,0,0,  9,0,5,  0,7,0 ],
        [ 6,0,0,  0,2,0,  0,0,0,  0,0,0,  0,0,0,  0,6,0,  0,0,9 ],

        [ 0,9,0,  1,0,3,  0,7,0,  X,X,X,  0,7,0,  5,0,1,  0,9,0 ],
        [ 0,0,5,  0,0,0,  1,0,0,  X,X,X,  0,0,3,  0,0,0,  6,0,0 ],
        [ 0,1,0,  6,0,8,  0,9,0,  X,X,X,  0,2,0,  8,0,6,  0,1,0 ],

        [ 5,0,0,  0,7,0,  0,0,6,  X,X,X,  7,0,0,  0,2,0,  0,0,5 ],
        [ 0,2,0,  3,0,5,  0,1,0,  X,X,X,  0,9,0,  6,0,4,  0,3,0 ],
        [ 0,0,6,  0,0,0,  2,0,0,  X,X,X,  0,0,4,  0,0,0,  1,0,0 ] ];

    let expected = [
        [ 4,9,3,  7,1,5,  2,6,8,  X,X,X,  9,4,6,  8,3,5,  2,1,7 ],
        [ 5,2,7,  4,6,8,  9,3,1,  X,X,X,  1,3,7,  4,9,2,  5,8,6 ],
        [ 8,6,1,  2,9,3,  5,7,4,  X,X,X,  8,5,2,  7,1,6,  9,3,4 ],

        [ 9,5,4,  6,3,1,  8,2,7,  X,X,X,  5,2,4,  1,8,7,  6,9,3 ],
        [ 3,1,8,  9,2,7,  6,4,5,  X,X,X,  7,1,9,  6,4,3,  8,5,2 ],
        [ 2,7,6,  8,5,4,  3,1,9,  X,X,X,  6,8,3,  5,2,9,  7,4,1 ],

        [ 1,8,2,  3,7,9,  4,5,6,  7,1,3,  2,9,8,  3,7,1,  4,6,5 ],
        [ 6,4,5,  1,8,2,  7,9,3,  8,5,2,  4,6,1,  2,5,8,  3,7,9 ],
        [ 7,3,9,  5,4,6,  1,8,2,  9,6,4,  3,7,5,  9,6,4,  1,2,8 ],

        [ X,X,X,  X,X,X,  6,4,8,  5,9,1,  7,2,3,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  3,1,9,  2,8,7,  6,5,4,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  2,7,5,  3,4,6,  1,8,9,  X,X,X,  X,X,X ],

        [ 1,7,8,  9,3,6,  5,2,4,  1,7,8,  9,3,6,  2,8,7,  4,5,1 ],
        [ 2,4,3,  5,8,1,  9,6,7,  4,3,5,  8,1,2,  9,4,5,  3,7,6 ],
        [ 6,5,9,  4,2,7,  8,3,1,  6,2,9,  5,4,7,  1,6,3,  8,2,9 ],

        [ 8,9,2,  1,4,3,  6,7,5,  X,X,X,  6,7,8,  5,3,1,  2,9,4 ],
        [ 4,6,5,  7,9,2,  1,8,3,  X,X,X,  1,5,3,  4,9,2,  6,8,7 ],
        [ 3,1,7,  6,5,8,  4,9,2,  X,X,X,  4,2,9,  8,7,6,  5,1,3 ],

        [ 5,8,1,  2,7,9,  3,4,6,  X,X,X,  7,6,1,  3,2,8,  9,4,5 ],
        [ 9,2,4,  3,6,5,  7,1,8,  X,X,X,  2,9,5,  6,1,4,  7,3,8 ],
        [ 7,3,6,  8,1,4,  2,5,9,  X,X,X,  3,8,4,  7,5,9,  1,6,2 ] ];

    let (mut sys, vars) = make_samurai_sudoku(&puzzle);
    let dict = sys.solve_any().expect("solution");
    print_samurai_sudoku(&dict, &vars);
    verify_samurai_sudoku(&dict, &vars, &expected);
    println!("samuraisudoku_easy: {} guesses", sys.num_guesses());
}
<commit_msg>Update test: Samurai Sudoku.<commit_after>//! Samurai Sudoku.
//!
//! https://en.wikipedia.org/wiki/Sudoku#Variants
//! http://www.samurai-sudoku.com/#ai

extern crate puzzle_solver;

use puzzle_solver::{Puzzle,Solution,VarToken};

const SQRT_SIZE: usize = 3;
const SIZE: usize = 9;
const X: i32 = -1;
type Board = [[i32; SIZE + SQRT_SIZE + SIZE]; SIZE + SQRT_SIZE + SIZE];
type SudokuVars = Vec<Vec<VarToken>>;
type SamuraiVars = (SudokuVars, SudokuVars, SudokuVars, SudokuVars, SudokuVars);

fn make_sudoku(sys: &mut Puzzle) -> SudokuVars {
    let vars = sys.new_vars_with_candidates_2d(SIZE, SIZE, &[1,2,3,4,5,6,7,8,9]);

    for y in 0..SIZE {
        sys.all_different(&vars[y]);
    }

    for x in 0..SIZE {
        sys.all_different(vars.iter().map(|row| &row[x]));
    }

    for block in 0..SIZE {
        let x0 = SQRT_SIZE * (block % SQRT_SIZE);
        let y0 = SQRT_SIZE * (block / SQRT_SIZE);
        sys.all_different((0..SIZE).map(|n|
                &vars[y0 + (n / SQRT_SIZE)][x0 + (n % SQRT_SIZE)]));
    }

    vars
}

fn make_samurai_sudoku(board: &Board) -> (Puzzle, SamuraiVars) {
    let set = |sys: &mut Puzzle, var, val| if val != 0 { sys.set_value(var, val) };

    let mut sys = Puzzle::new();
    let tl = make_sudoku(&mut sys);
    let tr = make_sudoku(&mut sys);
    let bl = make_sudoku(&mut sys);
    let br = make_sudoku(&mut sys);
    let mid = make_sudoku(&mut sys);

    for y in 0..SQRT_SIZE {
        for x in 0..SQRT_SIZE {
            sys.unify(mid[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x], tl[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.unify(mid[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x], tr[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
            sys.unify(mid[2 * SQRT_SIZE + y][0 * SQRT_SIZE + x], bl[0 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
            sys.unify(mid[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x], br[0 * SQRT_SIZE + y][0 * SQRT_SIZE + x]);
        }
    }

    for y in 0..SIZE {
        for x in 0..SIZE {
            set(&mut sys, tl[y][x], board[y][x]);
            set(&mut sys, tr[y][x], board[y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, bl[y][x], board[SIZE + SQRT_SIZE + y][x]);
            set(&mut sys, br[y][x], board[SIZE + SQRT_SIZE + y][SIZE + SQRT_SIZE + x]);
            set(&mut sys, mid[y][x], board[2 * SQRT_SIZE + y][2 * SQRT_SIZE + x]);
        }
    }

    (sys, (tl, tr, bl, br, mid))
}

fn print_samurai_sudoku(dict: &Solution, vars: &SamuraiVars) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    let pr3 = |a: &[VarToken], j| print!(" {}{}{}", dict[a[j]], dict[a[j + 1]], dict[a[j + 2]]);
    let pr9 = |a| { pr3(a, 0); pr3(a, 3); pr3(a, 6); };
    let gap = || print!("    ");

    for i in 0..SIZE {
        pr9(&tl[i]);
        if 2 * SQRT_SIZE <= i {
            pr3(&mid[i - 2 * SQRT_SIZE], 3);
        } else {
            gap();
        }
        pr9(&tr[i]);
        println!();
    }

    for i in SQRT_SIZE..(2 * SQRT_SIZE) {
        gap();
        gap();
        pr9(&mid[i]);
        println!();
    }

    for i in 0..SIZE {
        pr9(&bl[i]);
        if i < SQRT_SIZE {
            pr3(&mid[2 * SQRT_SIZE + i], 3);
        } else {
            gap();
        }
        pr9(&br[i]);
        println!();
    }
}

fn verify_samurai_sudoku(dict: &Solution, vars: &SamuraiVars, expected: &Board) {
    let &(ref tl, ref tr, ref bl, ref br, ref mid) = vars;
    for i in 0..SIZE {
        for j in 0..SIZE {
            assert_eq!(dict[tl[i][j]], expected[i][j]);
            assert_eq!(dict[tr[i][j]], expected[i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[bl[i][j]], expected[SIZE + SQRT_SIZE + i][j]);
            assert_eq!(dict[br[i][j]], expected[SIZE + SQRT_SIZE + i][SIZE + SQRT_SIZE + j]);
            assert_eq!(dict[mid[i][j]], expected[2 * SQRT_SIZE + i][2 * SQRT_SIZE + j]);
        }
    }
}

#[test]
fn samuraisudoku_easy() {
    let puzzle = [
        [ 0,0,3,  0,0,0,  2,0,0,  X,X,X,  0,0,6,  0,0,0,  2,0,0 ],
        [ 0,2,0,  4,0,8,  0,3,0,  X,X,X,  0,3,0,  4,0,2,  0,8,0 ],
        [ 8,0,0,  0,9,0,  0,0,4,  X,X,X,  8,0,0,  0,1,0,  0,0,4 ],

        [ 0,5,0,  6,0,1,  0,2,0,  X,X,X,  0,2,0,  1,0,7,  0,9,0 ],
        [ 0,0,8,  0,0,0,  6,0,0,  X,X,X,  0,0,9,  0,0,0,  8,0,0 ],
        [ 0,7,0,  8,0,4,  0,1,0,  X,X,X,  0,8,0,  5,0,9,  0,4,0 ],

        [ 1,0,0,  0,7,0,  0,0,0,  0,0,0,  0,0,0,  0,7,0,  0,0,5 ],
        [ 0,4,0,  1,0,2,  0,0,0,  0,0,0,  0,0,0,  2,0,8,  0,7,0 ],
        [ 0,0,9,  0,0,0,  0,0,0,  0,6,0,  0,0,0,  0,0,0,  1,0,0 ],

        [ X,X,X,  X,X,X,  0,0,0,  5,0,1,  0,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,9,  0,0,0,  6,0,0,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  0,0,0,  3,0,6,  0,0,0,  X,X,X,  X,X,X ],

        [ 0,0,8,  0,0,0,  0,0,0,  0,7,0,  0,0,0,  0,0,0,  4,0,0 ],
        [ 0,4,0,  5,0,1,  0,0,0,  0,0,0,  0,0,0,  9,0,5,  0,7,0 ],
        [ 6,0,0,  0,2,0,  0,0,0,  0,0,0,  0,0,0,  0,6,0,  0,0,9 ],

        [ 0,9,0,  1,0,3,  0,7,0,  X,X,X,  0,7,0,  5,0,1,  0,9,0 ],
        [ 0,0,5,  0,0,0,  1,0,0,  X,X,X,  0,0,3,  0,0,0,  6,0,0 ],
        [ 0,1,0,  6,0,8,  0,9,0,  X,X,X,  0,2,0,  8,0,6,  0,1,0 ],

        [ 5,0,0,  0,7,0,  0,0,6,  X,X,X,  7,0,0,  0,2,0,  0,0,5 ],
        [ 0,2,0,  3,0,5,  0,1,0,  X,X,X,  0,9,0,  6,0,4,  0,3,0 ],
        [ 0,0,6,  0,0,0,  2,0,0,  X,X,X,  0,0,4,  0,0,0,  1,0,0 ] ];

    let expected = [
        [ 4,9,3,  7,1,5,  2,6,8,  X,X,X,  9,4,6,  8,3,5,  2,1,7 ],
        [ 5,2,7,  4,6,8,  9,3,1,  X,X,X,  1,3,7,  4,9,2,  5,8,6 ],
        [ 8,6,1,  2,9,3,  5,7,4,  X,X,X,  8,5,2,  7,1,6,  9,3,4 ],

        [ 9,5,4,  6,3,1,  8,2,7,  X,X,X,  5,2,4,  1,8,7,  6,9,3 ],
        [ 3,1,8,  9,2,7,  6,4,5,  X,X,X,  7,1,9,  6,4,3,  8,5,2 ],
        [ 2,7,6,  8,5,4,  3,1,9,  X,X,X,  6,8,3,  5,2,9,  7,4,1 ],

        [ 1,8,2,  3,7,9,  4,5,6,  7,1,3,  2,9,8,  3,7,1,  4,6,5 ],
        [ 6,4,5,  1,8,2,  7,9,3,  8,5,2,  4,6,1,  2,5,8,  3,7,9 ],
        [ 7,3,9,  5,4,6,  1,8,2,  9,6,4,  3,7,5,  9,6,4,  1,2,8 ],

        [ X,X,X,  X,X,X,  6,4,8,  5,9,1,  7,2,3,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  3,1,9,  2,8,7,  6,5,4,  X,X,X,  X,X,X ],
        [ X,X,X,  X,X,X,  2,7,5,  3,4,6,  1,8,9,  X,X,X,  X,X,X ],

        [ 1,7,8,  9,3,6,  5,2,4,  1,7,8,  9,3,6,  2,8,7,  4,5,1 ],
        [ 2,4,3,  5,8,1,  9,6,7,  4,3,5,  8,1,2,  9,4,5,  3,7,6 ],
        [ 6,5,9,  4,2,7,  8,3,1,  6,2,9,  5,4,7,  1,6,3,  8,2,9 ],

        [ 8,9,2,  1,4,3,  6,7,5,  X,X,X,  6,7,8,  5,3,1,  2,9,4 ],
        [ 4,6,5,  7,9,2,  1,8,3,  X,X,X,  1,5,3,  4,9,2,  6,8,7 ],
        [ 3,1,7,  6,5,8,  4,9,2,  X,X,X,  4,2,9,  8,7,6,  5,1,3 ],

        [ 5,8,1,  2,7,9,  3,4,6,  X,X,X,  7,6,1,  3,2,8,  9,4,5 ],
        [ 9,2,4,  3,6,5,  7,1,8,  X,X,X,  2,9,5,  6,1,4,  7,3,8 ],
        [ 7,3,6,  8,1,4,  2,5,9,  X,X,X,  3,8,4,  7,5,9,  1,6,2 ] ];

    let (mut sys, vars) = make_samurai_sudoku(&puzzle);
    let dict = sys.solve_any().expect("solution");
    print_samurai_sudoku(&dict, &vars);
    verify_samurai_sudoku(&dict, &vars, &expected);
    println!("samuraisudoku_easy: {} guesses", sys.num_guesses());
}
<|endoftext|>


<commit_before>use log::trace;

use super::value::Value;
use crate::compiler::lir::ChunkIndex;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Heap {
    objects: HashMap<ObjectPointer, Object>,
    next_address: ObjectPointer,
}

pub type ObjectPointer = usize;

#[derive(Debug, Clone)] // TODO: remove Clone once it's no longer needed
pub struct Object {
    reference_count: usize,
    pub data: ObjectData,
}
#[derive(Clone, Debug)] // TODO: remove Clone once it's no longer needed
pub enum ObjectData {
    Int(u64),
    Text(String),
    Symbol(String),
    Struct(HashMap<ObjectPointer, ObjectPointer>),
    Closure {
        captured: Vec<ObjectPointer>,
        body: ChunkIndex,
    },
}

impl Heap {
    pub fn new() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: 0,
        }
    }

    pub fn get(&self, address: ObjectPointer) -> &Object {
        self.objects
            .get(&address)
            .expect(&format!("Couldn't get object {}.", address))
    }
    pub fn get_mut(&mut self, address: ObjectPointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .expect(&format!("Couldn't get object {}.", address))
    }

    pub fn dup(&mut self, address: ObjectPointer) {
        self.get_mut(address).reference_count += 1;
        trace!(
            "RefCount of {} increased to {}. Value: {}",
            address,
            self.get(address).reference_count,
            self.export_without_dropping(address),
        );
    }
    pub fn drop(&mut self, address: ObjectPointer) {
        let value = self.export_without_dropping(address); // TODO: Only for logging
        let object = self.get_mut(address);
        object.reference_count -= 1;
        trace!(
            "RefCount of {} reduced to {}. Value: {}",
            address,
            object.reference_count,
            value,
        );
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: ObjectData) -> ObjectPointer {
        let address = self.next_address;
        trace!("Creating object {:?} at {}.", object, address);
        self.objects.insert(
            address,
            Object {
                reference_count: 1,
                data: object,
            },
        );
        self.next_address += 1;
        address
    }
    pub fn free(&mut self, address: ObjectPointer) {
        let object = self.objects.remove(&address).unwrap();
        trace!("Freeing object {:?} at {}.", object, address);
        assert_eq!(object.reference_count, 0);
        match object.data {
            ObjectData::Int(_) => {}
            ObjectData::Text(_) => {}
            ObjectData::Symbol(_) => {}
            ObjectData::Struct(entries) => {
                for (key, value) in entries {
                    self.drop(key);
                    self.drop(value);
                }
            }
            ObjectData::Closure { captured, .. } => {
                for object in captured {
                    self.drop(object);
                }
            }
        }
    }

    pub(super) fn import(&mut self, value: Value) -> ObjectPointer {
        let value = match value {
            Value::Int(int) => ObjectData::Int(int),
            Value::Text(text) => ObjectData::Text(text),
            Value::Symbol(symbol) => ObjectData::Symbol(symbol),
            Value::Struct(struct_) => {
                let mut entries = HashMap::new();
                for (key, value) in struct_ {
                    let key = self.import(key);
                    let value = self.import(value);
                    entries.insert(key, value);
                }
                ObjectData::Struct(entries)
            }
            Value::Closure { captured, body } => {
                let mut captured = vec![];
                ObjectData::Closure { captured, body }
            }
        };
        self.create(value)
    }
    pub(super) fn export(&mut self, address: ObjectPointer) -> Value {
        let value = self.export_without_dropping(address);
        self.drop(address);
        value
    }
    pub fn export_without_dropping(&self, address: ObjectPointer) -> Value {
        match &self.get(address).data {
            ObjectData::Int(int) => Value::Int(*int),
            ObjectData::Text(text) => Value::Text(text.clone()),
            ObjectData::Symbol(symbol) => Value::Symbol(symbol.clone()),
            ObjectData::Struct(struct_) => {
                let mut entries = im::HashMap::new();
                for (key, value) in struct_ {
                    let key = self.export_without_dropping(*key);
                    let value = self.export_without_dropping(*value);
                    entries.insert(key, value);
                }
                Value::Struct(entries)
            }
            ObjectData::Closure { captured, body } => Value::Closure {
                captured: captured.clone(),
                body: *body,
            },
        }
    }
}
<commit_msg>Fix error of ignoring captured variables of imported closures<commit_after>use log::trace;

use super::value::Value;
use crate::compiler::lir::ChunkIndex;
use std::collections::HashMap;

#[derive(Debug)]
pub struct Heap {
    objects: HashMap<ObjectPointer, Object>,
    next_address: ObjectPointer,
}

pub type ObjectPointer = usize;

#[derive(Debug, Clone)] // TODO: remove Clone once it's no longer needed
pub struct Object {
    reference_count: usize,
    pub data: ObjectData,
}
#[derive(Clone, Debug)] // TODO: remove Clone once it's no longer needed
pub enum ObjectData {
    Int(u64),
    Text(String),
    Symbol(String),
    Struct(HashMap<ObjectPointer, ObjectPointer>),
    Closure {
        captured: Vec<ObjectPointer>,
        body: ChunkIndex,
    },
}

impl Heap {
    pub fn new() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: 0,
        }
    }

    pub fn get(&self, address: ObjectPointer) -> &Object {
        self.objects
            .get(&address)
            .expect(&format!("Couldn't get object {}.", address))
    }
    pub fn get_mut(&mut self, address: ObjectPointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .expect(&format!("Couldn't get object {}.", address))
    }

    pub fn dup(&mut self, address: ObjectPointer) {
        self.get_mut(address).reference_count += 1;
        trace!(
            "RefCount of {} increased to {}. Value: {}",
            address,
            self.get(address).reference_count,
            self.export_without_dropping(address),
        );
    }
    pub fn drop(&mut self, address: ObjectPointer) {
        let value = self.export_without_dropping(address); // TODO: Only for logging
        let object = self.get_mut(address);
        object.reference_count -= 1;
        trace!(
            "RefCount of {} reduced to {}. Value: {}",
            address,
            object.reference_count,
            value,
        );
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: ObjectData) -> ObjectPointer {
        let address = self.next_address;
        trace!("Creating object {:?} at {}.", object, address);
        self.objects.insert(
            address,
            Object {
                reference_count: 1,
                data: object,
            },
        );
        self.next_address += 1;
        address
    }
    pub fn free(&mut self, address: ObjectPointer) {
        let object = self.objects.remove(&address).unwrap();
        trace!("Freeing object {:?} at {}.", object, address);
        assert_eq!(object.reference_count, 0);
        match object.data {
            ObjectData::Int(_) => {}
            ObjectData::Text(_) => {}
            ObjectData::Symbol(_) => {}
            ObjectData::Struct(entries) => {
                for (key, value) in entries {
                    self.drop(key);
                    self.drop(value);
                }
            }
            ObjectData::Closure { captured, .. } => {
                for object in captured {
                    self.drop(object);
                }
            }
        }
    }

    pub(super) fn import(&mut self, value: Value) -> ObjectPointer {
        let value = match value {
            Value::Int(int) => ObjectData::Int(int),
            Value::Text(text) => ObjectData::Text(text),
            Value::Symbol(symbol) => ObjectData::Symbol(symbol),
            Value::Struct(struct_) => {
                let mut entries = HashMap::new();
                for (key, value) in struct_ {
                    let key = self.import(key);
                    let value = self.import(value);
                    entries.insert(key, value);
                }
                ObjectData::Struct(entries)
            }
            Value::Closure { captured, body } => ObjectData::Closure { captured, body },
        };
        self.create(value)
    }
    pub(super) fn export(&mut self, address: ObjectPointer) -> Value {
        let value = self.export_without_dropping(address);
        self.drop(address);
        value
    }
    pub fn export_without_dropping(&self, address: ObjectPointer) -> Value {
        match &self.get(address).data {
            ObjectData::Int(int) => Value::Int(*int),
            ObjectData::Text(text) => Value::Text(text.clone()),
            ObjectData::Symbol(symbol) => Value::Symbol(symbol.clone()),
            ObjectData::Struct(struct_) => {
                let mut entries = im::HashMap::new();
                for (key, value) in struct_ {
                    let key = self.export_without_dropping(*key);
                    let value = self.export_without_dropping(*value);
                    entries.insert(key, value);
                }
                Value::Struct(entries)
            }
            ObjectData::Closure { captured, body } => Value::Closure {
                captured: captured.clone(),
                body: *body,
            },
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::str;

use crate::reflect::error::ReflectError;
use crate::wire_format::WireType;

/// `Result` alias for `ProtobufError`
pub type Result<T> = std::result::Result<T, crate::Error>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug, thiserror::Error)]
pub(crate) enum WireError {
    #[error("Unexpected EOF")]
    UnexpectedEof,
    #[error("Unexpected wire type")]
    UnexpectedWireType(WireType),
    #[error("Incorrect tag")]
    IncorrectTag(u32),
    #[error("Incorrect varint")]
    IncorrectVarint,
    #[error("Invalid UTF-8 sequence")]
    Utf8Error,
    #[error("Invalid enum `{}` value: {}", .0, .1)]
    InvalidEnumValue(&'static str, i32),
    #[error("Over recursion limit")]
    OverRecursionLimit,
    #[error("Truncated message")]
    TruncatedMessage,
    // not really possible
    #[error("Limit overflow")]
    LimitOverflow,
    #[error("New limit must not be greater than current limit")]
    LimitIncrease,
    #[error("Encoded message size {0} is too large")]
    MessageTooLarge(u64),
    #[error("Value too large for u32: {}", .0)]
    U32Overflow(u64),
    #[error("Value too large for i32: {}", .0)]
    I32Overflow(i64),
}

/// Generic protobuf error
#[derive(Debug, thiserror::Error)]
pub(crate) enum ProtobufError {
    /// I/O error when reading or writing
    #[error(transparent)]
    IoError(#[from] io::Error),
    /// Malformed input
    #[error(transparent)]
    WireError(#[from] WireError),
    #[error(transparent)]
    Reflect(#[from] ReflectError),
    /// Protocol contains a string which is not valid UTF-8 string
    #[error("UTF-8 decode error")]
    Utf8(
        #[source]
        #[from]
        str::Utf8Error,
    ),
    /// Not all required fields of message set.
    #[error("Message `{}` is missing required fields", .0)]
    MessageNotInitialized(String),
    /// Protobuf type and runtime types mismatch.
    #[error("Protobuf type and runtime types are not compatible")]
    IncompatibleProtobufTypeAndRuntimeType,
    /// Group field type not implemented.
    #[error("Group field is not supported")]
    GroupIsNotImplemented,
}

/// Error type for protobuf operations.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct Error(pub(crate) Box<ProtobufError>);

impl From<ProtobufError> for Error {
    #[cold]
    fn from(e: ProtobufError) -> Self {
        Self(Box::new(e))
    }
}

impl From<WireError> for Error {
    #[cold]
    fn from(e: WireError) -> Self {
        Self(Box::new(ProtobufError::WireError(e)))
    }
}

impl From<ReflectError> for Error {
    #[cold]
    fn from(e: ReflectError) -> Self {
        Self(Box::new(ProtobufError::Reflect(e)))
    }
}

impl From<Error> for io::Error {
    #[cold]
    fn from(err: Error) -> Self {
        match *err.0 {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}

impl From<io::Error> for Error {
    #[cold]
    fn from(err: io::Error) -> Self {
        Error(Box::new(ProtobufError::IoError(err)))
    }
}

#[cfg(test)]
mod test {
    use std::mem;

    #[test]
    fn error_size() {
        assert_eq!(mem::size_of::<usize>(), mem::size_of::<crate::Error>());
    }
}
<commit_msg>Links<commit_after>use std::io;
use std::str;

use crate::reflect::error::ReflectError;
use crate::wire_format::WireType;

/// [`Result`] alias for [`Error`].
pub type Result<T> = std::result::Result<T, crate::Error>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug, thiserror::Error)]
pub(crate) enum WireError {
    #[error("Unexpected EOF")]
    UnexpectedEof,
    #[error("Unexpected wire type")]
    UnexpectedWireType(WireType),
    #[error("Incorrect tag")]
    IncorrectTag(u32),
    #[error("Incorrect varint")]
    IncorrectVarint,
    #[error("Invalid UTF-8 sequence")]
    Utf8Error,
    #[error("Invalid enum `{}` value: {}", .0, .1)]
    InvalidEnumValue(&'static str, i32),
    #[error("Over recursion limit")]
    OverRecursionLimit,
    #[error("Truncated message")]
    TruncatedMessage,
    // not really possible
    #[error("Limit overflow")]
    LimitOverflow,
    #[error("New limit must not be greater than current limit")]
    LimitIncrease,
    #[error("Encoded message size {0} is too large")]
    MessageTooLarge(u64),
    #[error("Value too large for u32: {}", .0)]
    U32Overflow(u64),
    #[error("Value too large for i32: {}", .0)]
    I32Overflow(i64),
}

/// Generic protobuf error
#[derive(Debug, thiserror::Error)]
pub(crate) enum ProtobufError {
    /// I/O error when reading or writing
    #[error(transparent)]
    IoError(#[from] io::Error),
    /// Malformed input
    #[error(transparent)]
    WireError(#[from] WireError),
    #[error(transparent)]
    Reflect(#[from] ReflectError),
    /// Protocol contains a string which is not valid UTF-8 string
    #[error("UTF-8 decode error")]
    Utf8(
        #[source]
        #[from]
        str::Utf8Error,
    ),
    /// Not all required fields of message set.
    #[error("Message `{}` is missing required fields", .0)]
    MessageNotInitialized(String),
    /// Protobuf type and runtime types mismatch.
    #[error("Protobuf type and runtime types are not compatible")]
    IncompatibleProtobufTypeAndRuntimeType,
    /// Group field type not implemented.
    #[error("Group field is not supported")]
    GroupIsNotImplemented,
}

/// Error type for protobuf operations.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct Error(pub(crate) Box<ProtobufError>);

impl From<ProtobufError> for Error {
    #[cold]
    fn from(e: ProtobufError) -> Self {
        Self(Box::new(e))
    }
}

impl From<WireError> for Error {
    #[cold]
    fn from(e: WireError) -> Self {
        Self(Box::new(ProtobufError::WireError(e)))
    }
}

impl From<ReflectError> for Error {
    #[cold]
    fn from(e: ReflectError) -> Self {
        Self(Box::new(ProtobufError::Reflect(e)))
    }
}

impl From<Error> for io::Error {
    #[cold]
    fn from(err: Error) -> Self {
        match *err.0 {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}

impl From<io::Error> for Error {
    #[cold]
    fn from(err: io::Error) -> Self {
        Error(Box::new(ProtobufError::IoError(err)))
    }
}

#[cfg(test)]
mod test {
    use std::mem;

    #[test]
    fn error_size() {
        assert_eq!(mem::size_of::<usize>(), mem::size_of::<crate::Error>());
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Formatter, Debug};

use backend::Backend;
use super::js_var::{JsPtrEnum, JsVar};

#[derive(Clone)]
pub struct NativeFn(fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>));

impl NativeFn {
    pub fn new(func: fn(Box<Backend>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>)) -> NativeFn
{
      NativeFn(func)
    }

    pub fn call(&self, backend: Box<Backend>, args: Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar,
Option<JsPtrEnum>) {
        self.0(backend, args)
    }
}

impl Debug for NativeFn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "[native_code]")
    }
}
<commit_msg>switch to using Rc<RefCell> instead of Box<commit_after>use std::cell::RefCell;
use std::fmt::{self, Formatter, Debug};
use std::rc::Rc;

use backend::Backend;
use super::js_var::{JsPtrEnum, JsVar};

#[derive(Clone)]
pub struct NativeFn(fn(Rc<RefCell<Backend>>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>));

impl NativeFn {
    pub fn new(func: fn(Rc<RefCell<Backend>>, Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar, Option<JsPtrEnum>)) -> NativeFn
{
      NativeFn(func)
    }

    pub fn call(&self, backend: Rc<RefCell<Backend>>, args: Vec<(JsVar, Option<JsPtrEnum>)>) -> (JsVar,
Option<JsPtrEnum>) {
        self.0(backend, args)
    }
}

impl Debug for NativeFn {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "[native_code]")
    }
}
<|endoftext|>