<commit_before>use std::io;

use bytes::BytesMut;

use tokio_io::codec::{Decoder, Encoder};

// TODO - this stuff - all options
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RespValue {
    Array(Vec<RespValue>),
    BulkString(Vec<u8>)
}

pub trait ToResp {
    fn to_resp(&self) -> RespValue;
}

impl<'a> ToResp for &'a str {
    fn to_resp(&self) -> RespValue {
        RespValue::BulkString(self.as_bytes().into())
    }
}

impl<'a> ToResp for &'a [&'a str] {
    fn to_resp(&self) -> RespValue {
        RespValue::Array(self.as_ref().iter().map(|x| x.to_resp()).collect())
    }
}

impl<T: ToResp> From<T> for RespValue {
    fn from(from: T) -> RespValue {
        from.to_resp()
    }
}

/// Codec to read frames
pub struct RespCodec;

impl Encoder for RespCodec {
    type Item = RespValue;
    type Error = io::Error;

    fn encode(&mut self, msg: RespValue, buf: &mut BytesMut) -> io::Result<()> {
        unimplemented!()
    }
}

impl Decoder for RespCodec {
    type Item = RespValue;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<RespValue>, io::Error> {
        unimplemented!()
    }
}<commit_msg>Refactoring<commit_after>use std::io;

use bytes::{BufMut, BytesMut};

use tokio_io::codec::{Decoder, Encoder};

// TODO - this stuff - all Resp types
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RespValue {
    Array(Vec<RespValue>),
    BulkString(Vec<u8>)
}

pub trait ToResp {
    fn to_resp(&self) -> RespValue;
}

impl<'a> ToResp for &'a str {
    fn to_resp(&self) -> RespValue {
        RespValue::BulkString(self.as_bytes().into())
    }
}

impl<'a> ToResp for &'a [&'a str] {
    fn to_resp(&self) -> RespValue {
        RespValue::Array(self.as_ref().iter().map(|x| x.to_resp()).collect())
    }
}

impl<T: ToResp> From<T> for RespValue {
    fn from(from: T) -> RespValue {
        from.to_resp()
    }
}

/// Codec to read frames
pub struct RespCodec;

#[inline]
fn write_rn(buf: &mut BytesMut) {
    buf.put_u8(b'\r');
    buf.put_u8(b'\n');
}

#[inline]
fn check_and_reserve(buf: &mut BytesMut, amt: usize) {
    let remaining_bytes = buf.remaining_mut();
    if remaining_bytes < amt {
        buf.reserve(amt);
    }
}

#[inline]
fn write_header(symb: u8, len: usize, buf: &mut BytesMut) {
    let len_as_string = len.to_string();
    let len_as_bytes = len_as_string.as_bytes();
    let header_bytes = 1 + len_as_bytes.len() + 2;
    check_and_reserve(buf, header_bytes);
    buf.put_u8(symb);
    buf.extend(len_as_bytes);
    write_rn(buf);
}

impl Encoder for RespCodec {
    type Item = RespValue;
    type Error = io::Error;

    fn encode(&mut self, msg: RespValue, buf: &mut BytesMut) -> Result<(), Self::Error> {
        match msg {
            RespValue::Array(ary) => {
                write_header(b'*', ary.len(), buf);
                for v in ary {
                    self.encode(v, buf)?;
                }
            }
            RespValue::BulkString(bstr) => {
                let len = bstr.len();
                write_header(b'$', len, buf);
                check_and_reserve(buf, len + 2);
                buf.extend(bstr);
                write_rn(buf);
            }
        }
        Ok(())
    }
}

impl Decoder for RespCodec {
    type Item = RespValue;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        unimplemented!()
    }
}<|endoftext|>


<commit_before>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbaCodec;

impl Codec for RgbaCodec
{
    type Input = RgbaImage;
    type Mode = RgbaMode;

    fn encode<R: Rng>(
        source: &mut RgbaImage,
        payload: &[u8],
        mode: RgbaMode,
        mut rng: R)
    {
        // number of pixels per byte
        let ppb = match mode
        {
            // 1 values per pixel = 8 pixels per byte
            RgbaMode::Alpha => 8,
            // 4 values per pixel = 2 pixels per byte
            RgbaMode::All => 2,
        };

        // iterate pixels mutably
        for (mut pixels, byte) in source.pixels_mut()
             // split them into ppb-size chunks
            .chunks(ppb).into_iter()
            // make them vectors so we can check their lengths later
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk a byte
            .zip(payload.iter().map(|x| *x))
        {
            // if the pixels don't fit exactly into their chunks,
            // the last chunk will be short. we won't use that chunk
            // (making sure the payload fits into the image is not
            // this functions job!)
            if pixels.len() != ppb
            {
                return;
            }

            match mode
            {
                RgbaMode::Alpha =>
                {
                    for (i, px) in pixels.into_iter().enumerate()
                    {
                        // a true, or 1 bit
                        if get_bit(byte, i as u8)
                        {
                            // even = 0 bit, so it needs to be changed
                            if px.data[3] % 2 == 0
                            {
                                // special case: if it's zero, we have to go up
                                if px.data[3] == 0
                                {
                                    px.data[3] = 1;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        px.data[3] += 1;
                                    }
                                    else
                                    {
                                        px.data[3] -= 1;
                                    }
                                }
                            }
                        }
                        // a false, or 0 bit
                        else
                        {
                            // odd = 1 bit, so it needs to be changed
                            if px.data[3] % 2 == 1
                            {
                                // special case: if it's 255, we have to go down
                                if px.data[3] == 255
                                {
                                    px.data[3] = 254;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        px.data[3] += 1;
                                    }
                                    else
                                    {
                                        px.data[3] -= 1;
                                    }
                                }
                            }
                        }
                    }
                },
                RgbaMode::All =>
                {
                    for i in 0..8
                    {
                        let val = if i < 4
                        {
                            &mut pixels[0].data[i]
                        }
                        else
                        {
                            &mut pixels[1].data[i - 4]
                        };

                        if get_bit(byte, i as u8)
                        {
                            // even = 0 bit, so it needs to be changed
                            if *val % 2 == 0
                            {
                                // special case: if it's zero, we have to go up
                                if *val == 0
                                {
                                    *val = 1;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        *val += 1;
                                    }
                                    else
                                    {
                                        *val -= 1;
                                    }
                                }
                            }
                        }
                        // a false, or 0 bit
                        else
                        {
                            // odd = 1 bit, so it needs to be changed
                            if *val % 2 == 1
                            {
                                // special case: if it's 255, we have to go down
                                if *val == 255
                                {
                                    *val = 254;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        *val += 1;
                                    }
                                    else
                                    {
                                        *val -= 1;
                                    }
                                }
                            }
                        }
                    }
                },
            }
        }
    }

    fn decode(
        source: &RgbaImage,
        buffer: &mut [u8],
        len: usize,
        mode: RgbaMode)
    {
        assert!(len > buffer.len());

        // pixels per byte
        let ppb: usize = match mode
        {
            // one value per pixel = 8 pixels per byte
            RgbaMode::Alpha => 8,
            // four values per pixel = 2 pixels per byte
            RgbaMode::All => 2,
        };

        // iterate pixels
        for (index, pixels) in source.pixels()
            // split into ppb-sized chunks
            .chunks(ppb).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            .take(len)
            .enumerate()
        {
            // only decode while we have enough data
            if pixels.len() != ppb
            {
                break;
            }

            match mode
            {
                RgbaMode::Alpha =>
                {
                    let mut byte = 0u8;

                    for (i, px) in pixels.into_iter().enumerate()
                    {
                        byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                    }

                    buffer[index] = byte;
                },
                RgbaMode::All =>
                {
                    let mut byte = 0u8;

                    for i in 0..8
                    {
                        let val = if i < 4
                        {
                            pixels[0].data[i]
                        }
                        else
                        {
                            pixels[1].data[i - 4]
                        };

                        byte = set_bit(byte, i as u8, val % 2 == 1);
                    }

                    buffer[index] = byte;
                }
            }
        }
    }
}

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::All =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::All =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    byte = set_bit(byte, i as u8, val % 2 == 1);
                }

                buf.push(byte);
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in all field even/odd
    All,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

