<commit_before>use std::slice;
use std::libc::{c_int, c_char};
use std::str::raw;
use std::os::getenv;
use std::path::Path;
use gdal::driver::Driver;
use gdal::register_drivers;
use gdal::geom::Point;

#[link(name="gdal")]
extern {
    fn GDALCreateCopy(
            hDriver: *(),
            pszFilename: *c_char,
            hSrcDS: *(),
            bStrict: c_int,
            papszOptions: **c_char,
            pfnProgres: *(),
            pProgressData: *()
        ) -> *();
    fn GDALOpen(pszFilename: *c_char, eAccess: c_int) -> *();
    fn GDALClose(hDS: *());
    fn GDALGetDatasetDriver(hDataset: *()) -> *();
    fn GDALGetRasterXSize(hDataset: *()) -> c_int;
    fn GDALGetRasterYSize(hDataset: *()) -> c_int;
    fn GDALGetRasterCount(hDataset: *()) -> c_int;
    fn GDALGetProjectionRef(hDS: *()) -> *c_char;
    fn GDALSetProjection(hDS: *(), pszProjection: *c_char) -> c_int;
    fn GDALGetRasterBand(hDS: *(), nBandId: c_int) -> *();
    fn GDALRasterIO(
            hBand: *(),
            eRWFlag: c_int,
            nXOff: c_int,
            nYOff: c_int,
            nXSize: c_int,
            nYSize: c_int,
            pData: *(),
            nBufXSize: c_int,
            nBufYSize: c_int,
            GDALDataType: c_int,
            nPixelSpace: c_int,
            nLineSpace: c_int
        ) -> c_int;
}

static GA_ReadOnly:  c_int = 0;
static GA_Update:    c_int = 1;

static GDT_Unknown:  c_int = 0;
static GDT_Byte:     c_int = 1;
static GDT_UInt16:   c_int = 2;
static GDT_Int16:    c_int = 3;
static GDT_UInt32:   c_int = 4;
static GDT_Int32:    c_int = 5;
static GDT_Float32:  c_int = 6;
static GDT_Float64:  c_int = 7;
static GDT_CInt16:   c_int = 8;
static GDT_CInt32:   c_int = 9;
static GDT_CFloat32: c_int = 10;
static GDT_CFloat64: c_int = 11;

static GF_Read:      c_int = 0;
static GF_Write:     c_int = 1;

pub struct Dataset {
    c_dataset: *(),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn get_raster_size(&self) -> (int, int) {
        let size_x = unsafe { GDALGetRasterXSize(self.c_dataset) } as int;
        let size_y = unsafe { GDALGetRasterYSize(self.c_dataset) } as int;
        return (size_x, size_y);
    }

    pub fn get_driver(&self) -> Driver {
        let c_driver = unsafe { GDALGetDatasetDriver(self.c_dataset) };
        return Driver{c_driver: c_driver};
    }

    pub fn get_raster_count(&self) -> int {
        return unsafe { GDALGetRasterCount(self.c_dataset) } as int;
    }

    pub fn get_projection(&self) -> ~str {
        unsafe {
            let rv = GDALGetProjectionRef(self.c_dataset);
            return raw::from_c_str(rv);
        }
    }

    pub fn set_projection(&self, projection: &str) {
        projection.with_c_str(|c_projection| {
            unsafe { GDALSetProjection(self.c_dataset, c_projection) };
        });
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_dataset = filename.with_c_str(|c_filename| {
            unsafe {
                return GDALCreateCopy(
                    driver.c_driver,
                    c_filename,
                    self.c_dataset,
                    0,
                    null(),
                    null(),
                    null()
                )
            }
        });
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(
        &self,
        band_index: int,
        window: Point<int>,
        window_size: Point<uint>,
        buffer_size: Point<uint>
    ) -> ByteBuffer {
        let buffer_size_bytes = buffer_size.x * buffer_size.y;
        let mut data: ~[u8] = slice::with_capacity(buffer_size_bytes);
        for _ in range(0, buffer_size_bytes) { data.push(0u8); } // TODO zero fill
        unsafe {
            let c_band = GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = GDALRasterIO(
                c_band,
                GF_Read,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *(),
                buffer_size.x as c_int,
                buffer_size.y as c_int,
                GDT_Byte,
                0,
                0
            ) as int;
            assert!(rv == 0);
        };
        return ByteBuffer{
            width: buffer_size.x,
            height: buffer_size.y,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: int,
        window: Point<int>,
        window_size: Point<uint>,
        buffer: ByteBuffer
    ) {
        unsafe {
            let c_band = GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = GDALRasterIO(
                c_band,
                GF_Write,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *(),
                buffer.width as c_int,
                buffer.height as c_int,
                GDT_Byte,
                0,
                0
            ) as int;
            assert!(rv == 0);
        };
    }
}

pub fn open(path: &Path) -> Option<Dataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { GDALOpen(c_filename, GA_ReadOnly) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(Dataset{c_dataset: c_dataset}),
    };
}

struct ByteBuffer {
    width: uint,
    height: uint,
    data: ~[u8],
}

fn fixture_path(name: &str) -> Path {
    let envvar = "RUSTILES_TEST_FIXTURES";
    let fixtures = match getenv(envvar) {
        Some(p) => Path::new(p),
        None => fail!("Environment variable {} not set", envvar)
    };
    let rv = fixtures.join(name);
    return rv;
}

#[test]
fn test_open() {
    let dataset = open(&fixture_path("tinymarble.jpeg"));
    assert!(dataset.is_some());

    let missing_dataset = open(&fixture_path("no_such_file.jpeg"));
    assert!(missing_dataset.is_none());
}

#[test]
fn test_get_raster_size() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let (size_x, size_y) = dataset.get_raster_size();
    assert_eq!(size_x, 100);
    assert_eq!(size_y, 50);
}

#[test]
fn test_get_raster_count() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let count = dataset.get_raster_count();
    assert_eq!(count, 3);
}

#[test]
fn test_get_projection() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    //dataset.set_projection("WGS84");
    let projection = dataset.get_projection();
    assert_eq!(projection.slice(0, 16), "GEOGCS[\"WGS 84\",");
}

#[test]
fn test_read_raster() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let rv = dataset.read_raster(1, Point(20, 30), Point(10, 10), Point(3, 5));
    assert_eq!(rv.width, 3);
    assert_eq!(rv.height, 5);
    assert_eq!(rv.data, ~[13, 3, 18, 6, 9, 1, 2, 9, 4, 6, 11, 4, 6, 2, 9]);
}

#[test]
fn test_write_raster() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = driver.create("", 20, 10, 1).unwrap();

    // create a 2x1 raster
    let raster = ByteBuffer{width: 2, height: 1, data: ~[50u8, 20u8]};

    // epand it to fill the image (20x10)
    dataset.write_raster(1, Point(0, 0), Point(20, 10), raster);

    // read a pixel from the left side
    let left = dataset.read_raster(1, Point(5, 5), Point(1, 1), Point(1, 1));
    assert_eq!(left.data[0], 50u8);

    // read a pixel from the right side
    let right = dataset.read_raster(1, Point(15, 5), Point(1, 1), Point(1, 1));
    assert_eq!(right.data[0], 20u8);
}

#[test]
fn test_get_dataset_driver() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let driver = dataset.get_driver();
    assert_eq!(driver.get_short_name(), ~"JPEG");
    assert_eq!(driver.get_long_name(), ~"JPEG JFIF");
}

#[test]
fn test_create() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = driver.create("", 10, 20, 3).unwrap();
    assert_eq!(dataset.get_raster_size(), (10, 20));
    assert_eq!(dataset.get_raster_count(), 3);
    assert_eq!(dataset.get_driver().get_short_name(), ~"MEM");
}

#[test]
fn test_create_copy() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let copy = dataset.create_copy(driver, "").unwrap();
    assert_eq!(copy.get_raster_size(), (100, 50));
    assert_eq!(copy.get_raster_count(), 3);
}
<commit_msg>store buffer size as Point<commit_after>use std::slice;
use std::libc::{c_int, c_char};
use std::str::raw;
use std::os::getenv;
use std::path::Path;
use gdal::driver::Driver;
use gdal::register_drivers;
use gdal::geom::Point;

#[link(name="gdal")]
extern {
    fn GDALCreateCopy(
            hDriver: *(),
            pszFilename: *c_char,
            hSrcDS: *(),
            bStrict: c_int,
            papszOptions: **c_char,
            pfnProgres: *(),
            pProgressData: *()
        ) -> *();
    fn GDALOpen(pszFilename: *c_char, eAccess: c_int) -> *();
    fn GDALClose(hDS: *());
    fn GDALGetDatasetDriver(hDataset: *()) -> *();
    fn GDALGetRasterXSize(hDataset: *()) -> c_int;
    fn GDALGetRasterYSize(hDataset: *()) -> c_int;
    fn GDALGetRasterCount(hDataset: *()) -> c_int;
    fn GDALGetProjectionRef(hDS: *()) -> *c_char;
    fn GDALSetProjection(hDS: *(), pszProjection: *c_char) -> c_int;
    fn GDALGetRasterBand(hDS: *(), nBandId: c_int) -> *();
    fn GDALRasterIO(
            hBand: *(),
            eRWFlag: c_int,
            nXOff: c_int,
            nYOff: c_int,
            nXSize: c_int,
            nYSize: c_int,
            pData: *(),
            nBufXSize: c_int,
            nBufYSize: c_int,
            GDALDataType: c_int,
            nPixelSpace: c_int,
            nLineSpace: c_int
        ) -> c_int;
}

static GA_ReadOnly:  c_int = 0;
static GA_Update:    c_int = 1;

static GDT_Unknown:  c_int = 0;
static GDT_Byte:     c_int = 1;
static GDT_UInt16:   c_int = 2;
static GDT_Int16:    c_int = 3;
static GDT_UInt32:   c_int = 4;
static GDT_Int32:    c_int = 5;
static GDT_Float32:  c_int = 6;
static GDT_Float64:  c_int = 7;
static GDT_CInt16:   c_int = 8;
static GDT_CInt32:   c_int = 9;
static GDT_CFloat32: c_int = 10;
static GDT_CFloat64: c_int = 11;

static GF_Read:      c_int = 0;
static GF_Write:     c_int = 1;

pub struct Dataset {
    c_dataset: *(),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn get_raster_size(&self) -> (int, int) {
        let size_x = unsafe { GDALGetRasterXSize(self.c_dataset) } as int;
        let size_y = unsafe { GDALGetRasterYSize(self.c_dataset) } as int;
        return (size_x, size_y);
    }