use std::str::FromStr;

impl FromStr for RgbaMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbaMode, ()>
    {
        if s == "alpha"
        {
            Ok(RgbaMode::Alpha)
        }
        else if s == "all"
        {
            Ok(RgbaMode::All)
        }
        else
        {
            Err(())
        }
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Alpha, rng);

        let dec = decode_rgba(&image, RgbaMode::Alpha);

        assert_eq!(payload, dec);
    }

    #[test]
    fn all()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            2,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::All, rng);

        let dec = decode_rgba(&image, RgbaMode::All);

        assert_eq!(payload, dec);
    }
}
<commit_msg>Made tests use the new RgbaCodec<commit_after>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbaCodec;

impl Codec for RgbaCodec
{
    type Input = RgbaImage;
    type Mode = RgbaMode;

    fn encode<R: Rng>(
        source: &mut RgbaImage,
        payload: &[u8],
        mode: RgbaMode,
        mut rng: R)
    {
        // number of pixels per byte
        let ppb = match mode
        {
            // 1 values per pixel = 8 pixels per byte
            RgbaMode::Alpha => 8,
            // 4 values per pixel = 2 pixels per byte
            RgbaMode::All => 2,
        };

        // iterate pixels mutably
        for (mut pixels, byte) in source.pixels_mut()
             // split them into ppb-size chunks
            .chunks(ppb).into_iter()
            // make them vectors so we can check their lengths later
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk a byte
            .zip(payload.iter().map(|x| *x))
        {
            // if the pixels don't fit exactly into their chunks,
            // the last chunk will be short. we won't use that chunk
            // (making sure the payload fits into the image is not
            // this functions job!)
            if pixels.len() != ppb
            {
                return;
            }

            match mode
            {
                RgbaMode::Alpha =>
                {
                    for (i, px) in pixels.into_iter().enumerate()
                    {
                        // a true, or 1 bit
                        if get_bit(byte, i as u8)
                        {
                            // even = 0 bit, so it needs to be changed
                            if px.data[3] % 2 == 0
                            {
                                // special case: if it's zero, we have to go up
                                if px.data[3] == 0
                                {
                                    px.data[3] = 1;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        px.data[3] += 1;
                                    }
                                    else
                                    {
                                        px.data[3] -= 1;
                                    }
                                }
                            }
                        }
                        // a false, or 0 bit
                        else
                        {
                            // odd = 1 bit, so it needs to be changed
                            if px.data[3] % 2 == 1
                            {
                                // special case: if it's 255, we have to go down
                                if px.data[3] == 255
                                {
                                    px.data[3] = 254;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        px.data[3] += 1;
                                    }
                                    else
                                    {
                                        px.data[3] -= 1;
                                    }
                                }
                            }
                        }
                    }
                },
                RgbaMode::All =>
                {
                    for i in 0..8
                    {
                        let val = if i < 4
                        {
                            &mut pixels[0].data[i]
                        }
                        else
                        {
                            &mut pixels[1].data[i - 4]
                        };

                        if get_bit(byte, i as u8)
                        {
                            // even = 0 bit, so it needs to be changed
                            if *val % 2 == 0
                            {
                                // special case: if it's zero, we have to go up
                                if *val == 0
                                {
                                    *val = 1;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        *val += 1;
                                    }
                                    else
                                    {
                                        *val -= 1;
                                    }
                                }
                            }
                        }
                        // a false, or 0 bit
                        else
                        {
                            // odd = 1 bit, so it needs to be changed
                            if *val % 2 == 1
                            {
                                // special case: if it's 255, we have to go down
                                if *val == 255
                                {
                                    *val = 254;
                                }
                                else
                                {
                                    if rng.gen()
                                    {
                                        *val += 1;
                                    }
                                    else
                                    {
                                        *val -= 1;
                                    }
                                }
                            }
                        }
                    }
                },
            }
        }
    }

    fn decode(
        source: &RgbaImage,
        buffer: &mut [u8],
        len: usize,
        mode: RgbaMode)
    {
        assert!(len >= buffer.len());

        // pixels per byte
        let ppb: usize = match mode
        {
            // one value per pixel = 8 pixels per byte
            RgbaMode::Alpha => 8,
            // four values per pixel = 2 pixels per byte
            RgbaMode::All => 2,
        };

        // iterate pixels
        for (index, pixels) in source.pixels()
            // split into ppb-sized chunks
            .chunks(ppb).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            .take(len)
            .enumerate()
        {
            // only decode while we have enough data
            if pixels.len() != ppb
            {
                break;
            }

            match mode
            {
                RgbaMode::Alpha =>
                {
                    let mut byte = 0u8;

                    for (i, px) in pixels.into_iter().enumerate()
                    {
                        byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                    }

                    buffer[index] = byte;
                },
                RgbaMode::All =>
                {
                    let mut byte = 0u8;

                    for i in 0..8
                    {
                        let val = if i < 4
                        {
                            pixels[0].data[i]
                        }
                        else
                        {
                            pixels[1].data[i - 4]
                        };

                        byte = set_bit(byte, i as u8, val % 2 == 1);
                    }

                    buffer[index] = byte;
                }
            }
        }
    }
}

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::All =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::All =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    byte = set_bit(byte, i as u8, val % 2 == 1);
                }

                buf.push(byte);
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in all field even/odd
    All,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

use std::str::FromStr;

impl FromStr for RgbaMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbaMode, ()>
    {
        if s == "alpha"
        {
            Ok(RgbaMode::Alpha)
        }
        else if s == "all"
        {
            Ok(RgbaMode::All)
        }
        else
        {
            Err(())
        }
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use codec::Codec;
    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let mut buf = vec![0; 25];

        let rng = StdRng::new().unwrap();

        RgbaCodec::encode(&mut image, &payload, RgbaMode::Alpha, rng);

        RgbaCodec::decode(&image, &mut buf, 25, RgbaMode::Alpha);

        assert_eq!(payload, buf);
    }

    #[test]
    fn all()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            2,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let mut buf = vec![0; 25];

        let rng = StdRng::new().unwrap();

        RgbaCodec::encode(&mut image, &payload, RgbaMode::All, rng);

        RgbaCodec::decode(&image, &mut buf, 25, RgbaMode::All);

        assert_eq!(payload, buf);
    }
}
<|endoftext|>


<commit_before>
use std::str;
use std::io::{self, Read, Write};

use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, Next};
use hyper::header::{ContentLength, ContentType};
use hyper::net::HttpStream;

use hyper::server::Server;
use hyper::server::Handler as HyperHandler;
use hyper::server::Request as HyperRequest;
use hyper::server::Response as HyperResponse;
use hyper::method::Method;
use hyper::version::HttpVersion;

use std::result::Result as StdResult;
use std::error::Error as StdError;
use std::sync::Arc;
use std::marker::Reflect;
use std::clone::Clone;
use std::marker::PhantomData;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::Request;
pub use response::Response;
pub use router::Router;
pub use srouter::SRouter;
pub use shandler::SHandler;

#[derive(Debug, PartialEq)]
pub enum Error {
    BeforeError,
    HandlerError,
    AfterError,
    RouterConfigError,
    RedirectError,
    NotFoundError,
}

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone)]
pub struct ReqPathParams;

pub trait SModule {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

    // here add routers ....
    fn router(&self, &mut SRouter) -> Result<()>;
    // fn router(&self, SRouter) -> Result<SRouter>;

}

pub trait SAppWrapper {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

}

// later will add more fields
pub struct SApp<T: SModule + Send + 'static, W: SAppWrapper + Send + 'static> {
    pub address: String,
    pub port:    u32,
    // for app entry, global middeware
    pub wrapper: Option<W>,
    // for actually use to recognize
    pub routers: Router,
    // marker for type T
    pub _marker: PhantomData<T>,
}

impl<T, W> SApp<T, W>
    where   T: SModule + Send + Sync + Reflect + Clone + 'static,
            W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
    {
    pub fn new() -> SApp<T, W> {
        SApp {
            address: String::new(),
            port: 0,
            wrapper: None,
            routers: Router::new(),
            _marker: PhantomData
        }
    }

    pub fn run(self) {

        let listen_addr = self.address.clone() + ":" + &self.port.to_string();
        let arc_sapp = Arc::new(Box::new(self));

        let server = Server::http(&listen_addr.parse().unwrap()).unwrap();
        let _guard = server.handle(move |_| {
            RequestHandler::new(arc_sapp.clone())
        });
    }

    pub fn with_wrapper(&mut self, w: W) -> &mut Self {
        self.wrapper = Some(w);
        self
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    // add methods of this smodule
    // prefix:  such as '/user'
    pub fn add_module(&mut self, sm: T) -> &mut Self {

        let mut router = SRouter::new();
        // get the sm router
        // pass self.router in
        sm.router(&mut router).unwrap();
        // combile this router to global big router
        // create a new closure, containing
        //      0. execute sapp.before();
        //      1. execute sm.before();
        //      2. execute a_router map pair value part function;
        //      3. execute sm.after();
        //      4. execute sapp.after();
        // fill the self.routers finally
        // assign this new closure to the routers router map pair  prefix + url part

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let wrapper = self.wrapper.clone().unwrap();
                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut Request| -> Result<Response> {
                    wrapper.before(req).unwrap();
                    sm.before(req).unwrap();
                    let res: Result<Response> = handler.handle(req);
                    let mut response = res.unwrap();
                    sm.after(req, &mut response).unwrap();
                    wrapper.after(req, &mut response).unwrap();
                    Ok(response)
                })));
            }
        }

        // self.modules.push(sm);

        self
    }
}

pub struct RequestHandler<
        T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static> {
    // router, keep the original handler function
    // pub router: SRouter,
    // wrapped router, keep the wrapped handler function
    // for actually use to recognize
    pub sapp: Arc<Box<SApp<T, W>>>,
    pub path: String,
    pub method: Method,
    pub version: HttpVersion,
    pub headers: Headers,
    pub buf: Vec<u8>,
    pub body: String,
    pub has_body: bool,
    // response deliver
    pub response: Option<Response>,
}

impl<T, W> RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
{
    pub fn new(sapp: Arc<Box<SApp<T, W>>>) -> RequestHandler<T, W> {
        RequestHandler {
            sapp: sapp,
            path: String::new(),
            method: Default::default(),
            version: Default::default(),
            headers: Default::default(),
            buf: vec![0; 2048],
            body: String::new(),
            has_body: false,
            response: None
        }
    }

}

impl<T, W> HyperHandler<HttpStream> for RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
 {
    fn on_request(&mut self, req: HyperRequest) -> Next {
        match *req.uri() {
            RequestUri::AbsolutePath(ref path) =>  {
                // if has_body
                if req.headers().get::<ContentLength>().is_some()
                    || req.headers().get::<ContentType>().is_some()
                 {
                    self.path = path.to_owned();
                    self.method = req.method().clone();
                    self.version = req.version().clone();
                    self.headers = req.headers().clone();
                    self.has_body = true;
                    Next::read_and_write()
                }
                else {
                    // if no body
                    let pathstr = &path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }

                    // make swiftrs request from hyper request
                    let mut sreq = Request::new(
                        req.method().clone(),
                        req.version().clone(),
                        req.headers().clone(),
                        path.clone(),
                        query_string);

                    match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                        Ok(response) => self.response = Some(response),
                        Err(e) => {
                            if e == Error::NotFoundError {
                                self.response = None
                            }
                        }
                    }

                    Next::write()
                }

                // XXX: Need more work
                // self.response = self.routers.handle_method(&mut sreq, &path).unwrap().ok();

                // TODO: complete it later
                // .unwrap_or_else(||
                    // match req.method {
                    //     method::Options => Ok(self.handle_options(&path)),
                    //     // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    //     method::Head => {
                    //         req.method = method::Get;
                    //         self.handle_method(req, &path).unwrap_or(
                    //             Err(IronError::new(NoRoute, status::NotFound))
                    //         )
                    //     }
                    //     _ => Err(IronError::new(NoRoute, status::NotFound))
                    // }
                // );
                // currently

                // if is_more {
                //     Next::read_and_write()
                // } else {
                //     Next::write()
                // }

                // Next::read_and_write()
                // Next::write()
            },
            _ => Next::write()
        }
    }
    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        if self.has_body {
            match transport.read(&mut self.buf) {
                Ok(0) => {
                    debug!("Read 0, eof");

                    // TODO: need optimize
                    let pathstr = &self.path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }
                    let mut sreq = Request::new(
                        self.method.clone(),
                        self.version.clone(),
                        self.headers.clone(),
                        path.clone(),
                        query_string);

                    sreq.set_raw_body(self.body.clone());

                    match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                        Ok(response) => self.response = Some(response),
                        Err(e) => {
                            if e == Error::NotFoundError {
                                self.response = None
                            }
                        }
                    }
                    //
                    return Next::write()
                },
                Ok(n) => {
                    self.body.push_str(str::from_utf8(&self.buf[0..n]).unwrap());
                    return Next::read_and_write()
                }
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => return Next::read_and_write(),
                    _ => {
                        println!("read error {:?}", e);
                        return Next::end()
                    }
                }
            }
        }

        Next::write()
    }

    fn on_response(&mut self, res: &mut HyperResponse) -> Next {
        match self.response {
            Some(ref response) => {
                if let &Some(ref body) = response.body() {
                    // here, set hyper response status code, and headers
                    res.headers_mut().set(ContentLength(body.len() as u64));
                }
                Next::write()
            },
            None => {
                // Inner Error
                // end
                res.set_status(StatusCode::NotFound);
                res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                Next::write()
            }
        }

    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        match self.response {
            Some(ref response) => {
                if let &Some(ref body) = response.body() {
                    // write response.body.unwrap() to transport
                    transport.write(body.as_bytes()).unwrap();
                }
                Next::end()
            },
            None => {
                transport.write("404 Not Found".as_bytes()).unwrap();
                // end
                Next::end()
            }
        }

    }
}
<commit_msg>update high level response headers to low level hyper mio response headers.<commit_after>
use std::str;
use std::io::{self, Read, Write};

use hyper::{Get, Post, StatusCode, RequestUri, Decoder, Encoder, Next};
use hyper::header::{ContentLength, ContentType};
use hyper::net::HttpStream;

use hyper::server::Server;
use hyper::server::Handler as HyperHandler;
use hyper::server::Request as HyperRequest;
use hyper::server::Response as HyperResponse;
use hyper::method::Method;
use hyper::version::HttpVersion;

use std::result::Result as StdResult;
use std::error::Error as StdError;
use std::sync::Arc;
use std::marker::Reflect;
use std::clone::Clone;
use std::marker::PhantomData;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::Request;
pub use response::Response;
pub use router::Router;
pub use srouter::SRouter;
pub use shandler::SHandler;

#[derive(Debug, PartialEq)]
pub enum Error {
    BeforeError,
    HandlerError,
    AfterError,
    RouterConfigError,
    RedirectError,
    NotFoundError,
}

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Clone)]
pub struct ReqPathParams;

pub trait SModule {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

    // here add routers ....
    fn router(&self, &mut SRouter) -> Result<()>;
    // fn router(&self, SRouter) -> Result<SRouter>;

}