    pub fn get_driver(&self) -> Driver {
        let c_driver = unsafe { GDALGetDatasetDriver(self.c_dataset) };
        return Driver{c_driver: c_driver};
    }

    pub fn get_raster_count(&self) -> int {
        return unsafe { GDALGetRasterCount(self.c_dataset) } as int;
    }

    pub fn get_projection(&self) -> ~str {
        unsafe {
            let rv = GDALGetProjectionRef(self.c_dataset);
            return raw::from_c_str(rv);
        }
    }

    pub fn set_projection(&self, projection: &str) {
        projection.with_c_str(|c_projection| {
            unsafe { GDALSetProjection(self.c_dataset, c_projection) };
        });
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_dataset = filename.with_c_str(|c_filename| {
            unsafe {
                return GDALCreateCopy(
                    driver.c_driver,
                    c_filename,
                    self.c_dataset,
                    0,
                    null(),
                    null(),
                    null()
                )
            }
        });
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(
        &self,
        band_index: int,
        window: Point<int>,
        window_size: Point<uint>,
        buffer_size: Point<uint>
    ) -> ByteBuffer {
        let buffer_size_bytes = buffer_size.x * buffer_size.y;
        let mut data: ~[u8] = slice::with_capacity(buffer_size_bytes);
        for _ in range(0, buffer_size_bytes) { data.push(0u8); } // TODO zero fill
        unsafe {
            let c_band = GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = GDALRasterIO(
                c_band,
                GF_Read,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *(),
                buffer_size.x as c_int,
                buffer_size.y as c_int,
                GDT_Byte,
                0,
                0
            ) as int;
            assert!(rv == 0);
        };
        return ByteBuffer{
            size: buffer_size,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: int,
        window: Point<int>,
        window_size: Point<uint>,
        buffer: ByteBuffer
    ) {
        unsafe {
            let c_band = GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = GDALRasterIO(
                c_band,
                GF_Write,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *(),
                buffer.size.x as c_int,
                buffer.size.y as c_int,
                GDT_Byte,
                0,
                0
            ) as int;
            assert!(rv == 0);
        };
    }
}

pub fn open(path: &Path) -> Option<Dataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { GDALOpen(c_filename, GA_ReadOnly) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(Dataset{c_dataset: c_dataset}),
    };
}

struct ByteBuffer {
    size: Point<uint>,
    data: ~[u8],
}

fn fixture_path(name: &str) -> Path {
    let envvar = "RUSTILES_TEST_FIXTURES";
    let fixtures = match getenv(envvar) {
        Some(p) => Path::new(p),
        None => fail!("Environment variable {} not set", envvar)
    };
    let rv = fixtures.join(name);
    return rv;
}

#[test]
fn test_open() {
    let dataset = open(&fixture_path("tinymarble.jpeg"));
    assert!(dataset.is_some());

    let missing_dataset = open(&fixture_path("no_such_file.jpeg"));
    assert!(missing_dataset.is_none());
}

#[test]
fn test_get_raster_size() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let (size_x, size_y) = dataset.get_raster_size();
    assert_eq!(size_x, 100);
    assert_eq!(size_y, 50);
}

#[test]
fn test_get_raster_count() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let count = dataset.get_raster_count();
    assert_eq!(count, 3);
}

#[test]
fn test_get_projection() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    //dataset.set_projection("WGS84");
    let projection = dataset.get_projection();
    assert_eq!(projection.slice(0, 16), "GEOGCS[\"WGS 84\",");
}

#[test]
fn test_read_raster() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let rv = dataset.read_raster(1, Point(20, 30), Point(10, 10), Point(3, 5));
    assert_eq!(rv.size.x, 3);
    assert_eq!(rv.size.y, 5);
    assert_eq!(rv.data, ~[13, 3, 18, 6, 9, 1, 2, 9, 4, 6, 11, 4, 6, 2, 9]);
}

#[test]
fn test_write_raster() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = driver.create("", 20, 10, 1).unwrap();

    // create a 2x1 raster
    let raster = ByteBuffer{size: Point(2, 1), data: ~[50u8, 20u8]};

    // epand it to fill the image (20x10)
    dataset.write_raster(1, Point(0, 0), Point(20, 10), raster);

    // read a pixel from the left side
    let left = dataset.read_raster(1, Point(5, 5), Point(1, 1), Point(1, 1));
    assert_eq!(left.data[0], 50u8);

    // read a pixel from the right side
    let right = dataset.read_raster(1, Point(15, 5), Point(1, 1), Point(1, 1));
    assert_eq!(right.data[0], 20u8);
}

#[test]
fn test_get_dataset_driver() {
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let driver = dataset.get_driver();
    assert_eq!(driver.get_short_name(), ~"JPEG");
    assert_eq!(driver.get_long_name(), ~"JPEG JFIF");
}

#[test]
fn test_create() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = driver.create("", 10, 20, 3).unwrap();
    assert_eq!(dataset.get_raster_size(), (10, 20));
    assert_eq!(dataset.get_raster_count(), 3);
    assert_eq!(dataset.get_driver().get_short_name(), ~"MEM");
}

#[test]
fn test_create_copy() {
    use gdal::driver::get_driver;
    let driver = get_driver("MEM").unwrap();
    let dataset = open(&fixture_path("tinymarble.jpeg")).unwrap();
    let copy = dataset.create_copy(driver, "").unwrap();
    assert_eq!(copy.get_raster_size(), (100, 50));
    assert_eq!(copy.get_raster_count(), 3);
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, Seek, SeekFrom, Write};
use std::marker::PhantomData;
use std::ops::{DerefMut, Range};

/** A private type trait for the ability to efficiently implement stream skipping.
 */
pub trait ForwardSeek {
    fn skip(&mut self, n: u64) -> io::Result<u64>;
}

impl<S: ?Sized> ForwardSeek for S
where
    S: Seek,
{
    fn skip(&mut self, n: u64) -> io::Result<u64> {
        let curr_pos = self.seek(SeekFrom::Current(0))?;
        let new_pos = self.seek(SeekFrom::Current(n as i64))?;
        Ok(new_pos - curr_pos)
    }
}

pub trait ReadSeek: Read + Seek {}
impl<T: ?Sized> ReadSeek for T where T: Read + Seek {}

#[derive(Debug)]
pub struct SeekInterval<S: ?Sized, B: DerefMut<Target = S>> {
    source: B,
    current: u64,
    begin: u64,
    end: u64,
    marker: PhantomData<S>,
}

impl<S: ?Sized, B> SeekInterval<S, B>
where
    S: Seek,
    B: DerefMut<Target = S>,
{
    /// Create an interval from the current position and ending
    /// after `n` bytes.
    pub fn new_here(mut source: B, n: u32) -> io::Result<Self> {
        let pos = source.seek(SeekFrom::Current(0))?;
        Ok(SeekInterval {
            source,
            current: pos,
            begin: pos,
            end: pos + u64::from(n),
            marker: PhantomData,
        })
    }

    /// Create an interval that starts and ends according to the given
    /// range of bytes.
    pub fn new_at(mut source: B, range: Range<u64>) -> io::Result<Self> {
        let pos = source.seek(SeekFrom::Start(range.start))?;
        Ok(SeekInterval {
            source,
            current: pos,
            begin: pos,
            end: range.end,
            marker: PhantomData,
        })
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.end - self.current) as usize
    }
}

impl<S: ?Sized, B> Seek for SeekInterval<S, B>
where
    S: Seek,
    B: DerefMut<Target = S>,
{
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        match pos {
            SeekFrom::Start(o) => self
                .source
                .seek(SeekFrom::Start(self.begin + o))
                .map(|v| v - self.begin),
            pos @ SeekFrom::Current(_) => self.source.seek(pos).map(|v| v - self.begin),
            SeekFrom::End(o) => self
                .source
                .seek(SeekFrom::Start((self.end as i64 + o) as u64))
                .map(|v| v - self.begin),
        }
    }
}

impl<S: ?Sized + Seek, B> Read for SeekInterval<S, B>
where
    S: Read,
    B: DerefMut<Target = S>,
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let r = self.remaining();
        let buf = if buf.len() > r { &mut buf[0..r] } else { buf };

        self.source.read(buf)
    }
}

impl<S: ?Sized, B> Write for SeekInterval<S, B>
where
    S: Write + Seek,
    B: DerefMut<Target = S>,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let r = self.remaining();

        let buf = if buf.len() > r { &buf[0..r] } else { buf };

        self.source.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.source.flush()
    }
}

#[cfg(test)]
mod tests {
    use super::SeekInterval;
    use std::io::{Cursor, Write};

    #[test]
    fn seek_interval_writing_here() {
        let mut buf = Cursor::new(vec![0xFFu8; 8]);
        {
            let mut interval = SeekInterval::new_here(&mut buf, 5).unwrap();
            let count = interval.write(&vec![0; 8]).unwrap();
            assert_eq!(count, 5);
        }
        assert_eq!(
            buf.into_inner(),
            vec![0, 0, 0, 0, 0, 0xFFu8, 0xFFu8, 0xFFu8]
        )
    }

    #[test]
    fn seek_interval_writing() {
        let mut buf = Cursor::new(vec![0xFFu8; 8]);
        {
            let mut interval = SeekInterval::new_at(&mut buf, 2..8).unwrap();
            let count = interval.write(&vec![0; 8]).unwrap();
            assert_eq!(count, 6);
        }
        assert_eq!(buf.into_inner(), vec![0xFFu8, 0xFF, 0, 0, 0, 0, 0, 0])
    }
}
<commit_msg>Mark test only functions as cfg(test)<commit_after>use std::io;
use std::io::{Read, Seek, SeekFrom, Write};
use std::marker::PhantomData;
use std::ops::DerefMut;
#[cfg(test)]
use std::ops::Range;

/** A private type trait for the ability to efficiently implement stream skipping.
 */
pub trait ForwardSeek {
    fn skip(&mut self, n: u64) -> io::Result<u64>;
}

impl<S: ?Sized> ForwardSeek for S
where
    S: Seek,
{
    fn skip(&mut self, n: u64) -> io::Result<u64> {
        let curr_pos = self.seek(SeekFrom::Current(0))?;
        let new_pos = self.seek(SeekFrom::Current(n as i64))?;
        Ok(new_pos - curr_pos)
    }
}

pub trait ReadSeek: Read + Seek {}
impl<T: ?Sized> ReadSeek for T where T: Read + Seek {}

#[derive(Debug)]
pub struct SeekInterval<S: ?Sized, B: DerefMut<Target = S>> {
    source: B,
    current: u64,
    begin: u64,
    end: u64,
    marker: PhantomData<S>,
}

impl<S: ?Sized, B> SeekInterval<S, B>
where
    S: Seek,
    B: DerefMut<Target = S>,
{
    #[cfg(test)]
    /// Create an interval from the current position and ending
    /// after `n` bytes.
    pub fn new_here(mut source: B, n: u32) -> io::Result<Self> {
        let pos = source.seek(SeekFrom::Current(0))?;
        Ok(SeekInterval {
            source,
            current: pos,
            begin: pos,
            end: pos + u64::from(n),
            marker: PhantomData,
        })
    }

    #[cfg(test)]
    /// Create an interval that starts and ends according to the given
    /// range of bytes.
    pub fn new_at(mut source: B, range: Range<u64>) -> io::Result<Self> {
        let pos = source.seek(SeekFrom::Start(range.start))?;
        Ok(SeekInterval {
            source,
            current: pos,
            begin: pos,
            end: range.end,
            marker: PhantomData,
        })
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.end - self.current) as usize
    }
}

impl<S: ?Sized, B> Seek for SeekInterval<S, B>
where
    S: Seek,
    B: DerefMut<Target = S>,
{
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        match pos {
            SeekFrom::Start(o) => self
                .source
                .seek(SeekFrom::Start(self.begin + o))
                .map(|v| v - self.begin),
            pos @ SeekFrom::Current(_) => self.source.seek(pos).map(|v| v - self.begin),
            SeekFrom::End(o) => self
                .source
                .seek(SeekFrom::Start((self.end as i64 + o) as u64))
                .map(|v| v - self.begin),
        }
    }
}

impl<S: ?Sized + Seek, B> Read for SeekInterval<S, B>
where
    S: Read,
    B: DerefMut<Target = S>,
{
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let r = self.remaining();
        let buf = if buf.len() > r { &mut buf[0..r] } else { buf };

        self.source.read(buf)
    }
}

impl<S: ?Sized, B> Write for SeekInterval<S, B>
where
    S: Write + Seek,
    B: DerefMut<Target = S>,
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let r = self.remaining();

        let buf = if buf.len() > r { &buf[0..r] } else { buf };

        self.source.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.source.flush()
    }
}

#[cfg(test)]
mod tests {
    use super::SeekInterval;
    use std::io::{Cursor, Write};

    #[test]
    fn seek_interval_writing_here() {
        let mut buf = Cursor::new(vec![0xFFu8; 8]);
        {
            let mut interval = SeekInterval::new_here(&mut buf, 5).unwrap();
            let count = interval.write(&vec![0; 8]).unwrap();
            assert_eq!(count, 5);
        }
        assert_eq!(
            buf.into_inner(),
            vec![0, 0, 0, 0, 0, 0xFFu8, 0xFFu8, 0xFFu8]
        )
    }