pub trait SAppWrapper {
    fn before(&self, &mut Request) -> Result<()>;

    fn after(&self, &Request, &mut Response) -> Result<()>;

}

// later will add more fields
pub struct SApp<T: SModule + Send + 'static, W: SAppWrapper + Send + 'static> {
    pub address: String,
    pub port:    u32,
    // for app entry, global middeware
    pub wrapper: Option<W>,
    // for actually use to recognize
    pub routers: Router,
    // marker for type T
    pub _marker: PhantomData<T>,
}

impl<T, W> SApp<T, W>
    where   T: SModule + Send + Sync + Reflect + Clone + 'static,
            W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
    {
    pub fn new() -> SApp<T, W> {
        SApp {
            address: String::new(),
            port: 0,
            wrapper: None,
            routers: Router::new(),
            _marker: PhantomData
        }
    }

    pub fn run(self) {

        let listen_addr = self.address.clone() + ":" + &self.port.to_string();
        let arc_sapp = Arc::new(Box::new(self));

        let server = Server::http(&listen_addr.parse().unwrap()).unwrap();
        let _guard = server.handle(move |_| {
            RequestHandler::new(arc_sapp.clone())
        });
    }

    pub fn with_wrapper(&mut self, w: W) -> &mut Self {
        self.wrapper = Some(w);
        self
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    // add methods of this smodule
    // prefix:  such as '/user'
    pub fn add_module(&mut self, sm: T) -> &mut Self {

        let mut router = SRouter::new();
        // get the sm router
        // pass self.router in
        sm.router(&mut router).unwrap();
        // combile this router to global big router
        // create a new closure, containing
        //      0. execute sapp.before();
        //      1. execute sm.before();
        //      2. execute a_router map pair value part function;
        //      3. execute sm.after();
        //      4. execute sapp.after();
        // fill the self.routers finally
        // assign this new closure to the routers router map pair  prefix + url part

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let wrapper = self.wrapper.clone().unwrap();
                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut Request| -> Result<Response> {
                    wrapper.before(req).unwrap();
                    sm.before(req).unwrap();
                    let res: Result<Response> = handler.handle(req);
                    let mut response = res.unwrap();
                    sm.after(req, &mut response).unwrap();
                    wrapper.after(req, &mut response).unwrap();
                    Ok(response)
                })));
            }
        }

        // self.modules.push(sm);

        self
    }
}

pub struct RequestHandler<
        T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static> {
    // router, keep the original handler function
    // pub router: SRouter,
    // wrapped router, keep the wrapped handler function
    // for actually use to recognize
    pub sapp: Arc<Box<SApp<T, W>>>,
    pub path: String,
    pub method: Method,
    pub version: HttpVersion,
    pub headers: Headers,
    pub buf: Vec<u8>,
    pub body: String,
    pub has_body: bool,
    // response deliver
    pub response: Option<Response>,
}

impl<T, W> RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
{
    pub fn new(sapp: Arc<Box<SApp<T, W>>>) -> RequestHandler<T, W> {
        RequestHandler {
            sapp: sapp,
            path: String::new(),
            method: Default::default(),
            version: Default::default(),
            headers: Default::default(),
            buf: vec![0; 2048],
            body: String::new(),
            has_body: false,
            response: None
        }
    }

}

impl<T, W> HyperHandler<HttpStream> for RequestHandler<T, W>
where   T: SModule + Send + Sync + Reflect + Clone + 'static,
        W: SAppWrapper + Send + Sync + Reflect + Clone + 'static
 {
    fn on_request(&mut self, req: HyperRequest) -> Next {
        match *req.uri() {
            RequestUri::AbsolutePath(ref path) =>  {
                // if has_body
                if req.headers().get::<ContentLength>().is_some()
                    || req.headers().get::<ContentType>().is_some()
                 {
                    self.path = path.to_owned();
                    self.method = req.method().clone();
                    self.version = req.version().clone();
                    self.headers = req.headers().clone();
                    self.has_body = true;
                    Next::read_and_write()
                }
                else {
                    // if no body
                    let pathstr = &path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }

                    // make swiftrs request from hyper request
                    let mut sreq = Request::new(
                        req.method().clone(),
                        req.version().clone(),
                        req.headers().clone(),
                        path.clone(),
                        query_string);

                    match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                        Ok(response) => self.response = Some(response),
                        Err(e) => {
                            if e == Error::NotFoundError {
                                self.response = None
                            }
                        }
                    }

                    Next::write()
                }

                // XXX: Need more work
                // self.response = self.routers.handle_method(&mut sreq, &path).unwrap().ok();

                // TODO: complete it later
                // .unwrap_or_else(||
                    // match req.method {
                    //     method::Options => Ok(self.handle_options(&path)),
                    //     // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    //     method::Head => {
                    //         req.method = method::Get;
                    //         self.handle_method(req, &path).unwrap_or(
                    //             Err(IronError::new(NoRoute, status::NotFound))
                    //         )
                    //     }
                    //     _ => Err(IronError::new(NoRoute, status::NotFound))
                    // }
                // );
                // currently

                // if is_more {
                //     Next::read_and_write()
                // } else {
                //     Next::write()
                // }

                // Next::read_and_write()
                // Next::write()
            },
            _ => Next::write()
        }
    }
    fn on_request_readable(&mut self, transport: &mut Decoder<HttpStream>) -> Next {
        if self.has_body {
            match transport.read(&mut self.buf) {
                Ok(0) => {
                    debug!("Read 0, eof");

                    // TODO: need optimize
                    let pathstr = &self.path[..];
                    let pathvec: Vec<&str> = pathstr.split('?').collect();
                    let path = pathvec[0].to_owned();
                    let mut query_string = None;

                    // if has query_string
                    if pathvec.len() > 1 {
                        query_string = Some(pathvec[1].to_owned());
                    }
                    let mut sreq = Request::new(
                        self.method.clone(),
                        self.version.clone(),
                        self.headers.clone(),
                        path.clone(),
                        query_string);

                    sreq.set_raw_body(self.body.clone());

                    match self.sapp.routers.handle_method(&mut sreq, &path).unwrap() {
                        Ok(response) => self.response = Some(response),
                        Err(e) => {
                            if e == Error::NotFoundError {
                                self.response = None
                            }
                        }
                    }
                    //
                    return Next::write()
                },
                Ok(n) => {
                    self.body.push_str(str::from_utf8(&self.buf[0..n]).unwrap());
                    return Next::read_and_write()
                }
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => return Next::read_and_write(),
                    _ => {
                        println!("read error {:?}", e);
                        return Next::end()
                    }
                }
            }
        }

        Next::write()
    }

    fn on_response(&mut self, res: &mut HyperResponse) -> Next {
        match self.response {
            Some(ref response) => {
                if let &Some(ref body) = response.body() {
                    // update top level headers to low level headers
                    for header in response.headers().iter() {
                        res.headers_mut()
                            .set_raw(header.name().to_owned(),
                                vec![header.value_string().as_bytes().to_vec()]);
                    }

                    // here, set hyper response status code, and headers
                    res.headers_mut().set(ContentLength(body.len() as u64));
                }
                Next::write()
            },
            None => {
                // Inner Error
                // end
                res.set_status(StatusCode::NotFound);
                res.headers_mut().set(ContentLength("404 Not Found".len() as u64));
                Next::write()
            }
        }

    }

    fn on_response_writable(&mut self, transport: &mut Encoder<HttpStream>) -> Next {
        match self.response {
            Some(ref response) => {
                if let &Some(ref body) = response.body() {
                    // write response.body.unwrap() to transport
                    transport.write(body.as_bytes()).unwrap();
                }
                Next::end()
            },
            None => {
                transport.write("404 Not Found".as_bytes()).unwrap();
                // end
                Next::end()
            }
        }

    }
}
<|endoftext|>