    #[test]
    fn seek_interval_writing() {
        let mut buf = Cursor::new(vec![0xFFu8; 8]);
        {
            let mut interval = SeekInterval::new_at(&mut buf, 2..8).unwrap();
            let count = interval.write(&vec![0; 8]).unwrap();
            assert_eq!(count, 6);
        }
        assert_eq!(buf.into_inner(), vec![0xFFu8, 0xFF, 0, 0, 0, 0, 0, 0])
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

use super::point::Point;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Polygon {
   pub points: Vec<Point>
}

impl Polygon {
   pub fn new(points: Vec<Point>) -> Self {
      Polygon {
         points: points
      }
   }
}

#[derive(Debug, PartialEq, Eq, Ord, Clone, Copy)]
pub struct Edge {
   pub p1: Point,
   pub p2: Point,
   pub dx: i64,
   pub dy: i64,
}

impl Edge {
   fn new(a1: &Point, a2: &Point) -> Self {
      let (p1, p2) = if a1 < a2 {
         (a1, a2)
      } else {
         (a2, a1)
      };

      Edge {
         p1: *p1,
         p2: *p2,
         dx: p2.x - p1.x,
         dy: p2.y - p1.y,
      }
   }
}

impl PartialOrd for Edge {
   fn partial_cmp(&self, other: &Edge) -> Option<Ordering> {
      Some(
         match self.p1.cmp(&other.p1) {
            Ordering::Greater => {
               Ordering::Greater
            },
            Ordering::Less => {
               Ordering::Less
            },
            Ordering::Equal => {
               if self.dy == 0 {
                  if other.dy == 0 {
                     self.dx.cmp(&other.dx)
                  } else {
                     if self.dx > 0 {
                        Ordering::Greater
                     } else {
                        Ordering::Less
                     }
                  }
               } else if other.dy == 0 {
                  if other.dx > 0 {
                     Ordering::Less
                  } else {
                     Ordering::Greater
                  }
               } else {
                  match (self.dx * other.dy).cmp(&(self.dy * other.dx)) {
                     Ordering::Greater => {
                        Ordering::Greater
                     },
                     Ordering::Less => {
                        Ordering::Less
                     },
                     Ordering::Equal => {
                        self.p2.cmp(&other.p2)
                     }
                  }
               }
            }
         }
      )
   }
}

fn cmp_edges_by_y(first: &Edge, second: &Edge) -> Ordering {
   first.p1.y.cmp(&second.p1.y)
}

pub fn to_scanline_edges(points: &Vec<Point>) -> Vec<Edge> {
   let mut edges = Vec::new();

   let mut p1 = points.last().unwrap();

   for p2 in points.iter() {
      let edge = Edge::new(p1, p2);

      if edge.dy != 0 {
         edges.push(edge);
      }

      p1 = p2
   }

   edges.sort_by(cmp_edges_by_y);

   edges
}

#[inline]
pub fn orientation(a: &Point, b: &Point, c: &Point) -> i64 {
   (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
}
<commit_msg>Polygon area function<commit_after>use std::cmp::Ordering;

use super::point::Point;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Polygon {
   pub points: Vec<Point>
}

impl Polygon {
   pub fn new(points: Vec<Point>) -> Self {
      Polygon {
         points: points
      }
   }
}

#[derive(Debug, PartialEq, Eq, Ord, Clone, Copy)]
pub struct Edge {
   pub p1: Point,
   pub p2: Point,
   pub dx: i64,
   pub dy: i64,
}

impl Edge {
   fn new(a1: &Point, a2: &Point) -> Self {
      let (p1, p2) = if a1 < a2 {
         (a1, a2)
      } else {
         (a2, a1)
      };

      Edge {
         p1: *p1,
         p2: *p2,
         dx: p2.x - p1.x,
         dy: p2.y - p1.y,
      }
   }
}

impl PartialOrd for Edge {
   fn partial_cmp(&self, other: &Edge) -> Option<Ordering> {
      Some(
         match self.p1.cmp(&other.p1) {
            Ordering::Greater => {
               Ordering::Greater
            },
            Ordering::Less => {
               Ordering::Less
            },
            Ordering::Equal => {
               if self.dy == 0 {
                  if other.dy == 0 {
                     self.dx.cmp(&other.dx)
                  } else {
                     if self.dx > 0 {
                        Ordering::Greater
                     } else {
                        Ordering::Less
                     }
                  }
               } else if other.dy == 0 {
                  if other.dx > 0 {
                     Ordering::Less
                  } else {
                     Ordering::Greater
                  }
               } else {
                  match (self.dx * other.dy).cmp(&(self.dy * other.dx)) {
                     Ordering::Greater => {
                        Ordering::Greater
                     },
                     Ordering::Less => {
                        Ordering::Less
                     },
                     Ordering::Equal => {
                        self.p2.cmp(&other.p2)
                     }
                  }
               }
            }
         }
      )
   }
}

fn cmp_edges_by_y(first: &Edge, second: &Edge) -> Ordering {
   first.p1.y.cmp(&second.p1.y)
}

pub fn to_scanline_edges(points: &Vec<Point>) -> Vec<Edge> {
   let mut edges = Vec::new();

   let mut p1 = points.last().unwrap();

   for p2 in points.iter() {
      let edge = Edge::new(p1, p2);

      if edge.dy != 0 {
         edges.push(edge);
      }

      p1 = p2
   }

   edges.sort_by(cmp_edges_by_y);

   edges
}

#[inline]
pub fn orientation(a: &Point, b: &Point, c: &Point) -> i64 {
   (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
}

pub fn double_polygon_area(start: usize, points: &Vec<Point>) -> i64 {
   let mut p1 = points.last().unwrap();

   let mut area = 0;

   for p2 in points[start..].iter() {
      area += p1.x * p2.y - p1.y * p2.x;

      p1 = p2;
   }

   area.abs()
}
<|endoftext|>


<commit_before>// Copyright Cryptape Technologies LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::contracts::tools::method as method_tools;
// use crate::engines::NullEngine;
use crate::libexecutor::block::EVMBlockDataProvider;
use crate::types::reserved_addresses;
use cita_types::{Address, H160, U256};
// use evm::{Factory, VMType};
use std::str::FromStr;
// use util::BytesRef;
use crate::cita_executive::{
    build_evm_context, build_vm_exec_params, call as vm_call, ExecutiveParams,
};
use crate::cita_vm_helper::get_interpreter_conf;
use crate::data_provider::Store as VMSubState;
use crate::libexecutor::executor::CitaTrieDB;
use crate::types::context::Context;
use cita_vm::evm::InterpreterResult;
use cita_vm::state::State as CitaState;
use std::cell::RefCell;
use std::sync::Arc;

const AUTO_EXEC: &[u8] = &*b"autoExec()";

lazy_static! {
    static ref AUTO_EXEC_ADDR: H160 = H160::from_str(reserved_addresses::AUTO_EXEC).unwrap();
    static ref AUTO_EXEC_HASH: Vec<u8> = method_tools::encode_to_vec(AUTO_EXEC);
}

pub fn auto_exec(
    state: Arc<RefCell<CitaState<CitaTrieDB>>>,
    auto_exec_quota_limit: u64,
    context: Context,
) {
    let hash = &*AUTO_EXEC_HASH;
    let params = ExecutiveParams {
        code_address: Some(*AUTO_EXEC_ADDR),
        sender: Address::from(0x0),
        to_address: Some(*AUTO_EXEC_ADDR),
        gas: U256::from(auto_exec_quota_limit),
        gas_price: U256::from(1),
        value: U256::from(0),
        nonce: U256::from(0),
        data: Some(hash.to_vec()),
    };
    let block_provider = EVMBlockDataProvider::new(context.clone());
    let vm_exec_params = build_vm_exec_params(&params, state.clone());
    let mut sub_state = VMSubState::default();

    sub_state.evm_context = build_evm_context(&context.clone());
    sub_state.evm_cfg = get_interpreter_conf();
    let sub_state = Arc::new(RefCell::new(sub_state));

    match vm_call(
        Arc::new(block_provider),
        state.clone(),
        sub_state.clone(),
        &vm_exec_params.into(),
    ) {
        Ok(res) => match res {
            InterpreterResult::Normal(_, _, _) => {
                trace!("Auto exec run succeed.");
            }
            InterpreterResult::Revert(_, _) => {
                info!("Auto exec run Revert!");
            }
            _ => {
                info!("Auto exec should not run as create");
            }
        },
        Err(e) => info!("Auto exec failed: {}", e),
    }
}
<commit_msg>Delete unused comments<commit_after>// Copyright Cryptape Technologies LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::cita_executive::{
    build_evm_context, build_vm_exec_params, call as vm_call, ExecutiveParams,
};
use crate::cita_vm_helper::get_interpreter_conf;
use crate::contracts::tools::method as method_tools;
use crate::data_provider::Store as VMSubState;
use crate::libexecutor::block::EVMBlockDataProvider;
use crate::libexecutor::executor::CitaTrieDB;
use crate::types::context::Context;
use crate::types::reserved_addresses;
use cita_types::{Address, H160, U256};
use cita_vm::evm::InterpreterResult;
use cita_vm::state::State as CitaState;
use std::cell::RefCell;
use std::str::FromStr;
use std::sync::Arc;

const AUTO_EXEC: &[u8] = &*b"autoExec()";

lazy_static! {
    static ref AUTO_EXEC_ADDR: H160 = H160::from_str(reserved_addresses::AUTO_EXEC).unwrap();
    static ref AUTO_EXEC_HASH: Vec<u8> = method_tools::encode_to_vec(AUTO_EXEC);
}

pub fn auto_exec(
    state: Arc<RefCell<CitaState<CitaTrieDB>>>,
    auto_exec_quota_limit: u64,
    context: Context,
) {
    let hash = &*AUTO_EXEC_HASH;
    let params = ExecutiveParams {
        code_address: Some(*AUTO_EXEC_ADDR),
        sender: Address::from(0x0),
        to_address: Some(*AUTO_EXEC_ADDR),
        gas: U256::from(auto_exec_quota_limit),
        gas_price: U256::from(1),
        value: U256::from(0),
        nonce: U256::from(0),
        data: Some(hash.to_vec()),
    };
    let block_provider = EVMBlockDataProvider::new(context.clone());
    let vm_exec_params = build_vm_exec_params(&params, state.clone());
    let mut sub_state = VMSubState::default();

    sub_state.evm_context = build_evm_context(&context.clone());
    sub_state.evm_cfg = get_interpreter_conf();
    let sub_state = Arc::new(RefCell::new(sub_state));

    match vm_call(
        Arc::new(block_provider),
        state.clone(),
        sub_state.clone(),
        &vm_exec_params.into(),
    ) {
        Ok(res) => match res {
            InterpreterResult::Normal(_, _, _) => {
                trace!("Auto exec run succeed.");
            }
            InterpreterResult::Revert(_, _) => {
                info!("Auto exec run Revert!");
            }
            _ => {
                info!("Auto exec should not run as create");
            }
        },
        Err(e) => info!("Auto exec failed: {}", e),
    }
}
<|endoftext|>


<commit_before>//! Paths and Unix shells
//!
//! MacOS, Linux, FreeBSD, and many other OS model their design on Unix,
//! so handling them is relatively consistent. But only relatively.
//! POSIX postdates Unix by 20 years, and each "Unix-like" shell develops
//! unique quirks over time.
//!
//!
//! Windowing Managers, Desktop Environments, GUI Terminals, and PATHs
//!
//! Duplicating paths in PATH can cause performance issues when the OS searches
//! the same place multiple times. Traditionally, Unix configurations have
//! resolved this by setting up PATHs in the shell's login profile.
//!
//! This has its own issues. Login profiles are only intended to run once, but
//! changing the PATH is common enough that people may run it twice. Desktop
//! environments often choose to NOT start login shells in GUI terminals. Thus,
//! a trend has emerged to place PATH updates in other run-commands (rc) files,
//! leaving Rustup with few assumptions to build on for fulfilling its promise
//! to set up PATH appropriately.
//!
//! Rustup addresses this by:
//! 1) using a shell script that updates PATH if the path is not in PATH
//! 2) sourcing this script in any known and appropriate rc file

use super::*;
use crate::process;
use error_chain::bail;
use std::path::PathBuf;

pub type Shell = Box<dyn UnixShell>;

#[derive(Debug, PartialEq)]
pub struct ShellScript {
    content: &'static str,
    name: &'static str,
}

impl ShellScript {
    pub fn write(&self) -> Result<()> {
        let home = utils::cargo_home()?;
        let cargo_bin = format!("{}/bin", cargo_home_str()?);
        let env_name = home.join(self.name);
        let env_file = self.content.replace("{cargo_bin}", &cargo_bin);
        utils::write_file(self.name, &env_name, &env_file)?;
        Ok(())
    }
}

// TODO: Update into a bytestring.
pub fn cargo_home_str() -> Result<Cow<'static, str>> {
    let path = utils::cargo_home()?;

    let default_cargo_home = utils::home_dir()
        .unwrap_or_else(|| PathBuf::from("."))
        .join(".cargo");
    Ok(if default_cargo_home == path {
        "$HOME/.cargo".into()
    } else {
        match path.to_str() {
            Some(p) => p.to_owned().into(),
            None => bail!("Non-Unicode path!"),
        }
    })
}

// TODO: Tcsh (BSD)
// TODO?: Make a decision on Ion Shell, Power Shell, Nushell
// Cross-platform non-POSIX shells have not been assessed for integration yet
fn enumerate_shells() -> Vec<Shell> {
    vec![Box::new(Posix), Box::new(Bash), Box::new(Zsh)]
}

pub fn get_available_shells() -> impl Iterator<Item = Shell> {
    enumerate_shells().into_iter().filter(|sh| sh.does_exist())
}

pub trait UnixShell {
    // Detects if a shell "exists". Users have multiple shells, so an "eager"
    // heuristic should be used, assuming shells exist if any traces do.
    fn does_exist(&self) -> bool;

    // Gives all rcfiles of a given shell that rustup is concerned with.
    // Used primarily in checking rcfiles for cleanup.
    fn rcfiles(&self) -> Vec<PathBuf>;

    // Gives rcs that should be written to.
    fn update_rcs(&self) -> Vec<PathBuf>;

    // Writes the relevant env file.
    fn env_script(&self) -> ShellScript {
        ShellScript {
            name: "env.sh",
            content: include_str!("env.sh"),
        }
    }

    fn source_string(&self) -> Result<String> {
        Ok(format!(r#"source "{}/env.sh""#, cargo_home_str()?))
    }
}

struct Posix;
impl UnixShell for Posix {
    fn does_exist(&self) -> bool {
        true
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        match utils::home_dir() {
            Some(dir) => vec![dir.join(".profile")],
            _ => vec![],
        }
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        // Write to .profile even if it doesn't exist.
        self.rcfiles()
    }
}

struct Bash;

impl Bash {
    fn profiles() -> impl Iterator<Item = PathBuf> {
        [".bash_profile", ".bash_login", ".profile", ".bashrc"]
            .iter()
            .filter_map(|rc| utils::home_dir().map(|dir| dir.join(rc)))
    }
}

impl UnixShell for Bash {
    fn does_exist(&self) -> bool {
        // Checking to see if we can find any traces of Bash in $SHELL
        // or a file or binary on disk.
        matches!(process().var("SHELL"), Ok(sh) if sh.contains("bash"))
            || self.rcfiles().iter().any(|rc| rc.is_file())
            || matches!(utils::find_cmd(&["bash"]), Some(_))
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        Bash::profiles().collect()
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        Bash::profiles().filter(|rc| rc.is_file()).collect()
    }
}

struct Zsh;

impl Zsh {
    fn zdotdir() -> Result<PathBuf> {
        use std::ffi::OsStr;
        use std::os::unix::ffi::OsStrExt;

        if matches!(process().var("SHELL"), Ok(sh) if sh.contains("zsh")) {
            match process().var("ZDOTDIR") {
                Ok(dir) if dir.len() > 0 => Ok(PathBuf::from(dir)),
                _ => bail!("Zsh setup failed."),
            }
        } else if utils::find_cmd(&["zsh"]) == Some("zsh") {
            match std::process::Command::new("zsh")
                .args(&["-c", "'echo $ZDOTDIR'"])
                .output()
            {
                Ok(io) if io.stdout.len() > 0 => Ok(PathBuf::from(OsStr::from_bytes(&io.stdout))),
                _ => bail!("Zsh setup failed."),
            }
        } else {
            bail!("What? Unpossible.")
        }
    }
}

impl UnixShell for Zsh {
    fn does_exist(&self) -> bool {
        // zsh has to either be the shell or be callable for zsh setup.
        matches!(process().var("SHELL"), Ok(sh) if sh.contains("zsh"))
            || matches!(utils::find_cmd(&["zsh"]), Some(sh) if sh.contains("zsh"))
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        [Zsh::zdotdir().ok(), utils::home_dir()]
            .iter()
            .filter_map(|dir| dir.as_ref().map(|p| p.join(".zshenv")))
            .collect()
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        // zsh can change $ZDOTDIR both _before_ AND _during_ reading .zshenv,
        // so we: write to $ZDOTDIR/.zshenv if-exists ($ZDOTDIR changes before)
        // OR write to $HOME/.zshenv if it exists (change-during)
        // if neither exist, we create it ourselves, but using the same logic,
        // because we must still respond to whether $ZDOTDIR is set or unset.
        // In any case we only write once.
        self.rcfiles()
            .into_iter()
            .filter(|env| env.is_file())
            .chain(self.rcfiles().into_iter())
            .take(1)
            .collect()
    }
}

pub fn legacy_paths() -> impl Iterator<Item = PathBuf> {
    let zprofiles = Zsh::zdotdir()
        .into_iter()
        .chain(utils::home_dir())
        .map(|d| d.join(".zprofile"));
    let profiles = [".bash_profile", ".profile"]
        .iter()
        .filter_map(|rc| utils::home_dir().map(|d| d.join(rc)));

    profiles.chain(zprofiles)
}
<commit_msg>Simplify Bash logic<commit_after>//! Paths and Unix shells
//!
//! MacOS, Linux, FreeBSD, and many other OS model their design on Unix,
//! so handling them is relatively consistent. But only relatively.
//! POSIX postdates Unix by 20 years, and each "Unix-like" shell develops
//! unique quirks over time.
//!
//!
//! Windowing Managers, Desktop Environments, GUI Terminals, and PATHs
//!
//! Duplicating paths in PATH can cause performance issues when the OS searches
//! the same place multiple times. Traditionally, Unix configurations have
//! resolved this by setting up PATHs in the shell's login profile.
//!
//! This has its own issues. Login profiles are only intended to run once, but
//! changing the PATH is common enough that people may run it twice. Desktop
//! environments often choose to NOT start login shells in GUI terminals. Thus,
//! a trend has emerged to place PATH updates in other run-commands (rc) files,
//! leaving Rustup with few assumptions to build on for fulfilling its promise
//! to set up PATH appropriately.
//!
//! Rustup addresses this by:
//! 1) using a shell script that updates PATH if the path is not in PATH
//! 2) sourcing this script in any known and appropriate rc file

use super::*;
use crate::process;
use error_chain::bail;
use std::path::PathBuf;

pub type Shell = Box<dyn UnixShell>;

#[derive(Debug, PartialEq)]
pub struct ShellScript {
    content: &'static str,
    name: &'static str,
}

impl ShellScript {
    pub fn write(&self) -> Result<()> {
        let home = utils::cargo_home()?;
        let cargo_bin = format!("{}/bin", cargo_home_str()?);
        let env_name = home.join(self.name);
        let env_file = self.content.replace("{cargo_bin}", &cargo_bin);
        utils::write_file(self.name, &env_name, &env_file)?;
        Ok(())
    }
}

// TODO: Update into a bytestring.
pub fn cargo_home_str() -> Result<Cow<'static, str>> {
    let path = utils::cargo_home()?;

    let default_cargo_home = utils::home_dir()
        .unwrap_or_else(|| PathBuf::from("."))
        .join(".cargo");
    Ok(if default_cargo_home == path {
        "$HOME/.cargo".into()
    } else {
        match path.to_str() {
            Some(p) => p.to_owned().into(),
            None => bail!("Non-Unicode path!"),
        }
    })
}

// TODO: Tcsh (BSD)
// TODO?: Make a decision on Ion Shell, Power Shell, Nushell
// Cross-platform non-POSIX shells have not been assessed for integration yet
fn enumerate_shells() -> Vec<Shell> {
    vec![Box::new(Posix), Box::new(Bash), Box::new(Zsh)]
}

pub fn get_available_shells() -> impl Iterator<Item = Shell> {
    enumerate_shells().into_iter().filter(|sh| sh.does_exist())
}

pub trait UnixShell {
    // Detects if a shell "exists". Users have multiple shells, so an "eager"
    // heuristic should be used, assuming shells exist if any traces do.
    fn does_exist(&self) -> bool;

    // Gives all rcfiles of a given shell that rustup is concerned with.
    // Used primarily in checking rcfiles for cleanup.
    fn rcfiles(&self) -> Vec<PathBuf>;

    // Gives rcs that should be written to.
    fn update_rcs(&self) -> Vec<PathBuf>;

    // Writes the relevant env file.
    fn env_script(&self) -> ShellScript {
        ShellScript {
            name: "env.sh",
            content: include_str!("env.sh"),
        }
    }

    fn source_string(&self) -> Result<String> {
        Ok(format!(r#"source "{}/env.sh""#, cargo_home_str()?))
    }
}

struct Posix;
impl UnixShell for Posix {
    fn does_exist(&self) -> bool {
        true
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        match utils::home_dir() {
            Some(dir) => vec![dir.join(".profile")],
            _ => vec![],
        }
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        // Write to .profile even if it doesn't exist.
        self.rcfiles()
    }
}

struct Bash;

impl UnixShell for Bash {
    fn does_exist(&self) -> bool {
        self.update_rcs().len() > 0
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        [".bash_profile", ".bash_login", ".profile", ".bashrc"]
            .iter()
            .filter_map(|rc| utils::home_dir().map(|dir| dir.join(rc)))
            .collect()
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        self.rcfiles()
            .into_iter()
            .filter(|rc| rc.is_file())
            .collect()
    }
}

struct Zsh;

impl Zsh {
    fn zdotdir() -> Result<PathBuf> {
        use std::ffi::OsStr;
        use std::os::unix::ffi::OsStrExt;

        if matches!(process().var("SHELL"), Ok(sh) if sh.contains("zsh")) {
            match process().var("ZDOTDIR") {
                Ok(dir) if dir.len() > 0 => Ok(PathBuf::from(dir)),
                _ => bail!("Zsh setup failed."),
            }
        } else if utils::find_cmd(&["zsh"]) == Some("zsh") {
            match std::process::Command::new("zsh")
                .args(&["-c", "'echo $ZDOTDIR'"])
                .output()
            {
                Ok(io) if io.stdout.len() > 0 => Ok(PathBuf::from(OsStr::from_bytes(&io.stdout))),
                _ => bail!("Zsh setup failed."),
            }
        } else {
            bail!("What? Unpossible.")
        }
    }
}

impl UnixShell for Zsh {
    fn does_exist(&self) -> bool {
        // zsh has to either be the shell or be callable for zsh setup.
        matches!(process().var("SHELL"), Ok(sh) if sh.contains("zsh"))
            || matches!(utils::find_cmd(&["zsh"]), Some(sh) if sh.contains("zsh"))
    }

    fn rcfiles(&self) -> Vec<PathBuf> {
        [Zsh::zdotdir().ok(), utils::home_dir()]
            .iter()
            .filter_map(|dir| dir.as_ref().map(|p| p.join(".zshenv")))
            .collect()
    }

    fn update_rcs(&self) -> Vec<PathBuf> {
        // zsh can change $ZDOTDIR both _before_ AND _during_ reading .zshenv,
        // so we: write to $ZDOTDIR/.zshenv if-exists ($ZDOTDIR changes before)
        // OR write to $HOME/.zshenv if it exists (change-during)
        // if neither exist, we create it ourselves, but using the same logic,
        // because we must still respond to whether $ZDOTDIR is set or unset.
        // In any case we only write once.
        self.rcfiles()
            .into_iter()
            .filter(|env| env.is_file())
            .chain(self.rcfiles().into_iter())
            .take(1)
            .collect()
    }
}

pub fn legacy_paths() -> impl Iterator<Item = PathBuf> {
    let zprofiles = Zsh::zdotdir()
        .into_iter()
        .chain(utils::home_dir())
        .map(|d| d.join(".zprofile"));
    let profiles = [".bash_profile", ".profile"]
        .iter()
        .filter_map(|rc| utils::home_dir().map(|d| d.join(rc)));

    profiles.chain(zprofiles)
}
<|endoftext|>


<commit_before>use std::str;
use inlined_parser::{Node, Children, Data};
use self::unescape::unescapeString;

mod unescape;

// TODO: figure out how to write this as a function on Node; the borrow checker
// was extra painful the last time you tried.
macro_rules! node_children( ( $node:expr ) => ( {
  match $node.contents {
    Children( ref nodes ) => nodes,
    _ => fail!( "No children in node." )
  } } ) )

pub fn codeForNode( node: &Node ) -> String {
  match node.name {
    "Definition" => wrapChildrenOutput( "rule!( ", node, " )\n" ),
    "Expression" => expressionOutput( node ),
    "Sequence" => sequenceOutput( node ),
    "Literal" => literalOutput( node ),
    "Class" => classOutput( node ),
    "Suffix" => suffixOutput( node ),
    "Prefix" => prefixOutput( node ),
    "Primary" => primaryOutput( node ),
    "DOT" => String::from_str( "base::Dot" ),
    "LEFTARROW" => String::from_str( " <- " ),
    "SLASH" => String::from_str( ", " ),
    "Spacing" => String::new(),
    "EndOfLine" => String::new(),
    "OPEN" => String::new(),
    "CLOSE" => String::new(),
    _ => codeForNodeContents( node )
  }
}

fn codeForNodeContents( node: &Node ) -> String {
  match node.contents {
    Children( ref children ) => {
      children.iter().map( codeForNode ).collect::<Vec<String>>().concat()
    }
    Data( data ) => str::from_utf8( data ).unwrap().to_string(),
  }
}

fn wrapChildrenOutput( before: &str, node: &Node, after: &str ) -> String {
  [ before.into_maybe_owned(),
    codeForNodeContents( node ).into_maybe_owned(),
    after.into_maybe_owned() ].concat()
}

fn wrapNodeOutput( before: &str, node: &Node, after: &str ) -> String {
  [ before.into_maybe_owned(),
    codeForNode( node ).into_maybe_owned(),
    after.into_maybe_owned() ].concat()
}

fn expressionOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() > 1 {
    wrapChildrenOutput( "or!( ", node , " )" )
  } else {
    codeForNodeContents( node )
  }
}

fn sequenceOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() > 1 {
    let mut output = String::from_str( "seq!( " );
    for i in range( 0, children.len() ) {
      output.push_str( codeForNode( children.get( i ) ).as_slice() );
      if i != children.len() -1 {
        output.push_str( ", " );
      }
    }
    output.push_str( " )" );
    output.into_string()
  } else {
    codeForNodeContents( node )
  }
}

fn suffixOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 2 {
    let macro_name = match children.get( 1 ).name {
      "QUESTION" => "opt",
      "STAR" => "star",
      "PLUS" => "plus",
      _ => fail!( "Bad second child." )
    };

    [ macro_name,
      "!( ",
      codeForNode( children.get( 0 ) ).as_slice(),
      " )" ].concat()
  } else {
    codeForNodeContents( node )
  }
}

fn prefixOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 2 {
    let macro_name = children.get( 0 ).name.chars()
      .map( |x| x.to_lowercase() ).collect::<String>();

    [ macro_name.as_slice(),
      "!( ",
      codeForNode( children.get( 1 ) ).as_slice(),
      " )" ].concat()
  } else {
    codeForNodeContents( node )
  }
}

fn primaryOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 1 && children.get( 0 ).name == "Identifier" {
    wrapNodeOutput( "ex!( ", children.get( 0 ), " )" )
  } else {
    codeForNodeContents( node )
  }
}

fn literalOutput( node: &Node ) -> String {
  stringBasedRule( node, "lit" )
}

fn classOutput( node: &Node ) -> String {
  stringBasedRule( node, "class" )
    .replace( r"\\]", r"]" )
    .replace( r"\\[", r"[" )
}

fn escapeToRustLiteral( input: &str ) -> String {
  input.to_string()
    .replace( r"\", r"\\" )
    .replace( "\n", r"\n" )
    .replace( "\t", r"\t" )
    .replace( "\r", r"\r" )
    .replace( "\"", r#"\""# )
}

fn stringBasedRule( node: &Node, rule_name: &str ) -> String {
  let full = codeForNodeContents( node );
  let content = escapeToRustLiteral(
    unescapeString(
      full.as_slice().slice_chars( 1, full.len() - 1 ) ).as_slice() );
  format!( "{}!( \"{}\" )", rule_name, content )
}
<commit_msg>More updating to latest rustc<commit_after>use std::str;
use inlined_parser::{Node, Children, Data};
use self::unescape::unescapeString;

mod unescape;

// TODO: figure out how to write this as a function on Node; the borrow checker
// was extra painful the last time you tried.
macro_rules! node_children( ( $node:expr ) => ( {
  match $node.contents {
    Children( ref nodes ) => nodes,
    _ => fail!( "No children in node." )
  } } ) )

pub fn codeForNode( node: &Node ) -> String {
  match node.name {
    "Definition" => wrapChildrenOutput( "rule!( ", node, " )\n" ),
    "Expression" => expressionOutput( node ),
    "Sequence" => sequenceOutput( node ),
    "Literal" => literalOutput( node ),
    "Class" => classOutput( node ),
    "Suffix" => suffixOutput( node ),
    "Prefix" => prefixOutput( node ),
    "Primary" => primaryOutput( node ),
    "DOT" => String::from_str( "base::Dot" ),
    "LEFTARROW" => String::from_str( " <- " ),
    "SLASH" => String::from_str( ", " ),
    "Spacing" => String::new(),
    "EndOfLine" => String::new(),
    "OPEN" => String::new(),
    "CLOSE" => String::new(),
    _ => codeForNodeContents( node )
  }
}

fn codeForNodeContents( node: &Node ) -> String {
  match node.contents {
    Children( ref children ) => {
      children.iter().map( codeForNode ).collect::<Vec<String>>().concat()
    }
    Data( data ) => str::from_utf8( data ).unwrap().to_string(),
  }
}

fn wrapChildrenOutput( before: &str, node: &Node, after: &str ) -> String {
  [ before.into_maybe_owned(),
    codeForNodeContents( node ).into_maybe_owned(),
    after.into_maybe_owned() ].concat()
}

fn wrapNodeOutput( before: &str, node: &Node, after: &str ) -> String {
  [ before.into_maybe_owned(),
    codeForNode( node ).into_maybe_owned(),
    after.into_maybe_owned() ].concat()
}

fn expressionOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() > 1 {
    wrapChildrenOutput( "or!( ", node , " )" )
  } else {
    codeForNodeContents( node )
  }
}

fn sequenceOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() > 1 {
    let mut output = String::from_str( "seq!( " );
    for i in range( 0, children.len() ) {
      output.push_str( codeForNode( &children[ i ] ).as_slice() );
      if i != children.len() -1 {
        output.push_str( ", " );
      }
    }
    output.push_str( " )" );
    output.into_string()
  } else {
    codeForNodeContents( node )
  }
}