<commit_before>use std::cmp::{Ordering};
use std::collections::{BinaryHeap};

#[derive(Eq, PartialEq, Debug)]
pub struct Length(pub String);

impl Ord for Length {
    fn cmp(&self, other: &Self) -> Ordering {
        use std::cmp::Ordering::*;

        let len = self.0.len().cmp(&other.0.len());
        match len {
            Equal => self.0.cmp(&other.0).reverse(),
            _ => len,
        }
    }
}

impl PartialOrd for Length {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

pub struct HeapDrain<'a, T> where T: 'a + Ord {
    heap: &'a mut BinaryHeap<T>,
}

pub trait HeapPopDrain<T> where T: Ord {
    fn pop_drain(&mut self) -> HeapDrain<T>;
}

impl<T> HeapPopDrain<T> for BinaryHeap<T> where T: Ord {
    fn pop_drain(&mut self) -> HeapDrain<T> {
        HeapDrain{
            heap: self,
        }
    }
}

impl<'a, T> Iterator for HeapDrain<'a, T> where T: 'a + Ord {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.heap.pop()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_length() {
        use super::{Length};
        use std::cmp::{Ordering};

        let short = Length("short".to_string());
        let longer = Length("longer".to_string());
        let equal = Length("equal".to_string());

        assert_eq!(short.cmp(&longer), Ordering::Less);
        assert_eq!(longer.cmp(&short), Ordering::Greater);
        assert_eq!(short.cmp(&equal), Ordering::Equal);
    }

    #[test]
    fn test_heapdrain() {
        use super::{Length, HeapPopDrain};
        use std::collections::{BinaryHeap};

        {
            let mut heap = BinaryHeap::new();
            heap.push(3);
            heap.push(9);
            heap.push(6);

            let mut drain = heap.pop_drain();
            assert_eq!(drain.next(), Some(9));
            assert_eq!(drain.next(), Some(6));
            assert_eq!(drain.next(), Some(3));
            assert_eq!(drain.next(), None);
        }

        {
            let mut heap = BinaryHeap::new();
            heap.push(Length("short".to_string()));
            heap.push(Length("notequal".to_string()));
            heap.push(Length("longer".to_string()));

            let mut drain = heap.pop_drain();
            assert_eq!(drain.next(), Some(Length("notequal".to_string())));
            assert_eq!(drain.next(), Some(Length("longer".to_string())));
            assert_eq!(drain.next(), Some(Length("short".to_string())));
            assert_eq!(drain.next(), None);
        }
    }
}
<commit_msg>Remove now-unused HeapDrain.<commit_after>use std::cmp::{Ordering};

#[derive(Eq, PartialEq, Debug)]
pub struct Length(pub String);

impl Ord for Length {
    fn cmp(&self, other: &Self) -> Ordering {
        use std::cmp::Ordering::*;

        let len = self.0.len().cmp(&other.0.len());
        match len {
            Equal => self.0.cmp(&other.0).reverse(),
            _ => len,
        }
    }
}

impl PartialOrd for Length {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_length() {
        use super::{Length};
        use std::cmp::{Ordering};

        let short = Length("short".to_string());
        let longer = Length("longer".to_string());
        let equal = Length("equal".to_string());

        assert_eq!(short.cmp(&longer), Ordering::Less);
        assert_eq!(longer.cmp(&short), Ordering::Greater);
        assert_eq!(short.cmp(&equal), Ordering::Equal);
    }
}
<|endoftext|>


<commit_before>//! Helper functions and structures for the translation.
use cranelift_codegen::ir;
use std::u32;
use wasmparser;

/// Index type of a function (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct FuncIndex(u32);
entity_impl!(FuncIndex);

/// Index type of a defined function inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedFuncIndex(u32);
entity_impl!(DefinedFuncIndex);

/// Index type of a table (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct TableIndex(u32);
entity_impl!(TableIndex);

/// Index type of a global variable (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct GlobalIndex(u32);
entity_impl!(GlobalIndex);

/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct MemoryIndex(u32);
entity_impl!(MemoryIndex);

/// Index type of a signature (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SignatureIndex(u32);
entity_impl!(SignatureIndex);

/// WebAssembly global.
#[derive(Debug, Clone, Copy)]
pub struct Global {
    /// The type of the value stored in the global.
    pub ty: ir::Type,
    /// A flag indicating whether the value may change at runtime.
    pub mutability: bool,
    /// The source of the initial value.
    pub initializer: GlobalInit,
}

/// Globals are initialized via the four `const` operators or by referring to another import.
#[derive(Debug, Clone, Copy)]
pub enum GlobalInit {
    /// An `i32.const`.
    I32Const(i32),
    /// An `i64.const`.
    I64Const(i64),
    /// An `f32.const`.
    F32Const(u32),
    /// An `f64.const`.
    F64Const(u64),
    /// A `get_global` of another global.
    GlobalRef(GlobalIndex),
    ///< The global is imported from, and thus initialized by, a different module.
    Import(),
}

/// WebAssembly table.
#[derive(Debug, Clone, Copy)]
pub struct Table {
    /// The type of data stored in elements of the table.
    pub ty: TableElementType,
    /// The minimum number of elements in the table.
    pub size: usize,
    /// The maximum number of elements in the table.
    pub maximum: Option<usize>,
}

/// WebAssembly table element. Can be a function or a scalar type.
#[derive(Debug, Clone, Copy)]
pub enum TableElementType {
    Val(ir::Type),
    Func(),
}

/// WebAssembly linear memory.
#[derive(Debug, Clone, Copy)]
pub struct Memory {
    /// The minimum number of pages in the memory.
    pub pages_count: usize,
    /// The maximum number of pages in the memory.
    pub maximum: Option<usize>,
    /// Whether the memory may be shared between multiple threads.
    pub shared: bool,
}

/// Helper function translating wasmparser types to Cranelift types when possible.
pub fn type_to_type(ty: wasmparser::Type) -> Result<ir::Type, ()> {
    match ty {
        wasmparser::Type::I32 => Ok(ir::types::I32),
        wasmparser::Type::I64 => Ok(ir::types::I64),
        wasmparser::Type::F32 => Ok(ir::types::F32),
        wasmparser::Type::F64 => Ok(ir::types::F64),
        _ => Err(()),
    }
}

/// Turns a `wasmparser` `f32` into a `Cranelift` one.
pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
    ir::immediates::Ieee32::with_bits(x.bits())
}

/// Turns a `wasmparser` `f64` into a `Cranelift` one.
pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
    ir::immediates::Ieee64::with_bits(x.bits())
}

/// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible
pub fn num_return_values(ty: wasmparser::Type) -> usize {
    match ty {
        wasmparser::Type::EmptyBlockType => 0,
        wasmparser::Type::I32
        | wasmparser::Type::F32
        | wasmparser::Type::I64
        | wasmparser::Type::F64 => 1,
        _ => panic!("unsupported return value type"),
    }
}
<commit_msg>Make cranelift-wasm's `type_to_type` easier to optimize.<commit_after>//! Helper functions and structures for the translation.
use cranelift_codegen::ir;
use std::u32;
use wasmparser;

/// Index type of a function (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct FuncIndex(u32);
entity_impl!(FuncIndex);

/// Index type of a defined function inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct DefinedFuncIndex(u32);
entity_impl!(DefinedFuncIndex);

/// Index type of a table (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct TableIndex(u32);
entity_impl!(TableIndex);

/// Index type of a global variable (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct GlobalIndex(u32);
entity_impl!(GlobalIndex);

/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct MemoryIndex(u32);
entity_impl!(MemoryIndex);

/// Index type of a signature (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct SignatureIndex(u32);
entity_impl!(SignatureIndex);