fn suffixOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 2 {
    let macro_name = match children[ 1 ].name {
      "QUESTION" => "opt",
      "STAR" => "star",
      "PLUS" => "plus",
      _ => fail!( "Bad second child." )
    };

    [ macro_name,
      "!( ",
      codeForNode( &children[ 0 ] ).as_slice(),
      " )" ].concat()
  } else {
    codeForNodeContents( node )
  }
}

fn prefixOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 2 {
    let macro_name = children[ 0 ].name.chars()
      .map( |x| x.to_lowercase() ).collect::<String>();

    [ macro_name.as_slice(),
      "!( ",
      codeForNode( &children[ 1 ] ).as_slice(),
      " )" ].concat()
  } else {
    codeForNodeContents( node )
  }
}

fn primaryOutput( node: &Node ) -> String {
  let children = node_children!( node );
  if children.len() == 1 && children[ 0 ].name == "Identifier" {
    wrapNodeOutput( "ex!( ", &children[ 0 ], " )" )
  } else {
    codeForNodeContents( node )
  }
}

fn literalOutput( node: &Node ) -> String {
  stringBasedRule( node, "lit" )
}

fn classOutput( node: &Node ) -> String {
  stringBasedRule( node, "class" )
    .replace( r"\\]", r"]" )
    .replace( r"\\[", r"[" )
}

fn escapeToRustLiteral( input: &str ) -> String {
  input.to_string()
    .replace( r"\", r"\\" )
    .replace( "\n", r"\n" )
    .replace( "\t", r"\t" )
    .replace( "\r", r"\r" )
    .replace( "\"", r#"\""# )
}

fn stringBasedRule( node: &Node, rule_name: &str ) -> String {
  let full = codeForNodeContents( node );
  let content = escapeToRustLiteral(
    unescapeString(
      full.as_slice().slice_chars( 1, full.len() - 1 ) ).as_slice() );
  format!( "{}!( \"{}\" )", rule_name, content )
}
<|endoftext|>


<commit_before>// Copyright 2018 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 spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};

pub fn target() -> TargetResult {
    let mut base = super::windows_msvc_base::opts();
    base.max_atomic_width = Some(64);
    base.has_elf_tls = true;

    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
    base.panic_strategy = PanicStrategy::Abort;
    base.linker = Some("rust-lld".to_owned());

    Ok(Target {
        llvm_target: "aarch64-pc-windows-msvc".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "windows".to_string(),
        target_env: "msvc".to_string(),
        target_vendor: "pc".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
        options: base,
    })
}
<commit_msg>Rollup merge of #54290 - michaelwoerister:aarch64-back-to-msvc, r=alexcrichton<commit_after>// Copyright 2018 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 spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};

pub fn target() -> TargetResult {
    let mut base = super::windows_msvc_base::opts();
    base.max_atomic_width = Some(64);
    base.has_elf_tls = true;

    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
    base.panic_strategy = PanicStrategy::Abort;

    Ok(Target {
        llvm_target: "aarch64-pc-windows-msvc".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "64".to_string(),
        target_c_int_width: "32".to_string(),
        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
        arch: "aarch64".to_string(),
        target_os: "windows".to_string(),
        target_env: "msvc".to_string(),
        target_vendor: "pc".to_string(),
        linker_flavor: LinkerFlavor::Msvc,
        options: base,
    })
}
<|endoftext|>


<commit_before>use std::net::ToSocketAddrs;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

use futures::channel::oneshot;
use futures::future;
use futures::future::FutureExt;
use futures::future::TryFutureExt;

use httpbis;
use httpbis::for_test::*;
use httpbis::*;

use super::BIND_HOST;
use crate::assert_types::assert_send_future;
use std::thread::JoinHandle;
use tokio::runtime::Runtime;

/// Single connection HTTP/server.
/// Accepts only one connection.
pub struct ServerOneConn {
    from_loop: FromLoop,
    join_handle: Option<thread::JoinHandle<()>>,
    shutdown_tx: Option<oneshot::Sender<()>>,
    conn: Arc<Mutex<Option<ServerConn>>>,
}

struct FromLoop {
    port: u16,
}

impl ServerOneConn {
    pub fn new_fn<S>(port: u16, service: S) -> Self
    where
        S: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> httpbis::Result<()>
            + Send
            + Sync
            + 'static,
    {
        ServerOneConn::new_fn_impl(port, service)
    }

    #[allow(dead_code)]
    fn new_fn_impl<S>(port: u16, service: S) -> Self
    where
        S: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> httpbis::Result<()>
            + Send
            + Sync
            + 'static,
    {
        let (from_loop_tx, from_loop_rx) = std::sync::mpsc::channel();
        let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();

        let conn: Arc<Mutex<Option<ServerConn>>> = Default::default();

        let conn_for_thread = conn.clone();

        let join_handle: JoinHandle<()> = thread::Builder::new()
            .name("server_one_conn".to_owned())
            .spawn(move || {
                let lp = Runtime::new().unwrap();

                let listener = lp
                    .block_on(tokio::net::TcpListener::bind(
                        &(BIND_HOST, port).to_socket_addrs().unwrap().next().unwrap(),
                    ))
                    .unwrap();

                let actual_port = listener.local_addr().unwrap().port();
                from_loop_tx
                    .send(FromLoop { port: actual_port })
                    .ok()
                    .unwrap();

                let handle = lp.handle().clone();

                let conn = listener.accept().map_err(httpbis::Error::from);

                // TODO: close listening port
                //drop(listener);

                let future = async move {
                    let (conn, peer_addr) = match conn.await {
                        Ok((conn, peer_addr)) => (conn, peer_addr),
                        Err(e) => {
                            warn!("accept failed: {}", e);
                            return;
                        }
                    };

                    let (conn, future) = ServerConn::new_plain_single_thread_fn(
                        &handle,
                        conn,
                        peer_addr,
                        Default::default(),
                        service,
                    );
                    *conn_for_thread.lock().unwrap() = Some(conn);
                    future.await
                };

                let shutdown_rx = shutdown_rx.then(|_| future::ready(()));

                let shutdown_rx = assert_send_future::<(), _>(shutdown_rx);

                let shutdown_rx = Box::pin(shutdown_rx);

                lp.block_on(future::select(shutdown_rx, Box::pin(future)));
            })
            .expect("spawn");

        ServerOneConn {
            from_loop: from_loop_rx.recv().unwrap(),
            join_handle: Some(join_handle),
            shutdown_tx: Some(shutdown_tx),
            conn,
        }
    }
}

#[allow(dead_code)]
impl ServerOneConn {
    pub fn port(&self) -> u16 {
        self.from_loop.port
    }

    pub fn dump_state(&self) -> ConnStateSnapshot {
        let g = self.conn.lock().expect("lock");
        let conn = g.as_ref().expect("conn");
        Runtime::new()
            .unwrap()
            .block_on(conn.dump_state())
            .expect("dump_status")
    }
}

impl Drop for ServerOneConn {
    fn drop(&mut self) {
        drop(self.shutdown_tx.take().unwrap().send(()));
        self.join_handle.take().unwrap().join().ok();
    }
}
<commit_msg>Drop listener after accept in single-conn server<commit_after>use std::net::ToSocketAddrs;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

use futures::channel::oneshot;
use futures::future;
use futures::future::FutureExt;

use httpbis;
use httpbis::for_test::*;
use httpbis::*;

use super::BIND_HOST;
use crate::assert_types::assert_send_future;
use std::thread::JoinHandle;
use tokio::runtime::Runtime;

/// Single connection HTTP/server.
/// Accepts only one connection.
pub struct ServerOneConn {
    from_loop: FromLoop,
    join_handle: Option<thread::JoinHandle<()>>,
    shutdown_tx: Option<oneshot::Sender<()>>,
    conn: Arc<Mutex<Option<ServerConn>>>,
}

struct FromLoop {
    port: u16,
}

impl ServerOneConn {
    pub fn new_fn<S>(port: u16, service: S) -> Self
    where
        S: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> httpbis::Result<()>
            + Send
            + Sync
            + 'static,
    {
        ServerOneConn::new_fn_impl(port, service)
    }

    #[allow(dead_code)]
    fn new_fn_impl<S>(port: u16, service: S) -> Self
    where
        S: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> httpbis::Result<()>
            + Send
            + Sync
            + 'static,
    {
        let (from_loop_tx, from_loop_rx) = std::sync::mpsc::channel();
        let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();

        let conn: Arc<Mutex<Option<ServerConn>>> = Default::default();

        let conn_for_thread = conn.clone();

        let join_handle: JoinHandle<()> = thread::Builder::new()
            .name("server_one_conn".to_owned())
            .spawn(move || {
                let lp = Runtime::new().unwrap();

                let listener = lp
                    .block_on(tokio::net::TcpListener::bind(
                        &(BIND_HOST, port).to_socket_addrs().unwrap().next().unwrap(),
                    ))
                    .unwrap();

                let actual_port = listener.local_addr().unwrap().port();
                from_loop_tx
                    .send(FromLoop { port: actual_port })
                    .ok()
                    .unwrap();

                let handle = lp.handle().clone();

                let future = async move {
                    let conn = listener.accept().await;

                    drop(listener);

                    let (conn, peer_addr) = match conn {
                        Ok((conn, peer_addr)) => (conn, peer_addr),
                        Err(e) => {
                            warn!("accept failed: {}", e);
                            return;
                        }
                    };

                    let (conn, future) = ServerConn::new_plain_single_thread_fn(
                        &handle,
                        conn,
                        peer_addr,
                        Default::default(),
                        service,
                    );
                    *conn_for_thread.lock().unwrap() = Some(conn);
                    future.await
                };

                let shutdown_rx = shutdown_rx.then(|_| future::ready(()));

                let shutdown_rx = assert_send_future::<(), _>(shutdown_rx);

                let shutdown_rx = Box::pin(shutdown_rx);

                lp.block_on(future::select(shutdown_rx, Box::pin(future)));
            })
            .expect("spawn");

        ServerOneConn {
            from_loop: from_loop_rx.recv().unwrap(),
            join_handle: Some(join_handle),
            shutdown_tx: Some(shutdown_tx),
            conn,
        }
    }
}

#[allow(dead_code)]
impl ServerOneConn {
    pub fn port(&self) -> u16 {
        self.from_loop.port
    }

    pub fn dump_state(&self) -> ConnStateSnapshot {
        let g = self.conn.lock().expect("lock");
        let conn = g.as_ref().expect("conn");
        Runtime::new()
            .unwrap()
            .block_on(conn.dump_state())
            .expect("dump_status")
    }
}

impl Drop for ServerOneConn {
    fn drop(&mut self) {
        drop(self.shutdown_tx.take().unwrap().send(()));
        self.join_handle.take().unwrap().join().ok();
    }
}
<|endoftext|>


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

//! A wrapper around any Reader to treat it as an RNG.

use old_io::Reader;
use rand::Rng;
use result::Result::{Ok, Err};
use slice::SliceExt;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// # Panics
///
/// It will panic if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::old_io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => panic!("ReaderRng.fill_bytes error: {:?}", e)
        }
    }
}

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

    use super::ReaderRng;
    use old_io::MemReader;
    use num::Int;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), 1_u64.to_be());
        assert_eq!(rng.next_u64(), 2_u64.to_be());
        assert_eq!(rng.next_u64(), 3_u64.to_be());
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), 1_u32.to_be());
        assert_eq!(rng.next_u32(), 2_u32.to_be());
        assert_eq!(rng.next_u32(), 3_u32.to_be());
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8; 8];

        let mut rng = ReaderRng::new(MemReader::new(v.as_slice().to_vec()));
        rng.fill_bytes(&mut w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8; 3];
        rng.fill_bytes(&mut v);
    }
}
<commit_msg>Auto merge of #21680 - japaric:slice, r=alexcrichton<commit_after>// Copyright 2013 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.

//! A wrapper around any Reader to treat it as an RNG.

use old_io::Reader;
use rand::Rng;
use result::Result::{Ok, Err};
use slice::SliceExt;

/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
/// # Panics
///
/// It will panic if it there is insufficient data to fulfill a request.
///
/// # Example
///
/// ```rust
/// use std::rand::{reader, Rng};
/// use std::old_io::MemReader;
///
/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
/// println!("{:x}", rng.gen::<uint>());
/// ```
pub struct ReaderRng<R> {
    reader: R
}

impl<R: Reader> ReaderRng<R> {
    /// Create a new `ReaderRng` from a `Reader`.
    pub fn new(r: R) -> ReaderRng<R> {
        ReaderRng {
            reader: r
        }
    }
}

impl<R: Reader> Rng for ReaderRng<R> {
    fn next_u32(&mut self) -> u32 {
        // This is designed for speed: reading a LE integer on a LE
        // platform just involves blitting the bytes into the memory
        // of the u32, similarly for BE on BE; avoiding byteswapping.
        if cfg!(target_endian="little") {
            self.reader.read_le_u32().unwrap()
        } else {
            self.reader.read_be_u32().unwrap()
        }
    }
    fn next_u64(&mut self) -> u64 {
        // see above for explanation.
        if cfg!(target_endian="little") {
            self.reader.read_le_u64().unwrap()
        } else {
            self.reader.read_be_u64().unwrap()
        }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        if v.len() == 0 { return }
        match self.reader.read_at_least(v.len(), v) {
            Ok(_) => {}
            Err(e) => panic!("ReaderRng.fill_bytes error: {:?}", e)
        }
    }
}

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

    use super::ReaderRng;
    use old_io::MemReader;
    use num::Int;
    use rand::Rng;

    #[test]
    fn test_reader_rng_u64() {
        // transmute from the target to avoid endianness concerns.
        let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1,
                     0  , 0, 0, 0, 0, 0, 0, 2,
                     0,   0, 0, 0, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u64(), 1_u64.to_be());
        assert_eq!(rng.next_u64(), 2_u64.to_be());
        assert_eq!(rng.next_u64(), 3_u64.to_be());
    }
    #[test]
    fn test_reader_rng_u32() {
        let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3];
        let mut rng = ReaderRng::new(MemReader::new(v));

        assert_eq!(rng.next_u32(), 1_u32.to_be());
        assert_eq!(rng.next_u32(), 2_u32.to_be());
        assert_eq!(rng.next_u32(), 3_u32.to_be());
    }
    #[test]
    fn test_reader_rng_fill_bytes() {
        let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
        let mut w = [0u8; 8];

        let mut rng = ReaderRng::new(MemReader::new(v.to_vec()));
        rng.fill_bytes(&mut w);

        assert!(v == w);
    }

    #[test]
    #[should_fail]
    fn test_reader_rng_insufficient_bytes() {
        let mut rng = ReaderRng::new(MemReader::new(vec!()));
        let mut v = [0u8; 3];
        rng.fill_bytes(&mut v);
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, Write};

use analysis::rust_type::AsStr;
use env::Env;
use library;
use super::ffi_type::*;
use super::super::general;

pub fn generate_classes_funcs<W: Write>(w: &mut W, env: &Env, classes: &Vec<&library::Class>) -> Result<()> {
    for klass in classes {
        try!(generate_class_funcs(w, env, klass));
    }

    Ok(())
}

fn generate_class_funcs<W: Write>(w: &mut W, env: &Env, klass: &library::Class) -> Result<()> {
    try!(writeln!(w, ""));
    try!(writeln!(w, "    //========================================================================="));
    try!(writeln!(w, "    // {}", klass.glib_type_name));
    try!(writeln!(w, "    //========================================================================="));
    try!(writeln!(w, "    pub fn {:<36}() -> GType;", klass.glib_get_type));

    for func in &klass.functions {
        let decl = function_declaration(env, func);
        try!(writeln!(w, "    {}", decl));
    }

    Ok(())
}

fn function_declaration(env: &Env, func: &library::Function) -> String {
    let (mut commented, ret_str) = function_return_value(env, func);

    let mut parameter_strs: Vec<String> = Vec::new();
    for par in &func.parameters {
        let (c, par_str) = function_parameter(env, par);
        parameter_strs.push(par_str);
        if c { commented = true; }
    }

    let commented_str = if commented { "//" } else { "" };
    format!("{}pub fn {:<36}({}){};", commented_str, func.c_identifier,
        parameter_strs.connect(", "), ret_str)
}

fn function_return_value(env: &Env, func: &library::Function) -> (bool, String) {
    if func.ret.typ == Default::default() { return (false, String::new()) }
    let ffi_type = ffi_type(env, func.ret.typ);
    let commented = ffi_type.is_err();
    (commented, format!(" -> {}", ffi_type.as_str()))
}

fn function_parameter(env: &Env, par: &library::Parameter) -> (bool, String) {
    let ffi_type = ffi_type(env, par.typ);
    let commented = ffi_type.is_err();
    (commented, format!("{}: {}", general::fix_parameter_name(&par.name), ffi_type.as_str()))
}
<commit_msg>codegen::sys: Add VarArgs support<commit_after>use std::io::{Result, Write};

use analysis::rust_type::AsStr;
use env::Env;
use library;
use super::ffi_type::*;
use super::super::general;

pub fn generate_classes_funcs<W: Write>(w: &mut W, env: &Env, classes: &Vec<&library::Class>) -> Result<()> {
    for klass in classes {
        try!(generate_class_funcs(w, env, klass));
    }

    Ok(())
}

fn generate_class_funcs<W: Write>(w: &mut W, env: &Env, klass: &library::Class) -> Result<()> {
    try!(writeln!(w, ""));
    try!(writeln!(w, "    //========================================================================="));
    try!(writeln!(w, "    // {}", klass.glib_type_name));
    try!(writeln!(w, "    //========================================================================="));
    try!(writeln!(w, "    pub fn {:<36}() -> GType;", klass.glib_get_type));

    for func in &klass.functions {
        let decl = function_declaration(env, func);
        try!(writeln!(w, "    {}", decl));
    }

    Ok(())
}

fn function_declaration(env: &Env, func: &library::Function) -> String {
    let (mut commented, ret_str) = function_return_value(env, func);

    let mut parameter_strs: Vec<String> = Vec::new();
    for par in &func.parameters {
        let (c, par_str) = function_parameter(env, par);
        parameter_strs.push(par_str);
        if c { commented = true; }
    }

    let commented_str = if commented { "//" } else { "" };
    format!("{}pub fn {:<36}({}){};", commented_str, func.c_identifier,
        parameter_strs.connect(", "), ret_str)
}