/// WebAssembly global.
#[derive(Debug, Clone, Copy)]
pub struct Global {
    /// The type of the value stored in the global.
    pub ty: ir::Type,
    /// A flag indicating whether the value may change at runtime.
    pub mutability: bool,
    /// The source of the initial value.
    pub initializer: GlobalInit,
}

/// Globals are initialized via the four `const` operators or by referring to another import.
#[derive(Debug, Clone, Copy)]
pub enum GlobalInit {
    /// An `i32.const`.
    I32Const(i32),
    /// An `i64.const`.
    I64Const(i64),
    /// An `f32.const`.
    F32Const(u32),
    /// An `f64.const`.
    F64Const(u64),
    /// A `get_global` of another global.
    GlobalRef(GlobalIndex),
    ///< The global is imported from, and thus initialized by, a different module.
    Import(),
}

/// WebAssembly table.
#[derive(Debug, Clone, Copy)]
pub struct Table {
    /// The type of data stored in elements of the table.
    pub ty: TableElementType,
    /// The minimum number of elements in the table.
    pub size: usize,
    /// The maximum number of elements in the table.
    pub maximum: Option<usize>,
}

/// WebAssembly table element. Can be a function or a scalar type.
#[derive(Debug, Clone, Copy)]
pub enum TableElementType {
    Val(ir::Type),
    Func(),
}

/// WebAssembly linear memory.
#[derive(Debug, Clone, Copy)]
pub struct Memory {
    /// The minimum number of pages in the memory.
    pub pages_count: usize,
    /// The maximum number of pages in the memory.
    pub maximum: Option<usize>,
    /// Whether the memory may be shared between multiple threads.
    pub shared: bool,
}

/// Helper function translating wasmparser types to Cranelift types when possible.
pub fn type_to_type(ty: wasmparser::Type) -> Result<ir::Type, ()> {
    Ok(match ty {
        wasmparser::Type::I32 => ir::types::I32,
        wasmparser::Type::I64 => ir::types::I64,
        wasmparser::Type::F32 => ir::types::F32,
        wasmparser::Type::F64 => ir::types::F64,
        _ => return Err(()),
    })
}

/// Turns a `wasmparser` `f32` into a `Cranelift` one.
pub fn f32_translation(x: wasmparser::Ieee32) -> ir::immediates::Ieee32 {
    ir::immediates::Ieee32::with_bits(x.bits())
}

/// Turns a `wasmparser` `f64` into a `Cranelift` one.
pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
    ir::immediates::Ieee64::with_bits(x.bits())
}

/// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible
pub fn num_return_values(ty: wasmparser::Type) -> usize {
    match ty {
        wasmparser::Type::EmptyBlockType => 0,
        wasmparser::Type::I32
        | wasmparser::Type::F32
        | wasmparser::Type::I64
        | wasmparser::Type::F64 => 1,
        _ => panic!("unsupported return value type"),
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use chrono::naive::datetime::NaiveDateTime;
use serde_json::value::Value;
use uuid::Uuid;

use error::TaskError;
use error::TaskErrorKind;
use priority::TaskPriority;
use result::Result;
use status::TaskStatus;
use project::Project;
use tag::Tag;

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

#[derive(Debug, Clone)]
pub struct Task {
    status      : TaskStatus,
    uuid        : Uuid,
    entry       : NaiveDateTime,
    description : String,

    annotation  : Option<Vec<String>>,
    depends     : Option<String>,
    due         : Option<NaiveDateTime>,
    end         : Option<NaiveDateTime>,
    imask       : Option<i64>,
    mask        : Option<String>,
    modified    : Option<NaiveDateTime>,
    parent      : Option<Uuid>,
    priority    : Option<TaskPriority>,
    project     : Option<Project>,
    recur       : Option<String>,
    scheduled   : Option<NaiveDateTime>,
    start       : Option<NaiveDateTime>,
    tags        : Option<Vec<Tag>>,
    until       : Option<NaiveDateTime>,
    wait        : Option<NaiveDateTime>,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn new(
        status      : TaskStatus,
        uuid        : Uuid,
        entry       : NaiveDateTime,
        description : String,

        annotation  : Option<Vec<String>>,
        depends     : Option<String>,
        due         : Option<NaiveDateTime>,
        end         : Option<NaiveDateTime>,
        imask       : Option<i64>,
        mask        : Option<String>,
        modified    : Option<NaiveDateTime>,
        parent      : Option<Uuid>,
        priority    : Option<TaskPriority>,
        project     : Option<Project>,
        recur       : Option<String>,
        scheduled   : Option<NaiveDateTime>,
        start       : Option<NaiveDateTime>,
        tags        : Option<Vec<Tag>>,
        until       : Option<NaiveDateTime>,
        wait        : Option<NaiveDateTime>,
    ) -> Task
    {
        Task {
            status      : status,
            uuid        : uuid,
            entry       : entry,
            description : description,

            annotation  : annotation,
            depends     : depends,
            due         : due,
            end         : end,
            imask       : imask,
            mask        : mask,
            modified    : modified,
            parent      : parent,
            priority    : priority,
            project     : project,
            recur       : recur,
            scheduled   : scheduled,
            start       : start,
            tags        : tags,
            until       : until,
            wait        : wait,
        }
    }

    pub fn status(&self) -> &TaskStatus {
        &self.status
    }

    pub fn uuid(&self) -> Uuid {
        &self.uuid
    }

    pub fn entry(&self) -> NaiveDateTime {
        &self.entry
    }

    pub fn description(&self) -> String {
        &self.description
    }

    pub fn annotation(&self) -> Option<&Vec<String>> {
        self.annotation.as_ref()
    }

    pub fn depends(&self) -> Option<&String> {
        self.depends.as_ref()
    }

    pub fn due(&self) -> Option<&NaiveDateTime> {
        self.due.as_ref()
    }

    pub fn end(&self) -> Option<&NaiveDateTime> {
        self.end.as_ref()
    }

    pub fn imask(&self) -> Option<&i64> {
        self.imask.as_ref()
    }

    pub fn mask(&self) -> Option<&String> {
        self.mask.as_ref()
    }

    pub fn modified(&self) -> Option<&NaiveDateTime> {
        self.modified.as_ref()
    }

    pub fn parent(&self) -> Option<&Uuid> {
        self.parent.as_ref()
    }

    pub fn priority(&self) -> Option<&TaskPriority> {
        self.priority.as_ref()
    }

    pub fn project(&self) -> Option<&Project> {
        self.project.as_ref()
    }

    pub fn recur(&self) -> Option<&String> {
        self.recur.as_ref()
    }

    pub fn scheduled(&self) -> Option<&NaiveDateTime> {
        self.scheduled.as_ref()
    }

    pub fn start(&self) -> Option<&NaiveDateTime> {
        self.start.as_ref()
    }

    pub fn tags(&self) -> Option<&Vec<Tag>> {
        self.tags.as_ref()
    }

    pub fn until(&self) -> Option<&NaiveDateTime> {
        self.until.as_ref()
    }

    pub fn wait(&self) -> Option<&NaiveDateTime> {
        self.wait.as_ref()
    }

}

impl Into<Value> for Task {

    fn into(self) -> Value {
        unimplemented!()
    }

}

pub trait FromJson {

    fn from_json(Value) -> Result<Self>;

}

impl FromJson for Task {

    fn from_json(v: Value) -> Result<Self> {
        unimplemented!()
    }

}

<commit_msg>Start implementing de/ser for Task<commit_after>use std::collections::BTreeMap;
use std::result::Result as RResult;

use chrono::naive::datetime::NaiveDateTime;
use serde_json::value::Value;
use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use uuid::Uuid;

use error::TaskError;
use error::TaskErrorKind;
use priority::TaskPriority;
use result::Result;
use status::TaskStatus;
use project::Project;
use tag::Tag;

pub static TASKWARRIOR_DATETIME_TEMPLATE : &'static str = "%Y%m%dT%H%M%SZ";

#[derive(Debug, Clone)]
pub struct Task {
    status      : TaskStatus,
    uuid        : Uuid,
    entry       : NaiveDateTime,
    description : String,

    annotation  : Option<Vec<String>>,
    depends     : Option<String>,
    due         : Option<NaiveDateTime>,
    end         : Option<NaiveDateTime>,
    imask       : Option<i64>,
    mask        : Option<String>,
    modified    : Option<NaiveDateTime>,
    parent      : Option<Uuid>,
    priority    : Option<TaskPriority>,
    project     : Option<Project>,
    recur       : Option<String>,
    scheduled   : Option<NaiveDateTime>,
    start       : Option<NaiveDateTime>,
    tags        : Option<Vec<Tag>>,
    until       : Option<NaiveDateTime>,
    wait        : Option<NaiveDateTime>,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn new(
        status      : TaskStatus,
        uuid        : Uuid,
        entry       : NaiveDateTime,
        description : String,

        annotation  : Option<Vec<String>>,
        depends     : Option<String>,
        due         : Option<NaiveDateTime>,
        end         : Option<NaiveDateTime>,
        imask       : Option<i64>,
        mask        : Option<String>,
        modified    : Option<NaiveDateTime>,
        parent      : Option<Uuid>,
        priority    : Option<TaskPriority>,
        project     : Option<Project>,
        recur       : Option<String>,
        scheduled   : Option<NaiveDateTime>,
        start       : Option<NaiveDateTime>,
        tags        : Option<Vec<Tag>>,
        until       : Option<NaiveDateTime>,
        wait        : Option<NaiveDateTime>,
    ) -> Task
    {
        Task {
            status      : status,
            uuid        : uuid,
            entry       : entry,
            description : description,

            annotation  : annotation,
            depends     : depends,
            due         : due,
            end         : end,
            imask       : imask,
            mask        : mask,
            modified    : modified,
            parent      : parent,
            priority    : priority,
            project     : project,
            recur       : recur,
            scheduled   : scheduled,
            start       : start,
            tags        : tags,
            until       : until,
            wait        : wait,
        }
    }

    pub fn status(&self) -> &TaskStatus {
        &self.status
    }

    pub fn uuid(&self) -> Uuid {
        &self.uuid
    }

    pub fn entry(&self) -> NaiveDateTime {
        &self.entry
    }

    pub fn description(&self) -> String {
        &self.description
    }

    pub fn annotation(&self) -> Option<&Vec<String>> {
        self.annotation.as_ref()
    }

    pub fn depends(&self) -> Option<&String> {
        self.depends.as_ref()
    }

    pub fn due(&self) -> Option<&NaiveDateTime> {
        self.due.as_ref()
    }

    pub fn end(&self) -> Option<&NaiveDateTime> {
        self.end.as_ref()
    }

    pub fn imask(&self) -> Option<&i64> {
        self.imask.as_ref()
    }

    pub fn mask(&self) -> Option<&String> {
        self.mask.as_ref()
    }

    pub fn modified(&self) -> Option<&NaiveDateTime> {
        self.modified.as_ref()
    }

    pub fn parent(&self) -> Option<&Uuid> {
        self.parent.as_ref()
    }

    pub fn priority(&self) -> Option<&TaskPriority> {
        self.priority.as_ref()
    }

    pub fn project(&self) -> Option<&Project> {
        self.project.as_ref()
    }

    pub fn recur(&self) -> Option<&String> {
        self.recur.as_ref()
    }

    pub fn scheduled(&self) -> Option<&NaiveDateTime> {
        self.scheduled.as_ref()
    }

    pub fn start(&self) -> Option<&NaiveDateTime> {
        self.start.as_ref()
    }

    pub fn tags(&self) -> Option<&Vec<Tag>> {
        self.tags.as_ref()
    }

    pub fn until(&self) -> Option<&NaiveDateTime> {
        self.until.as_ref()
    }

    pub fn wait(&self) -> Option<&NaiveDateTime> {
        self.wait.as_ref()
    }

}

impl Serialize for Task {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), SerdeError>
        where S: Serializer
    {
        serializer.serialize_struct("Task", TaskVisitor {
            value: self,
            state: 0,
        })
    }

}

struct TaskVisitor<'a> {
    value: &'a Task,
    state: u8,
}