fn function_return_value(env: &Env, func: &library::Function) -> (bool, String) {
    if func.ret.typ == Default::default() { return (false, String::new()) }
    let ffi_type = ffi_type(env, func.ret.typ);
    let commented = ffi_type.is_err();
    (commented, format!(" -> {}", ffi_type.as_str()))
}

fn function_parameter(env: &Env, par: &library::Parameter) -> (bool, String) {
    if let &library::Type::Fundamental(library::Fundamental::VarArgs) = env.library.type_(par.typ) {
        return (false, "...".into());
    }
    let ffi_type = ffi_type(env, par.typ);
    let commented = ffi_type.is_err();
    (commented, format!("{}: {}", general::fix_parameter_name(&par.name), ffi_type.as_str()))
}
<|endoftext|>


<commit_before>//! CSS funciri values.

use cssparser::Parser;

use crate::allowed_url::{Fragment, Href};
use crate::error::*;
use crate::parsers::Parse;

/// Used where style properties take a funciri or "none"
///
/// This is not to be used for values which don't come from properties.
/// For example, the `xlink:href` attribute in the `<image>` element
/// does not take a funciri value (which looks like `url(...)`), but rather
/// it takes a plain URL.  Use the `Href` type in that case.
#[derive(Debug, Clone, PartialEq)]
pub enum IRI {
    None,
    Resource(Fragment),
}

impl Default for IRI {
    fn default() -> IRI {
        IRI::None
    }
}

impl IRI {
    /// Returns the contents of an `IRI::Resource`, or `None`
    pub fn get(&self) -> Option<&Fragment> {
        match *self {
            IRI::None => None,
            IRI::Resource(ref f) => Some(f),
        }
    }
}

impl Parse for IRI {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<IRI, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(IRI::None)
        } else {
            let loc = parser.current_source_location();

            let url = parser.expect_url()?;
            parser.expect_exhausted()?;

            let href = Href::parse(&url).map_err(|_| {
                loc.new_custom_error(ValueErrorKind::parse_error("could not parse href"))
            })?;

            match href {
                Href::PlainUrl(_) => Err(loc.new_custom_error(ValueErrorKind::parse_error(
                    "href requires a fragment identifier",
                )))?,
                Href::WithFragment(f) => Ok(IRI::Resource(f)),
            }
        }
    }
}

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

    #[test]
    fn parses_none() {
        assert_eq!(IRI::parse_str("none"), Ok(IRI::None));
    }

    #[test]
    fn parses_url() {
        assert_eq!(
            IRI::parse_str("url(#bar)"),
            Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
        );

        assert_eq!(
            IRI::parse_str("url(foo#bar)"),
            Ok(IRI::Resource(Fragment::new(
                Some("foo".to_string()),
                "bar".to_string()
            )))
        );

        // be permissive if the closing ) is missing
        assert_eq!(
            IRI::parse_str("url(#bar"),
            Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
        );
        assert_eq!(
            IRI::parse_str("url(foo#bar"),
            Ok(IRI::Resource(Fragment::new(
                Some("foo".to_string()),
                "bar".to_string()
            )))
        );

        assert!(IRI::parse_str("").is_err());
        assert!(IRI::parse_str("foo").is_err());
        assert!(IRI::parse_str("url(foo)bar").is_err());
    }
}
<commit_msg>IRI: preserve the Href error information<commit_after>//! CSS funciri values.

use cssparser::Parser;

use crate::allowed_url::{Fragment, Href};
use crate::error::*;
use crate::parsers::Parse;

/// Used where style properties take a funciri or "none"
///
/// This is not to be used for values which don't come from properties.
/// For example, the `xlink:href` attribute in the `<image>` element
/// does not take a funciri value (which looks like `url(...)`), but rather
/// it takes a plain URL.  Use the `Href` type in that case.
#[derive(Debug, Clone, PartialEq)]
pub enum IRI {
    None,
    Resource(Fragment),
}

impl Default for IRI {
    fn default() -> IRI {
        IRI::None
    }
}

impl IRI {
    /// Returns the contents of an `IRI::Resource`, or `None`
    pub fn get(&self) -> Option<&Fragment> {
        match *self {
            IRI::None => None,
            IRI::Resource(ref f) => Some(f),
        }
    }
}

impl Parse for IRI {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<IRI, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(IRI::None)
        } else {
            let loc = parser.current_source_location();

            let url = parser.expect_url()?;
            parser.expect_exhausted()?;

            let href =
                Href::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;

            match href {
                Href::PlainUrl(_) => Err(loc.new_custom_error(ValueErrorKind::parse_error(
                    "href requires a fragment identifier",
                )))?,
                Href::WithFragment(f) => Ok(IRI::Resource(f)),
            }
        }
    }
}

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

    #[test]
    fn parses_none() {
        assert_eq!(IRI::parse_str("none"), Ok(IRI::None));
    }

    #[test]
    fn parses_url() {
        assert_eq!(
            IRI::parse_str("url(#bar)"),
            Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
        );

        assert_eq!(
            IRI::parse_str("url(foo#bar)"),
            Ok(IRI::Resource(Fragment::new(
                Some("foo".to_string()),
                "bar".to_string()
            )))
        );

        // be permissive if the closing ) is missing
        assert_eq!(
            IRI::parse_str("url(#bar"),
            Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
        );
        assert_eq!(
            IRI::parse_str("url(foo#bar"),
            Ok(IRI::Resource(Fragment::new(
                Some("foo".to_string()),
                "bar".to_string()
            )))
        );

        assert!(IRI::parse_str("").is_err());
        assert!(IRI::parse_str("foo").is_err());
        assert!(IRI::parse_str("url(foo)bar").is_err());
    }
}
<|endoftext|>


<commit_before>use crate::api_call::{Kind::*, *};
use crate::application::*;
use crate::user::*;
use crate::version::USER_AGENT;
use crate::ToParams;

use super::Parameters;

#[cfg(feature = "http-types")]
mod http;
#[cfg(feature = "reqwest-types")]
mod reqwest;

#[derive(Clone, Debug)]
pub struct Request {
    pub method: http_types::Method,
    pub path: &'static str,
    pub parameters: Parameters,
    pub headers: http_types::HeaderMap,
}

use http_types::Method;
use std::borrow::Cow;

impl Request {
    pub fn endpoint(
        kind: Kind,
        application: Option<&Application>,
        user: Option<&User>,
    ) -> (Method, &'static str) {
        use super::endpoints::*;

        match (kind, application, user) {
            (Authorize, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, _) => AUTHORIZE_ENDPOINT,
            (AuthRep, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, _) => AUTHREP_ENDPOINT,
            (Report, _, _) => REPORT_ENDPOINT,
        }
    }

    pub fn uri_and_body(&self) -> (Cow<str>, Option<&str>) {
        (
            self.parameters.path_and_query(self.path),
            self.parameters.body(),
        )
    }
}

pub trait FromRequest<P> {
    fn from_request(r: Request, params: P) -> Self;
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for Request {
    fn from(apicall: &ApiCall) -> Self {
        use http_types::header::{HeaderName, HeaderValue};
        use http_types::HeaderMap;

        let (method, path) =
            Request::endpoint(apicall.kind(), apicall.application(), apicall.user());

        let mut params = Vec::with_capacity(8);
        apicall.to_params(&mut params);

        let parameters = Parameters::new(&method, params.as_slice());

        let mut headers = apicall.extensions().map_or_else(
            || HeaderMap::with_capacity(1),
            |e| {
                let options = e.to_string();
                let mut h = HeaderMap::with_capacity(2);
                let val = HeaderValue::from_str(options.as_str());

                if let Ok(val) = val {
                    h.insert(HeaderName::from_static("3scale-options"), val);
                }

                h
            },
        );

        headers.insert("User-Agent", HeaderValue::from_static(USER_AGENT));

        Request {
            method,
            path,
            parameters,
            headers,
        }
    }
}
<commit_msg>request: enable curl module implementation based on feature curl-types<commit_after>use crate::api_call::{Kind::*, *};
use crate::application::*;
use crate::user::*;
use crate::version::USER_AGENT;
use crate::ToParams;

use super::Parameters;

#[cfg(feature = "curl-types")]
pub mod curl;
#[cfg(feature = "http-types")]
mod http;
#[cfg(feature = "reqwest-types")]
mod reqwest;

#[derive(Clone, Debug)]
pub struct Request {
    pub method: http_types::Method,
    pub path: &'static str,
    pub parameters: Parameters,
    pub headers: http_types::HeaderMap,
}

use http_types::Method;
use std::borrow::Cow;

impl Request {
    pub fn endpoint(
        kind: Kind,
        application: Option<&Application>,
        user: Option<&User>,
    ) -> (Method, &'static str) {
        use super::endpoints::*;

        match (kind, application, user) {
            (Authorize, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHORIZE_ENDPOINT,
            (Authorize, _, _) => AUTHORIZE_ENDPOINT,
            (AuthRep, Some(Application::OAuthToken(_)), _) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, Some(&User::OAuthToken(_))) => OAUTH_AUTHREP_ENDPOINT,
            (AuthRep, _, _) => AUTHREP_ENDPOINT,
            (Report, _, _) => REPORT_ENDPOINT,
        }
    }

    pub fn uri_and_body(&self) -> (Cow<str>, Option<&str>) {
        (
            self.parameters.path_and_query(self.path),
            self.parameters.body(),
        )
    }
}

pub trait FromRequest<P> {
    fn from_request(r: Request, params: P) -> Self;
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for Request {
    fn from(apicall: &ApiCall) -> Self {
        use http_types::header::{HeaderName, HeaderValue};
        use http_types::HeaderMap;

        let (method, path) =
            Request::endpoint(apicall.kind(), apicall.application(), apicall.user());

        let mut params = Vec::with_capacity(8);
        apicall.to_params(&mut params);

        let parameters = Parameters::new(&method, params.as_slice());

        let mut headers = apicall.extensions().map_or_else(
            || HeaderMap::with_capacity(1),
            |e| {
                let options = e.to_string();
                let mut h = HeaderMap::with_capacity(2);
                let val = HeaderValue::from_str(options.as_str());

                if let Ok(val) = val {
                    h.insert(HeaderName::from_static("3scale-options"), val);
                }

                h
            },
        );

        headers.insert("User-Agent", HeaderValue::from_static(USER_AGENT));

        Request {
            method,
            path,
            parameters,
            headers,
        }
    }
}
<|endoftext|>