impl<'a> MapVisitor for TaskVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, SerdeError>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("status", &self.value.status))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("uuid", &self.value.uuid))))
            },
            2 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            3 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            4 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("annotation", &self.value.annotation))))
            },
            5 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("depends", &self.value.depends))))
            },
            6 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("due", &self.value.due))))
            },
            7 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("end", &self.value.end))))
            },
            8 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("imask", &self.value.imask))))
            },
            9 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("mask", &self.value.mask))))
            },
            10 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("modified", &self.value.modified))))
            },
            11 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("parent", &self.value.parent))))
            },
            12 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("priority", &self.value.priority))))
            },
            13 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("project", &self.value.project))))
            },
            14 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("recur", &self.value.recur))))
            },
            15 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("scheduled", &self.value.scheduled))))
            },
            16 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("start", &self.value.start))))
            },
            17 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("tags", &self.value.tags))))
            },
            18 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("until", &self.value.until))))
            },
            19 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("wait", &self.value.wait))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}
<|endoftext|>


<commit_before>//! BookmarkCollection module
//!
//! A BookmarkCollection is nothing more than a simple store entry. One can simply call functions
//! from the libimagentrylink::external::ExternalLinker trait on this to generate external links.
//!
//! The BookmarkCollection type offers helper functions to get all links or such things.
use std::ops::Deref;
use std::ops::DerefMut;

use regex::Regex;

use error::BookmarkErrorKind as BEK;
use error::MapErrInto;
use result::Result;
use module_path::ModuleEntryPath;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use libimagstore::store::FileLockEntry;
use libimagentrylink::external::ExternalLinker;
use libimagentrylink::internal::InternalLinker;
use libimagentrylink::internal::Link as StoreLink;
use libimagerror::into::IntoError;
use url::Url;

use link::Link;

pub struct BookmarkCollection<'a> {
    fle: FileLockEntry<'a>,
    store: &'a Store,
}

/// {Internal, External}Linker is implemented as Deref is implemented
impl<'a> Deref for BookmarkCollection<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.fle
    }

}

impl<'a> DerefMut for BookmarkCollection<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.fle
    }

}

impl<'a> BookmarkCollection<'a> {

    pub fn new(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
        let id = ModuleEntryPath::new(name).into_storeid();
        store.create(id)
            .map(|fle| {
                BookmarkCollection {
                    fle: fle,
                    store: store,
                }
            })
            .map_err_into(BEK::StoreReadError)
    }

    pub fn get(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
        let id = ModuleEntryPath::new(name).into_storeid();
        store.get(id)
            .map_err_into(BEK::StoreReadError)
            .and_then(|fle| {
                match fle {
                    None => Err(BEK::CollectionNotFound.into_error()),
                    Some(e) => Ok(BookmarkCollection {
                        fle: e,
                        store: store,
                    }),
                }
            })
    }

    pub fn delete(store: &Store, name: &str) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid()).map_err_into(BEK::StoreReadError)
    }

    pub fn links(&self) -> Result<Vec<Url>> {
        self.fle.get_external_links(&self.store).map_err_into(BEK::LinkError)
    }

    pub fn link_entries(&self) -> Result<Vec<StoreLink>> {
        use libimagentrylink::external::is_external_link_storeid;

        self.fle
            .get_internal_links()
            .map(|v| v.into_iter().filter(|id| is_external_link_storeid(id)).collect())
            .map_err_into(BEK::StoreReadError)
    }

    pub fn add_link(&mut self, l: Link) -> Result<()> {
        use link::IntoUrl;

        l.into_url()
            .and_then(|url| self.add_external_link(self.store, url).map_err_into(BEK::LinkingError))
            .map_err_into(BEK::LinkError)
    }

    pub fn get_links_matching(&self, r: Regex) -> Result<Vec<Link>> {
        self.get_external_links(self.store)
            .map_err_into(BEK::LinkError)
            .map(|v| {
                v.into_iter()
                    .map(Url::into_string)
                    .filter(|urlstr| r.is_match(&urlstr[..]))
                    .map(Link::from)
                    .collect()
            })
    }

    pub fn remove_link(&self, l: Link) -> Result<()> {
        unimplemented!()
    }

}

<commit_msg>Implement BookmarkCollection::remove_link()<commit_after>//! BookmarkCollection module
//!
//! A BookmarkCollection is nothing more than a simple store entry. One can simply call functions
//! from the libimagentrylink::external::ExternalLinker trait on this to generate external links.
//!
//! The BookmarkCollection type offers helper functions to get all links or such things.
use std::ops::Deref;
use std::ops::DerefMut;

use regex::Regex;

use error::BookmarkErrorKind as BEK;
use error::MapErrInto;
use result::Result;
use module_path::ModuleEntryPath;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use libimagstore::store::FileLockEntry;
use libimagentrylink::external::ExternalLinker;
use libimagentrylink::internal::InternalLinker;
use libimagentrylink::internal::Link as StoreLink;
use libimagerror::into::IntoError;
use url::Url;

use link::Link;

pub struct BookmarkCollection<'a> {
    fle: FileLockEntry<'a>,
    store: &'a Store,
}

/// {Internal, External}Linker is implemented as Deref is implemented
impl<'a> Deref for BookmarkCollection<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.fle
    }

}

impl<'a> DerefMut for BookmarkCollection<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.fle
    }

}

impl<'a> BookmarkCollection<'a> {

    pub fn new(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
        let id = ModuleEntryPath::new(name).into_storeid();
        store.create(id)
            .map(|fle| {
                BookmarkCollection {
                    fle: fle,
                    store: store,
                }
            })
            .map_err_into(BEK::StoreReadError)
    }

    pub fn get(store: &'a Store, name: &str) -> Result<BookmarkCollection<'a>> {
        let id = ModuleEntryPath::new(name).into_storeid();
        store.get(id)
            .map_err_into(BEK::StoreReadError)
            .and_then(|fle| {
                match fle {
                    None => Err(BEK::CollectionNotFound.into_error()),
                    Some(e) => Ok(BookmarkCollection {
                        fle: e,
                        store: store,
                    }),
                }
            })
    }

    pub fn delete(store: &Store, name: &str) -> Result<()> {
        store.delete(ModuleEntryPath::new(name).into_storeid()).map_err_into(BEK::StoreReadError)
    }

    pub fn links(&self) -> Result<Vec<Url>> {
        self.fle.get_external_links(&self.store).map_err_into(BEK::LinkError)
    }

    pub fn link_entries(&self) -> Result<Vec<StoreLink>> {
        use libimagentrylink::external::is_external_link_storeid;

        self.fle
            .get_internal_links()
            .map(|v| v.into_iter().filter(|id| is_external_link_storeid(id)).collect())
            .map_err_into(BEK::StoreReadError)
    }

    pub fn add_link(&mut self, l: Link) -> Result<()> {
        use link::IntoUrl;

        l.into_url()
            .and_then(|url| self.add_external_link(self.store, url).map_err_into(BEK::LinkingError))
            .map_err_into(BEK::LinkError)
    }

    pub fn get_links_matching(&self, r: Regex) -> Result<Vec<Link>> {
        self.get_external_links(self.store)
            .map_err_into(BEK::LinkError)
            .map(|v| {
                v.into_iter()
                    .map(Url::into_string)
                    .filter(|urlstr| r.is_match(&urlstr[..]))
                    .map(Link::from)
                    .collect()
            })
    }

    pub fn remove_link(&mut self, l: Link) -> Result<()> {
        use link::IntoUrl;

        l.into_url()
            .and_then(|url| {
                self.remove_external_link(self.store, url).map_err_into(BEK::LinkingError)
            })
            .map_err_into(BEK::LinkError)
    }

}

<|endoftext|>


<commit_before>use crate::prelude::*;

fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) {
    let puts = fx.module.declare_function("puts", Linkage::Import, &Signature {
        call_conv: CallConv::SystemV,
        params: vec![AbiParam::new(pointer_ty(fx.tcx))],
        returns: vec![],
    }).unwrap();
    let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func);

    let symbol_name = fx.tcx.symbol_name(fx.instance);
    let msg_bytes = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg).into_bytes().into_boxed_slice();
    let mut data_ctx = DataContext::new();
    data_ctx.define(msg_bytes);
    let msg_id = fx.module.declare_data(&(symbol_name.as_str().to_string() + msg), Linkage::Local, false, None).unwrap();

    // Ignore DuplicateDefinition error, as the data will be the same
    let _ = fx.module.define_data(msg_id, &data_ctx);

    let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
    let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
    fx.bcx.ins().call(puts, &[msg_ptr]);
}

/// Trap code: user0
pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
    codegen_print(fx, msg.as_ref());
    fx.bcx.ins().trap(TrapCode::User(0));
}

/// Trap code: user65535
pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
    codegen_print(fx, msg.as_ref());
    fx.bcx.ins().trap(TrapCode::User(!0));
}

/// Trap code: user65535
pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CValue<'tcx> {
    codegen_print(fx, msg.as_ref());
    let true_ = fx.bcx.ins().iconst(types::I32, 1);
    fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
    let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
    CValue::by_ref(zero, dest_layout)
}

/// Trap code: user65535
pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CPlace<'tcx> {
    codegen_print(fx, msg.as_ref());
    let true_ = fx.bcx.ins().iconst(types::I32, 1);
    fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
    let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
    CPlace::for_addr(zero, dest_layout)
}
<commit_msg>Add comments for trap::codegen_print gv and fn defs<commit_after>use crate::prelude::*;

fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) {
    let puts = fx.module.declare_function("puts", Linkage::Import, &Signature {
        call_conv: CallConv::SystemV,
        params: vec![AbiParam::new(pointer_ty(fx.tcx))],
        returns: vec![],
    }).unwrap();
    let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func);
    fx.add_entity_comment(puts, "puts");

    let symbol_name = fx.tcx.symbol_name(fx.instance);
    let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg);
    let mut data_ctx = DataContext::new();
    data_ctx.define(real_msg.as_bytes().to_vec().into_boxed_slice());
    let msg_id = fx.module.declare_data(&(symbol_name.as_str().to_string() + msg), Linkage::Local, false, None).unwrap();

    // Ignore DuplicateDefinition error, as the data will be the same
    let _ = fx.module.define_data(msg_id, &data_ctx);

    let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
    fx.add_entity_comment(local_msg_id, msg);
    let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
    fx.bcx.ins().call(puts, &[msg_ptr]);
}

/// Trap code: user0
pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
    codegen_print(fx, msg.as_ref());
    fx.bcx.ins().trap(TrapCode::User(0));
}

/// Trap code: user65535
pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
    codegen_print(fx, msg.as_ref());
    fx.bcx.ins().trap(TrapCode::User(!0));
}

/// Trap code: user65535
pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CValue<'tcx> {
    codegen_print(fx, msg.as_ref());
    let true_ = fx.bcx.ins().iconst(types::I32, 1);
    fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
    let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
    CValue::by_ref(zero, dest_layout)
}

/// Trap code: user65535
pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CPlace<'tcx> {
    codegen_print(fx, msg.as_ref());
    let true_ = fx.bcx.ins().iconst(types::I32, 1);
    fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
    let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
    CPlace::for_addr(zero, dest_layout)
}
<|endoftext|>