<commit_before>//! A collection of serialization and deserialization functions
//! that use the `serde` crate for the serializable and deserializable
//! implementation.

use std::io::{self, Write, Read};
use std::{error, fmt, result};
use ::{CountSize, SizeLimit};
use byteorder::{ByteOrder};

pub use super::de::{
    Deserializer,
};

pub use super::ser::{
    Serializer,
};

use super::ser::SizeChecker;

use serde_crate as serde;

/// The result of a serialization or deserialization operation.
pub type Result<T> = result::Result<T, Error>;

/// An error that can be produced during (de)serializing.
///
/// If decoding from a Buffer, assume that the buffer has been left
/// in an invalid state.
pub type Error = Box<ErrorKind>;

/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
    /// If the error stems from the reader/writer that is being used
    /// during (de)serialization, that error will be stored and returned here.
    Io(io::Error),
    /// If the bytes in the reader are not decodable because of an invalid
    /// encoding, this error will be returned.  This error is only possible
    /// if a stream is corrupted.  A stream produced from `encode` or `encode_into`
    /// should **never** produce an InvalidEncoding error.
    InvalidEncoding {
        #[allow(missing_docs)]
        desc: &'static str,
        #[allow(missing_docs)]
        detail: Option<String>
    },
    /// If (de)serializing a message takes more than the provided size limit, this
    /// error is returned.
    SizeLimit,
    /// Bincode can not encode sequences of unknown length (like iterators).
    SequenceMustHaveLength,
    /// A custom error message from Serde.
    Custom(String)
}

impl error::Error for ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref err) => error::Error::description(err),
            ErrorKind::InvalidEncoding{desc, ..} => desc,
            ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
            ErrorKind::SizeLimit => "the size limit for decoding has been reached",
            ErrorKind::Custom(ref msg) => msg,

        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ErrorKind::Io(ref err) => Some(err),
            ErrorKind::InvalidEncoding{..} => None,
            ErrorKind::SequenceMustHaveLength => None,
            ErrorKind::SizeLimit => None,
            ErrorKind::Custom(_) => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) =>
                write!(fmt, "Io: {}", ioerr),
            ErrorKind::InvalidEncoding{desc, detail: None}=>
                write!(fmt, "InvalidEncoding: {}", desc),
            ErrorKind::InvalidEncoding{desc, detail: Some(ref detail)}=>
                write!(fmt, "InvalidEncoding: {} ({})", desc, detail),
            ErrorKind::SequenceMustHaveLength =>
                write!(fmt, "Bincode can only encode sequences and maps that have a knowable size ahead of time."),
            ErrorKind::SizeLimit =>
                write!(fmt, "SizeLimit"),
            ErrorKind::Custom(ref s) =>
                s.fmt(fmt),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: fmt::Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}

impl serde::ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ErrorKind::Custom(msg.to_string()).into()
    }
}

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `Error` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W: ?Sized, T: ?Sized, S, E>(writer: &mut W, value: &T, size_limit: S) -> Result<()>
    where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder
{
    if let Some(limit) = size_limit.limit() {
        try!(serialized_size_bounded(value, limit).ok_or(ErrorKind::SizeLimit));
    }

    let mut serializer = Serializer::<_, E>::new(writer);
    serde::Serialize::serialize(value, &mut serializer)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T: ?Sized, S, E>(value: &T, size_limit: S) -> Result<Vec<u8>>
    where T: serde::Serialize, S: SizeLimit, E: ByteOrder
{
    let mut writer = match size_limit.limit() {
        Some(size_limit) => {
            let actual_size = try!(serialized_size_bounded(value, size_limit).ok_or(ErrorKind::SizeLimit));
            Vec::with_capacity(actual_size as usize)
        }
        None => {
            let size = serialized_size(value) as usize;
            Vec::with_capacity(size)
        }
    };

    try!(serialize_into::<_, _, _, E>(&mut writer, value, super::Infinite));
    Ok(writer)
}

impl SizeLimit for CountSize {
    fn add(&mut self, c: u64) -> Result<()> {
        self.total += c;
        if let Some(limit) = self.limit {
            if self.total > limit {
                return Err(Box::new(ErrorKind::SizeLimit))
            }
        }
        Ok(())
    }

    fn limit(&self) -> Option<u64> {
        unreachable!();
    }
}

/// Returns the size that an object would be if serialized using bincode.
///
/// This is used internally as part of the check for encode_into, but it can
/// be useful for preallocating buffers if thats your style.
pub fn serialized_size<T: ?Sized>(value: &T) -> u64
    where T: serde::Serialize
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize { total: 0, limit: None }
    };

    value.serialize(&mut size_counter).ok();
    size_counter.size_limit.total
}

/// Given a maximum size limit, check how large an object would be if it
/// were to be serialized.
///
/// If it can be serialized in `max` or fewer bytes, that number will be returned
/// inside `Some`.  If it goes over bounds, then None is returned.
pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
    where T: serde::Serialize
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize { total: 0, limit: Some(max) }
    };

    match value.serialize(&mut size_counter) {
        Ok(_) => Some(size_counter.size_limit.total),
        Err(_) => None,
    }
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `Error`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R: ?Sized, T, S, E>(reader: &mut R, size_limit: S) -> Result<T>
    where R: Read, T: serde::de::DeserializeOwned, S: SizeLimit, E: ByteOrder
{
    let reader = ::de::read::IoReader::new(reader);
    let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit);
    serde::Deserialize::deserialize(&mut deserializer)
}

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<'a, T, E: ByteOrder>(bytes: &'a [u8]) -> Result<T>
    where T: serde::de::Deserialize<'a>,
{
    let reader = ::de::read::SliceReader::new(bytes);
    let mut deserializer = Deserializer::<_, _, E>::new(reader, super::Infinite);
    serde::Deserialize::deserialize(&mut deserializer)
}
<commit_msg>take reader and writer by value (#200)<commit_after>//! A collection of serialization and deserialization functions
//! that use the `serde` crate for the serializable and deserializable
//! implementation.

use std::io::{self, Write, Read};
use std::{error, fmt, result};
use ::{CountSize, SizeLimit};
use byteorder::{ByteOrder};

pub use super::de::{
    Deserializer,
};

pub use super::ser::{
    Serializer,
};

use super::ser::SizeChecker;

use serde_crate as serde;

/// The result of a serialization or deserialization operation.
pub type Result<T> = result::Result<T, Error>;

/// An error that can be produced during (de)serializing.
///
/// If decoding from a Buffer, assume that the buffer has been left
/// in an invalid state.
pub type Error = Box<ErrorKind>;

/// The kind of error that can be produced during a serialization or deserialization.
#[derive(Debug)]
pub enum ErrorKind {
    /// If the error stems from the reader/writer that is being used
    /// during (de)serialization, that error will be stored and returned here.
    Io(io::Error),
    /// If the bytes in the reader are not decodable because of an invalid
    /// encoding, this error will be returned.  This error is only possible
    /// if a stream is corrupted.  A stream produced from `encode` or `encode_into`
    /// should **never** produce an InvalidEncoding error.
    InvalidEncoding {
        #[allow(missing_docs)]
        desc: &'static str,
        #[allow(missing_docs)]
        detail: Option<String>
    },
    /// If (de)serializing a message takes more than the provided size limit, this
    /// error is returned.
    SizeLimit,
    /// Bincode can not encode sequences of unknown length (like iterators).
    SequenceMustHaveLength,
    /// A custom error message from Serde.
    Custom(String)
}

impl error::Error for ErrorKind {
    fn description(&self) -> &str {
        match *self {
            ErrorKind::Io(ref err) => error::Error::description(err),
            ErrorKind::InvalidEncoding{desc, ..} => desc,
            ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
            ErrorKind::SizeLimit => "the size limit for decoding has been reached",
            ErrorKind::Custom(ref msg) => msg,

        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ErrorKind::Io(ref err) => Some(err),
            ErrorKind::InvalidEncoding{..} => None,
            ErrorKind::SequenceMustHaveLength => None,
            ErrorKind::SizeLimit => None,
            ErrorKind::Custom(_) => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) =>
                write!(fmt, "Io: {}", ioerr),
            ErrorKind::InvalidEncoding{desc, detail: None}=>
                write!(fmt, "InvalidEncoding: {}", desc),
            ErrorKind::InvalidEncoding{desc, detail: Some(ref detail)}=>
                write!(fmt, "InvalidEncoding: {} ({})", desc, detail),
            ErrorKind::SequenceMustHaveLength =>
                write!(fmt, "Bincode can only encode sequences and maps that have a knowable size ahead of time."),
            ErrorKind::SizeLimit =>
                write!(fmt, "SizeLimit"),
            ErrorKind::Custom(ref s) =>
                s.fmt(fmt),
        }
    }
}

impl serde::de::Error for Error {
    fn custom<T: fmt::Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}

impl serde::ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ErrorKind::Custom(msg.to_string()).into()
    }
}

/// Serializes an object directly into a `Writer`.
///
/// If the serialization would take more bytes than allowed by `size_limit`, an error
/// is returned and *no bytes* will be written into the `Writer`.
///
/// If this returns an `Error` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// serializing.
pub fn serialize_into<W, T: ?Sized, S, E>(writer: W, value: &T, size_limit: S) -> Result<()>
    where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder
{
    if let Some(limit) = size_limit.limit() {
        try!(serialized_size_bounded(value, limit).ok_or(ErrorKind::SizeLimit));
    }

    let mut serializer = Serializer::<_, E>::new(writer);
    serde::Serialize::serialize(value, &mut serializer)
}

/// Serializes a serializable object into a `Vec` of bytes.
///
/// If the serialization would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn serialize<T: ?Sized, S, E>(value: &T, size_limit: S) -> Result<Vec<u8>>
    where T: serde::Serialize, S: SizeLimit, E: ByteOrder
{
    let mut writer = match size_limit.limit() {
        Some(size_limit) => {
            let actual_size = try!(serialized_size_bounded(value, size_limit).ok_or(ErrorKind::SizeLimit));
            Vec::with_capacity(actual_size as usize)
        }
        None => {
            let size = serialized_size(value) as usize;
            Vec::with_capacity(size)
        }
    };

    try!(serialize_into::<_, _, _, E>(&mut writer, value, super::Infinite));
    Ok(writer)
}

impl SizeLimit for CountSize {
    fn add(&mut self, c: u64) -> Result<()> {
        self.total += c;
        if let Some(limit) = self.limit {
            if self.total > limit {
                return Err(Box::new(ErrorKind::SizeLimit))
            }
        }
        Ok(())
    }

    fn limit(&self) -> Option<u64> {
        unreachable!();
    }
}

/// Returns the size that an object would be if serialized using bincode.
///
/// This is used internally as part of the check for encode_into, but it can
/// be useful for preallocating buffers if thats your style.
pub fn serialized_size<T: ?Sized>(value: &T) -> u64
    where T: serde::Serialize
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize { total: 0, limit: None }
    };

    value.serialize(&mut size_counter).ok();
    size_counter.size_limit.total
}

/// Given a maximum size limit, check how large an object would be if it
/// were to be serialized.
///
/// If it can be serialized in `max` or fewer bytes, that number will be returned
/// inside `Some`.  If it goes over bounds, then None is returned.
pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
    where T: serde::Serialize
{
    let mut size_counter = SizeChecker {
        size_limit: CountSize { total: 0, limit: Some(max) }
    };

    match value.serialize(&mut size_counter) {
        Ok(_) => Some(size_counter.size_limit.total),
        Err(_) => None,
    }
}

/// Deserializes an object directly from a `Buffer`ed Reader.
///
/// If the provided `SizeLimit` is reached, the deserialization will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with
/// a neverending stream of values that runs your server out of memory.
///
/// If this returns an `Error`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn deserialize_from<R, T, S, E>(reader: R, size_limit: S) -> Result<T>
    where R: Read, T: serde::de::DeserializeOwned, S: SizeLimit, E: ByteOrder
{
    let reader = ::de::read::IoReader::new(reader);
    let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit);
    serde::Deserialize::deserialize(&mut deserializer)
}

/// Deserializes a slice of bytes into an object.
///
/// This method does not have a size-limit because if you already have the bytes
/// in memory, then you don't gain anything by having a limiter.
pub fn deserialize<'a, T, E: ByteOrder>(bytes: &'a [u8]) -> Result<T>
    where T: serde::de::Deserialize<'a>,
{
    let reader = ::de::read::SliceReader::new(bytes);
    let mut deserializer = Deserializer::<_, _, E>::new(reader, super::Infinite);
    serde::Deserialize::deserialize(&mut deserializer)
}
<|endoftext|>


<commit_before>//! Lambda encoding for byte strings

use lambda_calculus::term::*;
use lambda_calculus::booleans::{tru, fls};
use lambda_calculus::list::nil;
use std::char;

/// Decode lambda-encoded data as a `String`.
///
/// # Example
/// ```
/// use blc::binary_encoding::from_binary;
/// use blc::lambda_encoding::decode;
///
/// let k = from_binary(b"0000110");
///
/// assert!(k.is_ok());
/// assert_eq!(decode(k.unwrap()), "(λλ2)");
/// ```
pub fn decode(term: Term) -> String {
    if term == fls() {
        "".into()
    } else if term.is_list() && term.head_ref().unwrap().is_list() {
        let (head, tail) = term.uncons().unwrap(); // safe ensured by is_list
        let terms: Vec<Term> = head.into_iter().collect();
        let bits = terms
            .into_iter()
            .map(|t| (t
                .unabs()
                .and_then(|t| t.unabs())
                .and_then(|t| t.unvar())
                .unwrap() - 1) as u8
            ).collect::<Vec<u8>>();
        let byte = !bits.iter().fold(0, |acc, &b| acc * 2 + b);
        let chr = char::from(byte);
        chr.to_string() + &decode(tail)
    } else if term.head_ref() == Ok(&fls()) {
        "1".to_string() + &decode(term.tail().unwrap())
    } else if term.head_ref() == Ok(&tru()) {
        "0".to_string() + &decode(term.tail().unwrap())
    } else {
        format!("({})", term)
    }
}

fn encode_byte(b: u8) -> Term {
    match b {
        b'0' => tru(),
        b'1' => fls(),
        x    => encode(&format!("{:08b}", x).as_bytes())
    }
}

/// Encode bytes as a lambda `Term`.
///
/// # Example
/// ```
/// use blc::lambda_encoding::encode;
///
/// assert_eq!(&*format!("{}", encode(b"a")),
///     "λ1(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1)");
/// ```
pub fn encode(input: &[u8]) -> Term {
    input.iter().rev().fold(nil(), |acc, &b| acc.push(encode_byte(b)))
}

#[cfg(test)]
mod test {
    use super::*;
    use binary_encoding::from_binary;
    use std::str;

    #[test]
    fn encoding_lambda() {
        assert_eq!(&*format!("{}", encode(b"0")),     "λ1(λλ2)(λλ1)");
        assert_eq!(&*format!("{}", encode(b"1")),     "λ1(λλ1)(λλ1)");
        assert_eq!(&*format!("{}", encode(b"00")),    "λ1(λλ2)(λ1(λλ2)(λλ1))");
        assert_eq!(&*format!("{}", encode(b"01")),    "λ1(λλ2)(λ1(λλ1)(λλ1))");
        assert_eq!(&*format!("{}", encode(b"10")),    "λ1(λλ1)(λ1(λλ2)(λλ1))");
        assert_eq!(&*format!("{}", encode(b"11")),    "λ1(λλ1)(λ1(λλ1)(λλ1))");
        assert_eq!(&*format!("{}", encode(b"001")),   "λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))");
        assert_eq!(&*format!("{}", encode(b"100")),   "λ1(λλ1)(λ1(λλ2)(λ1(λλ2)(λλ1)))");
        assert_eq!(&*format!("{}", encode(b"a")),     "λ1(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)(λ1(λλ2)\
                                                       (λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1)");
        assert_eq!(&*format!("{}", encode(b"z0")),    "λ1(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ1)(λ1(λλ1)\
                                                       (λ1(λλ2)(λ1(λλ1)(λ1(λλ2)(λλ1)))))))))(λ1(λλ\
                                                       2)(λλ1))");
        assert_eq!(&*format!("{}", encode(b"\0(1)")), "λ1(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(\
                                                       λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λλ1)))))))))(λ1(λ1(\
                                                       λλ2)(λ1(λλ2)(λ1(λλ1)(λ1(λλ2)(λ1(λλ1)(λ1(λλ2\
                                                       )(λ1(λλ2)(λ1(λλ2)(λλ1)))))))))(λ1(λλ1)(λ1(λ\
                                                       1(λλ2)(λ1(λλ2)(λ1(λλ1)(λ1(λλ2)(λ1(λλ1)(λ1(λ\
                                                       λ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1))))");
    }

    #[test]
    fn decoding() {
        let k =     from_binary(b"0000110").unwrap();
        let s =     from_binary(b"00000001011110100111010").unwrap();
        let quine = from_binary(b"000101100100011010000000000001011\
                                  011110010111100111111011111011010").unwrap();

        assert_eq!(decode(k),     "(λλ2)");
        assert_eq!(decode(s),     "(λλλ31(21))");
        assert_eq!(decode(quine), "(λ1((λ11)(λλλλλ14(3(55)2)))1)");
    }

    #[test]
    fn decode_encode_lambda() {
        assert_eq!(decode(encode(b"herp derp")),             "herp derp");
        assert_eq!(decode(encode(b"0111010101011")),         "0111010101011");
        assert_eq!(decode(encode(b"01zeros110and1ones101")), "01zeros110and1ones101");
        assert_eq!(decode(encode(b"\0(1)")),                 "\0(1)");
    }
}
<commit_msg>fix encoding of 0 and 1 bytes<commit_after>//! Lambda encoding for byte strings

use lambda_calculus::term::*;
use lambda_calculus::booleans::{tru, fls};
use lambda_calculus::list::nil;
use std::char;

/// Decode lambda-encoded data as a `String`.
///
/// # Example
/// ```
/// use blc::binary_encoding::from_binary;
/// use blc::lambda_encoding::decode;
///
/// let k = from_binary(b"0000110");
///
/// assert!(k.is_ok());
/// assert_eq!(decode(k.unwrap()), "(λλ2)");
/// ```
pub fn decode(term: Term) -> String {
    if term == fls() {
        "".into()
    } else if term.is_list() && term.head_ref().unwrap().is_list() {
        let (head, tail) = term.uncons().unwrap(); // safe, ensured by is_list
        let terms: Vec<Term> = head.into_iter().collect();
        let bits = terms
            .into_iter()
            .map(|t| (t
                .unabs()
                .and_then(|t| t.unabs())
                .and_then(|t| t.unvar())
                .unwrap() - 1) as u8
            ).collect::<Vec<u8>>();
        let byte = !bits.iter().fold(0, |acc, &b| acc * 2 + b);
        let chr = char::from(byte);
        chr.to_string() + &decode(tail)
    } else if term.head_ref() == Ok(&fls()) {
        "1".to_string() + &decode(term.tail().unwrap())
    } else if term.head_ref() == Ok(&tru()) {
        "0".to_string() + &decode(term.tail().unwrap())
    } else {
        format!("({})", term)
    }
}

fn encode_byte(byte: u8) -> Term {
    let bitstr = format!("{:08b}", byte);
    let bits = bitstr.as_bytes();
    Term::from(bits.into_iter().map(|&bit| encode_bit(bit)).collect::<Vec<Term>>())
}

fn encode_bit(bit: u8) -> Term {
    match bit {
        b'0' => tru(),
        b'1' => fls(),
        _ => unreachable!()
    }
}

/// Encode bytes as a lambda `Term`.
///
/// # Example
/// ```
/// use blc::lambda_encoding::encode;
///
/// assert_eq!(&*format!("{}", encode(b"a")),
///     "λ1(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1)");
/// ```
pub fn encode(input: &[u8]) -> Term {
    input.iter().rev().fold(nil(), |acc, &b| acc.push(encode_byte(b)))
}

#[cfg(test)]
mod test {
    use super::*;
    use binary_encoding::from_binary;
    use std::str;

    #[test]
    fn encoding_lambda() {
        assert_eq!(&*format!("{}", encode(b"0")),     "λ1(λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)\
                                                       (λ1(λλ2)(λ1(λλ2)(λ1(λλ2)(λλ1)))))))))(λλ1)");
        assert_eq!(&*format!("{}", encode(b"1")),     "λ1(λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)\
                                                       (λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1)");
        assert_eq!(&*format!("{}", encode(b"a")),     "λ1(λ1(λλ2)(λ1(λλ1)(λ1(λλ1)(λ1(λλ2)(λ1(λλ2)\
                                                       (λ1(λλ2)(λ1(λλ2)(λ1(λλ1)(λλ1)))))))))(λλ1)");
    }

    #[test]
    fn decoding() {
        let k =     from_binary(b"0000110").unwrap();
        let s =     from_binary(b"00000001011110100111010").unwrap();
        let quine = from_binary(b"000101100100011010000000000001011\
                                  011110010111100111111011111011010").unwrap();

        assert_eq!(decode(k),     "(λλ2)");
        assert_eq!(decode(s),     "(λλλ31(21))");
        assert_eq!(decode(quine), "(λ1((λ11)(λλλλλ14(3(55)2)))1)");
    }

    #[test]
    fn decode_encode_lambda() {
        assert_eq!(decode(encode(b"herp derp")),             "herp derp");
        assert_eq!(decode(encode(b"0111010101011")),         "0111010101011");
        assert_eq!(decode(encode(b"01zeros110and1ones101")), "01zeros110and1ones101");
        assert_eq!(decode(encode(b"\0(1)")),                 "\0(1)");
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/move-pieces-to-obtain-a-string/
pub fn can_change(start: String, target: String) -> bool {
    fn swap(v: &mut Vec<char>, i: usize, j: usize) {
        let tmp = v[i];
        v[i] = v[j];
        v[j] = tmp;
    }

    let mut start: Vec<char> = start.chars().into_iter().collect();
    let target: Vec<char> = target.chars().into_iter().collect();
    let mut i = 0;
    let mut j = 0;
    while i < target.len() {
        if start[i] != target[i] {
            if target[i] == 'L' {
                if start[i] != '_' {
                    return false;
                }
                while j < start.len() && start[j] == '_' {
                    j += 1;
                }
                if start[j] != 'L' {
                    return false;
                }
                swap(&mut start, i, j);
            } else if target[i] == 'R' {
                return false;
            } else {
                if start[i] != 'R' {
                    return false;
                }
            }
        }
        println!("{:?}", start);
        i += 1;
    }
    true
}

fn main() {
    println!(
        "{}",
        can_change(String::from("_L__R__R_"), String::from("L______RR"))
    ); // true
    println!("{}", can_change(String::from("R_L_"), String::from("__LR"))); // true
    println!("{}", can_change(String::from("_R"), String::from("R_"))); // true
    println!("{}", can_change(String::from("LLLR"), String::from("LRRR"))); // false
    println!(
        "{}",
        can_change(String::from("__L_R_L_R__"), String::from("L___RL_R___"))
    ); // false
    println!(
        "{}",
        can_change(String::from("__L_RL__R__"), String::from("L___RL_R___"))
    ); // true
}
<commit_msg>Solve problem 2337<commit_after>// https://leetcode.com/problems/move-pieces-to-obtain-a-string/
pub fn can_change(start: String, target: String) -> bool {
    fn swap(v: &mut Vec<char>, i: usize, j: usize) {
        let tmp = v[i];
        v[i] = v[j];
        v[j] = tmp;
    }

    let mut start: Vec<char> = start.chars().into_iter().collect();
    let target: Vec<char> = target.chars().into_iter().collect();
    let mut i = 0;
    let mut j = 0;
    while i < target.len() {
        if start[i] != target[i] {
            if target[i] == 'L' {
                if start[i] != '_' {
                    return false;
                }
                while j < start.len() && start[j] == '_' {
                    j += 1;
                }
                if j == start.len() || start[j] != 'L' {
                    return false;
                }
                swap(&mut start, i, j);
            } else if target[i] == 'R' {
                return false;
            } else {
                if start[i] != 'R' {
                    return false;
                }
                while j < start.len() && start[j] == 'R' {
                    j += 1;
                }
                if j == start.len() || start[j] != '_' {
                    return false;
                }
                swap(&mut start, i, j);
            }
        }
        i += 1;
        j = j.max(i);
    }
    true
}

fn main() {
    println!(
        "{}",
        can_change(String::from("_L__R__R_"), String::from("L______RR"))
    ); // true
    println!("{}", can_change(String::from("R_L_"), String::from("__LR"))); // false
    println!("{}", can_change(String::from("_R"), String::from("R_"))); // false
    println!("{}", can_change(String::from("LLLR"), String::from("LRRR"))); // false
    println!(
        "{}",
        can_change(String::from("__L_R_L_R__"), String::from("L___RL_R___"))
    ); // false
    println!(
        "{}",
        can_change(String::from("__L_RL__R__"), String::from("L___RL_R___"))
    ); // false
    println!("{}", can_change(String::from("_"), String::from("L"))); // false
}
<|endoftext|>


<commit_before>use server::Server;
use definitions::registration::CucumberRegistrar;
use runner::WorldRunner;
use itertools::Itertools;

use std::process::{self, Command, Stdio};
use std::thread;
use std::time::Duration;
use std::env;

/// Starts a Cucumber server and the Ruby client
///
/// # Example
/// ```no_run
/// #[macro_use]
/// extern crate cucumber;
///
///
/// mod button_steps {
///   use cucumber::CucumberRegistrar;
///   pub fn register_steps(c: &mut CucumberRegistrar<u32>) {
///   }
/// }
///
/// mod widget_steps {
///   use cucumber::CucumberRegistrar;
///   pub fn register_steps(c: &mut CucumberRegistrar<u32>) {
///   }
/// }
///
/// fn main() {
///   let world: u32 = 0;
///
///   cucumber::start(
///     world,
///     &[
///       &button_steps::register_steps,
///       &widget_steps::register_steps,
///     ]
///   );
/// }
/// ```
///
pub fn start<W: Send + 'static>(world: W, register_fns: &[&Fn(&mut CucumberRegistrar<W>)]) {
  start_with_addr("0.0.0.0:7878", world, register_fns)
}

/// Start a Cucumber server, with an ip and port, see the [`start()
/// method`][start].
/// [start]: fn.start.html
#[allow(unused_variables)]
pub fn start_with_addr<W: Send + 'static>(addr: &'static str,
                                          world: W,
                                          register_fns: &[&Fn(&mut CucumberRegistrar<W>)]) {
  let mut runner = WorldRunner::new(world);

  register_fns.iter().foreach(|fun| fun(&mut runner));

  let server = Server::new(runner);
  // NOTE: Unused stop_rx needs to be held, or it will drop and close the server
  let (handle, stop_rx) = server.start(Some(addr));

  let status = ruby_command()
    .spawn()
    .unwrap_or_else(|e| panic!("failed to execute process: {}", e))
    .wait()
    .unwrap();

  // NOTE: Join disabled because of edge case when having zero tests
  //   In that case, ruby cuke will not make tcp connection. It is
  //   so far impossible to break from tcp::accept, so we must kill
  // TODO: Investigate MIO to resolve this
  // handle.join().unwrap();
  // NOTE: Sleep is an interim solution, to allow the thread time to clean up in
  // the typical case
  thread::sleep(Duration::new(2, 0));

  process::exit(status.code().unwrap());
}

/// Build a command to execute the Ruby Cucumber Server
pub fn ruby_command() -> Command {
  let mut command = Command::new("cucumber");
  command.stdout(Stdio::inherit());
  command.stderr(Stdio::inherit());
  // Skip the name of the executable, but pass the rest
  env::args().skip(1).foreach(|a| {
    command.arg(a);
  });
  command
}
<commit_msg>Added check for operating system (#34)<commit_after>use server::Server;
use definitions::registration::CucumberRegistrar;
use runner::WorldRunner;
use itertools::Itertools;

use std::process::{self, Command, Stdio};
use std::thread;
use std::time::Duration;
use std::env;

/// Starts a Cucumber server and the Ruby client
///
/// # Example
/// ```no_run
/// #[macro_use]
/// extern crate cucumber;
///
///
/// mod button_steps {
///   use cucumber::CucumberRegistrar;
///   pub fn register_steps(c: &mut CucumberRegistrar<u32>) {
///   }
/// }
///
/// mod widget_steps {
///   use cucumber::CucumberRegistrar;
///   pub fn register_steps(c: &mut CucumberRegistrar<u32>) {
///   }
/// }
///
/// fn main() {
///   let world: u32 = 0;
///
///   cucumber::start(
///     world,
///     &[
///       &button_steps::register_steps,
///       &widget_steps::register_steps,
///     ]
///   );
/// }
/// ```
///
pub fn start<W: Send + 'static>(world: W, register_fns: &[&Fn(&mut CucumberRegistrar<W>)]) {
  start_with_addr("0.0.0.0:7878", world, register_fns)
}

/// Start a Cucumber server, with an ip and port, see the [`start()
/// method`][start].
/// [start]: fn.start.html
#[allow(unused_variables)]
pub fn start_with_addr<W: Send + 'static>(addr: &'static str,
                                          world: W,
                                          register_fns: &[&Fn(&mut CucumberRegistrar<W>)]) {
  let mut runner = WorldRunner::new(world);

  register_fns.iter().foreach(|fun| fun(&mut runner));

  let server = Server::new(runner);
  // NOTE: Unused stop_rx needs to be held, or it will drop and close the server
  let (handle, stop_rx) = server.start(Some(addr));

  let status = ruby_command()
    .spawn()
    .unwrap_or_else(|e| panic!("failed to execute process: {}", e))
    .wait()
    .unwrap();

  // NOTE: Join disabled because of edge case when having zero tests
  //   In that case, ruby cuke will not make tcp connection. It is
  //   so far impossible to break from tcp::accept, so we must kill
  // TODO: Investigate MIO to resolve this
  // handle.join().unwrap();
  // NOTE: Sleep is an interim solution, to allow the thread time to clean up in
  // the typical case
  thread::sleep(Duration::new(2, 0));

  process::exit(status.code().unwrap());
}

/// Build a command to execute the Ruby Cucumber Server
pub fn ruby_command() -> Command {
  let cucumber_bin = if cfg!(target_os = "windows") {
    "cucumber.bat"
  } else {
    "cucumber"
  };

  let mut command = Command::new(cucumber_bin);
  command.stdout(Stdio::inherit());
  command.stderr(Stdio::inherit());
  // Skip the name of the executable, but pass the rest
  env::args().skip(1).foreach(|a| {
    command.arg(a);
  });
  command
}
<|endoftext|>


<commit_before>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};

pub type Node = Box<Containable>;

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<Rc<Node>> {
        let mut container = self.get_parent().upgrade();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == type_ {
                    return Some(parent);
                }
                container = parent.get_parent().upgrade();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Rc<Node>;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Weak<Node>,
    children: Vec<Rc<Node>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
        /*
        match self.type_ {
            ContainerType::Root => {
                // such hack
                unsafe {
                    // very unsafe
                    use std::mem;
                    let _dummy: Node = mem::uninitialized();
                    // much dummy
                    let _rc_dummy = Rc::new(_dummy);
                    Rc::downgrade(&_rc_dummy)}
            },
            _ => self.parent.clone(),
        }*/
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.iter().map(|child| Rc::downgrade(&child)).collect())
        }
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        for child in self.get_children().expect("No children") {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container().ok();
                    drop(child);
                }
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<Box<WlcView>>,
    parent: Weak<Node>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        None
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(ref handle) = self.handle {
            handle.close();
        }
        drop(self);
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}

impl Viewable for View {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool {
        if let Some(ref handle) = self.handle {
            match handle.get_state() {
                VIEW_MAXIMIZED => true,
                _ => false,
            }
        } else {
            false
        }
    }

    /// Figures out if the view is focused
    fn is_active(&self) -> bool {
        self.is_focused
    }

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool {
        unimplemented!();
    }

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool {
        unimplemented!();
    }

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Rc<Node> {
        let mut workspace = self.get_parent().upgrade();
        loop {
            if let Some(parent) = workspace {
                if parent.get_type() == ContainerType::Workspace {
                    return parent
                }
                workspace = parent.get_parent().upgrade();
            }
        }
    }
}
<commit_msg>Moved is_parent_of and is_child_of to Containable.<commit_after>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};

pub type Node = Box<Containable>;

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Returns true if this container is a parent of the child
    fn is_parent_of(&self, child: Rc<Node>) -> bool {
        unimplemented!();
    }

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of(&self, parent: Rc<Node>) -> bool {
        unimplemented!();
    }

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<Rc<Node>> {
        let mut container = self.get_parent().upgrade();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == type_ {
                    return Some(parent);
                }
                container = parent.get_parent().upgrade();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Rc<Node>;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Weak<Node>,
    children: Vec<Rc<Node>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
        /*
        match self.type_ {
            ContainerType::Root => {
                // such hack
                unsafe {
                    // very unsafe
                    use std::mem;
                    let _dummy: Node = mem::uninitialized();
                    // much dummy
                    let _rc_dummy = Rc::new(_dummy);
                    Rc::downgrade(&_rc_dummy)}
            },
            _ => self.parent.clone(),
        }*/
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.iter().map(|child| Rc::downgrade(&child)).collect())
        }
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        for child in self.get_children().expect("No children") {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container().ok();
                    drop(child);
                }
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<Box<WlcView>>,
    parent: Weak<Node>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Weak<Node> {
        self.parent.clone()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Weak<Node>>> {
        None
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(ref handle) = self.handle {
            handle.close();
        }
        drop(self);
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}

impl Viewable for View {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool {
        if let Some(ref handle) = self.handle {
            match handle.get_state() {
                VIEW_MAXIMIZED => true,
                _ => false,
            }
        } else {
            false
        }
    }

    /// Figures out if the view is focused
    fn is_active(&self) -> bool {
        self.is_focused
    }

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Rc<Node> {
        let mut workspace = self.get_parent().upgrade();
        loop {
            if let Some(parent) = workspace {
                if parent.get_type() == ContainerType::Workspace {
                    return parent
                }
                workspace = parent.get_parent().upgrade();
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(io)]
use std::io;
use std::io::prelude::*;
use std::path::{Path, Prefix};
use std::fs::{File};
use std::error::Error;

use board_logic::{Board, BoardMarker, Stone, Point};

/// Describes the file
pub enum FileType{
    /// Generic Renju _.pos_ file.
    ///
    /// These files seems to always assume a field of size 15*15
    /// # Layout in binary
    /// * 0: N moves
    /// * 1: Black move #1
    /// * 2: White move #2
    /// * N: Last move
    ///
    Pos,
    /// RenLib, _.lib_ file.
    ///
    /// This is not supported yet as I have not fully reversed the protocol yet.
    ///
    /// # About
    ///
    /// _.lib_ files are most used for it's excellent support for saving multiple games of one play. This enables
    /// a way to do analysis.
    ///
    /// #### Example
    /// The move sequence is H8 I9 G7 H7 D11 etc. We want to analyse and document what would
    /// have happened if we played H6 instead of H7 on move #4. So we would go back to move #3 and continue from there. Now,
    /// when walking through the game from the beginning, we will see that there are 2 choices
    /// highlighted on move #4, we have created a _sub game_.
    /// Clicking on either will continue this pattern of finding sub-games like before, repeating itself if needed. If
    /// you don't choose any of those choices it makes a new sub-game.
    ///
    /// This is why RenLib's _.lib_ format is so praised in the renju community.
    ///
    /// ...* _.lib_ files come in two variations, either as Libraries or as Positions. I have yet
    /// to identify what the signature is for both.
    ///
    /// ## Known:
    /// * Libraries seem to be saved with the signature 0x40 ("@") some where at the end.
    /// Positions seems to be stored as two bytes. With 0x78 being the middle.
    /// With what I know so far, after 10 "0xFF", the first move is stored. Then if the next byte is "0x00",
    /// continue and repeat. How sub-games are stored will soon be cracked.
    ///
    ///     This is the layout:
    ///
    ///          0: . . . . . . . . . . . . . . .
    ///          1: . . . . . . . . . . . . . . .
    ///          2: . . . . . . . . . . . . . . .
    ///          3: . . . . . . . . . . . . . . .
    ///          4: . . . O . . . . . . . . . . .
    ///          5: . . . . . . . . . . . . . . .
    ///          6: . . . . . . . . . . . . . . .
    ///          7: . . . . . . . X . . . . . . .
    ///          8: . . . . . . . . . . . . . . .
    ///          9: . . . . . . . . . . . . . . .
    ///          A: . . . . . . . . . . . . . . .
    ///          B: . . . . . . . . . . . . . . .
    ///          C: . . . . . . . . . . . . . . .
    ///          D: . . . . . . . . . . . . . . .
    ///          E: . . . . . . . . . . . . . . .
    ///             1 2 3 4 5 6 7 8 9 A B C D E F
    ///
    /// The _O_ is on `0x44`, the _X_ is on `0x78` (the middle)
    ///
    /// *    Libraries usually have "@" at the end, this
    Lib,
}

impl FileType{
    fn new(path: &Path) -> Option<FileType> {
        match path.extension() {
            Some(pos) if (pos == "pos") => Some(FileType::Pos),
            Some(lib) if (lib == "lib") => Some(FileType::Lib),
            Some(_) => None,
            None => None,
        }
    }
}
pub fn open_file_as_board(path: &Path) -> Option<Board> {
    let display = path.display();
    let filetype = FileType::new(path);
    let mut file = match File::open(&path){
        // Should probably return a none. Or change from Option to Result
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    match filetype {
        Some(FileType::Pos) => {
            let mut board = Board::new(15);
            for (index, pos) in file.bytes().skip(1).enumerate() { // First value should always be the number of moves.
                board.set_point(Point::from_1d(pos.ok().unwrap() as u32, 15), if index % 2 == 0 {Stone::Black} else {Stone::White});
            }
            return Some(board);
        },
        Some(FileType::Lib) => {
            unimplemented!();
        },
        _ => unimplemented!(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;
    use board_logic as bl;

    #[test]
    fn open_pos_file(){
        let file = Path::new("examplefiles/example.pos");
        let mut board = open_file_as_board(file).unwrap();
        println!("\n{}", board.board);
    }
}
<commit_msg>Advanced progress on .lib files.<commit_after>#![feature(io)]
use std::io;
use std::io::prelude::*;
use std::path::{Path, Prefix};
use std::fs::{File};
use std::error::Error;

use board_logic::{Board, BoardMarker, Stone, Point};

/// Describes the file
pub enum FileType{
    /// Generic Renju _.pos_ file.
    ///
    /// These files seems to always assume a field of size 15*15
    /// # Layout in binary
    /// * 0: N moves
    /// * 1: Black move #1
    /// * 2: White move #2
    /// * N: Last move
    ///
    Pos,
    /// RenLib, _.lib_ file.
    ///
    /// This is not supported yet as I have not fully reversed the protocol yet.
    ///
    /// # About
    ///
    /// _.lib_ files are most used for it's excellent support for saving multiple games of one play. This enables
    /// a way to do analysis.
    ///
    /// #### Example
    /// The move sequence is H8 I9 G7 H7 D11 etc. We want to analyse and document what would
    /// have happened if we played H6 instead of H7 on move #4. So we would go back to move #3 and continue from there. Now,
    /// when walking through the game from the beginning, we will see that there are 2 choices
    /// highlighted on move #4, we have created a _sub game_.
    /// Clicking on either will continue this pattern of finding sub-games like before, repeating itself if needed. If
    /// you don't choose any of those choices it makes a new sub-game.
    ///
    /// This is why RenLib's _.lib_ format is so praised in the renju community.
    ///
    /// ...* _.lib_ files come in two variations, either as Libraries or as Positions. I have yet
    /// to identify what the signature is for both.
    ///
    /// ## Known:
    /// * Libraries seem to be saved with the signature 0x40 ("@") some where at the end.
    /// Positions seems to be stored as two bytes. This means that 0x78 is the middle.
    /// With what I know so far, after 10 "0xFF", the first move is stored. Then if the next byte is "0x00",
    /// continue and repeat. How sub-games are stored will soon be cracked.
    ///
    ///     This is the layout for X, Y:
    ///
    ///          0: . . . . . . . . . . . . . . .
    ///          1: . . . . . . . . . . . . . . .
    ///          2: . . . . . . . . . . . . . . .
    ///          3: . . . . . . . . . . . . . . .
    ///          4: . . . O . . . . . . . . . . .
    ///          5: . . . . . . . . . . . . . . .
    ///          6: . . . . . . . . . . . . . . .
    ///          7: . . . . . . . X . . . . . . .
    ///          8: . . . . . . . . . . . . . . .
    ///          9: . . . . . . . . . . . . . . .
    ///          A: . . . . . . . . . . . . . . .
    ///          B: . . . . . . . . . . . . . . .
    ///          C: . . . . . . . . . . . . . . .
    ///          D: . . . . . . . . . . . . . . .
    ///          E: . . . . . . . . . . . . . . .
    ///             1 2 3 4 5 6 7 8 9 A B C D E F
    ///
    /// The _O_ is on `0x44`, the _X_ is on `0x78` (the middle)
    ///
    /// * The header consists of 20 bytes:
    ///         0xFF,  'R',  'e',  'n',  'L',  'i',  'b', 0xFF,
    ///         MAJOR_VERSION, MINOR_VERSION, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    ///         0xFF, 0xFF, 0xFF, 0xFF
    ///
    /// This can be shown with the command `xxd -g 1 -c8 <.lib file>`
    ///
    /// Note that the minor version doesn't really work, it hasn't been updated in code. Oh well.
    ///
    /// * FIXME!
    /// These are set in RenLib/MoveNode.cpp
    ///
    ///         const DOWN        = 0x000080;
    ///         const RIGHT       = 0x000040;
    ///         const OLD_COMMENT = 0x000020;
    ///         const MARK        = 0x000010;
    ///         const COMMENT     = 0x000008;
    ///         const START       = 0x000004;
    ///         const NO_MOVE     = 0x000002;
    ///         const EXTENSION   = 0x000001;
    ///         const MASK        = 0xFFFF3F;
    ///
    ///
    ///
    /// *    See RenLib/RenLibDoc.cpp for implementation.
    Lib,
}

impl FileType{
    fn new(path: &Path) -> Option<FileType> {
        match path.extension() {
            Some(pos) if (pos == "pos") => Some(FileType::Pos),
            Some(lib) if (lib == "lib") => Some(FileType::Lib),
            Some(_) => None,
            None => None,
        }
    }
}
pub fn open_file_as_board(path: &Path) -> Option<Board> {
    let display = path.display();
    let filetype = FileType::new(path);
    let mut file = match File::open(&path){
        // Should probably return a none. Or change from Option to Result
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    match filetype {
        Some(FileType::Pos) => {
            let mut board = Board::new(15);
            for (index, pos) in file.bytes().skip(1).enumerate() { // First value should always be the number of moves.
                board.set_point(Point::from_1d(pos.ok().unwrap() as u32, 15), if index % 2 == 0 {Stone::Black} else {Stone::White});
            }
            return Some(board);
        },
        Some(FileType::Lib) => {
            let file: Vec<u8> = file.bytes().map(|x| x.unwrap()).collect();
            let header: Vec<u8> = file.drain(0..21).collect();
            let Game = unimplemented!();
            let major_file_version = header[8] as u32;
            let minor_file_version = header[9] as u32;

            let command_iter = file.into_iter().peekable();

            // Here we will want to do everything that is needed.
            // First value is "always" the starting position.
            //
            while command_iter.peek().is_some() {
                unimplemented!();
            }

            unimplemented!();
        },
        _ => unimplemented!(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;
    use board_logic as bl;

    #[test]
    fn open_pos_file(){
        let file = Path::new("examplefiles/example.pos");
        let mut board = open_file_as_board(file).unwrap();
        println!("\n{}", board.board);
    }
}
<|endoftext|>


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

/*!
 * Concurrency-enabled mechanisms for sharing mutable and/or immutable state
 * between tasks.
 */

use core::atomics;
use core::clone::Clone;
use core::kinds::{Share, Send};
use core::mem::{min_align_of, size_of, drop};
use core::mem;
use core::ops::{Drop, Deref};
use core::option::{Some, None, Option};
use core::ptr;
use core::ptr::RawPtr;
use heap::deallocate;

/// An atomically reference counted wrapper for shared state.
///
/// # Example
///
/// In this example, a large vector of floats is shared between several tasks.
/// With simple pipes, without `Arc`, a copy would have to be made for each
/// task.
///
/// ```rust
/// extern crate sync;
///
/// use sync::Arc;
///
/// fn main() {
///     let numbers = Vec::from_fn(100, |i| i as f32);
///     let shared_numbers = Arc::new(numbers);
///
///     for _ in range(0, 10) {
///         let child_numbers = shared_numbers.clone();
///
///         spawn(proc() {
///             let local_numbers = child_numbers.as_slice();
///
///             // Work with the local numbers
///         });
///     }
/// }
/// ```
#[unsafe_no_drop_flag]
pub struct Arc<T> {
    // FIXME #12808: strange name to try to avoid interfering with
    // field accesses of the contained type via Deref
    _ptr: *mut ArcInner<T>,
}

/// A weak pointer to an `Arc`.
///
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
/// used to break cycles between `Arc` pointers.
#[unsafe_no_drop_flag]
pub struct Weak<T> {
    // FIXME #12808: strange name to try to avoid interfering with
    // field accesses of the contained type via Deref
    _ptr: *mut ArcInner<T>,
}

struct ArcInner<T> {
    strong: atomics::AtomicUint,
    weak: atomics::AtomicUint,
    data: T,
}

impl<T: Share + Send> Arc<T> {
    /// Create an atomically reference counted wrapper.
    #[inline]
    pub fn new(data: T) -> Arc<T> {
        // Start the weak pointer count as 1 which is the weak pointer that's
        // held by all the strong pointers (kinda), see std/rc.rs for more info
        let x = box ArcInner {
            strong: atomics::AtomicUint::new(1),
            weak: atomics::AtomicUint::new(1),
            data: data,
        };
        Arc { _ptr: unsafe { mem::transmute(x) } }
    }

    #[inline]
    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
        // This unsafety is ok because while this arc is alive we're guaranteed
        // that the inner pointer is valid. Furthermore, we know that the
        // `ArcInner` structure itself is `Share` because the inner data is
        // `Share` as well, so we're ok loaning out an immutable pointer to
        // these contents.
        unsafe { &*self._ptr }
    }

    /// Downgrades a strong pointer to a weak pointer
    ///
    /// Weak pointers will not keep the data alive. Once all strong references
    /// to the underlying data have been dropped, the data itself will be
    /// destroyed.
    pub fn downgrade(&self) -> Weak<T> {
        // See the clone() impl for why this is relaxed
        self.inner().weak.fetch_add(1, atomics::Relaxed);
        Weak { _ptr: self._ptr }
    }
}

impl<T: Share + Send> Clone for Arc<T> {
    /// Duplicate an atomically reference counted wrapper.
    ///
    /// The resulting two `Arc` objects will point to the same underlying data
    /// object. However, one of the `Arc` objects can be sent to another task,
    /// allowing them to share the underlying data.
    #[inline]
    fn clone(&self) -> Arc<T> {
        // Using a relaxed ordering is alright here, as knowledge of the
        // original reference prevents other threads from erroneously deleting
        // the object.
        //
        // As explained in the [Boost documentation][1], Increasing the
        // reference counter can always be done with memory_order_relaxed: New
        // references to an object can only be formed from an existing
        // reference, and passing an existing reference from one thread to
        // another must already provide any required synchronization.
        //
        // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
        self.inner().strong.fetch_add(1, atomics::Relaxed);
        Arc { _ptr: self._ptr }
    }
}

impl<T: Send + Share> Deref<T> for Arc<T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        &self.inner().data
    }
}

impl<T: Send + Share + Clone> Arc<T> {
    /// Acquires a mutable pointer to the inner contents by guaranteeing that
    /// the reference count is one (no sharing is possible).
    ///
    /// This is also referred to as a copy-on-write operation because the inner
    /// data is cloned if the reference count is greater than one.
    #[inline]
    #[experimental]
    pub fn make_unique<'a>(&'a mut self) -> &'a mut T {
        if self.inner().strong.load(atomics::SeqCst) != 1 {
            *self = Arc::new(self.deref().clone())
        }
        // This unsafety is ok because we're guaranteed that the pointer
        // returned is the *only* pointer that will ever be returned to T. Our
        // reference count is guaranteed to be 1 at this point, and we required
        // the Arc itself to be `mut`, so we're returning the only possible
        // reference to the inner data.
        unsafe { mem::transmute::<&_, &mut _>(self.deref()) }
    }
}

#[unsafe_destructor]
impl<T: Share + Send> Drop for Arc<T> {
    fn drop(&mut self) {
        // This structure has #[unsafe_no_drop_flag], so this drop glue may run
        // more than once (but it is guaranteed to be zeroed after the first if
        // it's run more than once)
        if self._ptr.is_null() { return }

        // Because `fetch_sub` is already atomic, we do not need to synchronize
        // with other threads unless we are going to delete the object. This
        // same logic applies to the below `fetch_sub` to the `weak` count.
        if self.inner().strong.fetch_sub(1, atomics::Release) != 1 { return }

        // This fence is needed to prevent reordering of use of the data and
        // deletion of the data. Because it is marked `Release`, the
        // decreasing of the reference count sychronizes with this `Acquire`
        // fence. This means that use of the data happens before decreasing
        // the refernce count, which happens before this fence, which
        // happens before the deletion of the data.
        //
        // As explained in the [Boost documentation][1],
        //
        // It is important to enforce any possible access to the object in
        // one thread (through an existing reference) to *happen before*
        // deleting the object in a different thread. This is achieved by a
        // "release" operation after dropping a reference (any access to the
        // object through this reference must obviously happened before),
        // and an "acquire" operation before deleting the object.
        //
        // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
        atomics::fence(atomics::Acquire);

        // Destroy the data at this time, even though we may not free the box
        // allocation itself (there may still be weak pointers lying around).
        unsafe { drop(ptr::read(&self.inner().data)); }

        if self.inner().weak.fetch_sub(1, atomics::Release) == 1 {
            atomics::fence(atomics::Acquire);
            unsafe { deallocate(self._ptr as *mut u8, size_of::<ArcInner<T>>(),
                                min_align_of::<ArcInner<T>>()) }
        }
    }
}

impl<T: Share + Send> Weak<T> {
    /// Attempts to upgrade this weak reference to a strong reference.
    ///
    /// This method will fail to upgrade this reference if the strong reference
    /// count has already reached 0, but if there are still other active strong
    /// references this function will return a new strong reference to the data
    pub fn upgrade(&self) -> Option<Arc<T>> {
        // We use a CAS loop to increment the strong count instead of a
        // fetch_add because once the count hits 0 is must never be above 0.
        let inner = self.inner();
        loop {
            let n = inner.strong.load(atomics::SeqCst);
            if n == 0 { return None }
            let old = inner.strong.compare_and_swap(n, n + 1, atomics::SeqCst);
            if old == n { return Some(Arc { _ptr: self._ptr }) }
        }
    }

    #[inline]
    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
        // See comments above for why this is "safe"
        unsafe { &*self._ptr }
    }
}

impl<T: Share + Send> Clone for Weak<T> {
    #[inline]
    fn clone(&self) -> Weak<T> {
        // See comments in Arc::clone() for why this is relaxed
        self.inner().weak.fetch_add(1, atomics::Relaxed);
        Weak { _ptr: self._ptr }
    }
}

#[unsafe_destructor]
impl<T: Share + Send> Drop for Weak<T> {
    fn drop(&mut self) {
        // see comments above for why this check is here
        if self._ptr.is_null() { return }

        // If we find out that we were the last weak pointer, then its time to
        // deallocate the data entirely. See the discussion in Arc::drop() about
        // the memory orderings
        if self.inner().weak.fetch_sub(1, atomics::Release) == 1 {
            atomics::fence(atomics::Acquire);
            unsafe { deallocate(self._ptr as *mut u8, size_of::<ArcInner<T>>(),
                                min_align_of::<ArcInner<T>>()) }
        }
    }
}

#[cfg(test)]
#[allow(experimental)]
mod tests {
    use std::clone::Clone;
    use std::comm::channel;
    use std::mem::drop;
    use std::ops::Drop;
    use std::option::{Option, Some, None};
    use std::sync::atomics;
    use std::task;
    use std::vec::Vec;
    use super::{Arc, Weak};
    use sync::Mutex;

    struct Canary(*mut atomics::AtomicUint);

    impl Drop for Canary
    {
        fn drop(&mut self) {
            unsafe {
                match *self {
                    Canary(c) => {
                        (*c).fetch_add(1, atomics::SeqCst);
                    }
                }
            }
        }
    }

    #[test]
    fn manually_share_arc() {
        let v = vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        let arc_v = Arc::new(v);

        let (tx, rx) = channel();

        task::spawn(proc() {
            let arc_v: Arc<Vec<int>> = rx.recv();
            assert_eq!(*arc_v.get(3), 4);
        });

        tx.send(arc_v.clone());

        assert_eq!(*arc_v.get(2), 3);
        assert_eq!(*arc_v.get(4), 5);

        info!("{:?}", arc_v);
    }

    #[test]
    fn test_cowarc_clone_make_unique() {
        let mut cow0 = Arc::new(75u);
        let mut cow1 = cow0.clone();
        let mut cow2 = cow1.clone();

        assert!(75 == *cow0.make_unique());
        assert!(75 == *cow1.make_unique());
        assert!(75 == *cow2.make_unique());

        *cow0.make_unique() += 1;
        *cow1.make_unique() += 2;
        *cow2.make_unique() += 3;

        assert!(76 == *cow0);
        assert!(77 == *cow1);
        assert!(78 == *cow2);

        // none should point to the same backing memory
        assert!(*cow0 != *cow1);
        assert!(*cow0 != *cow2);
        assert!(*cow1 != *cow2);
    }

    #[test]
    fn test_cowarc_clone_unique2() {
        let mut cow0 = Arc::new(75u);
        let cow1 = cow0.clone();
        let cow2 = cow1.clone();

        assert!(75 == *cow0);
        assert!(75 == *cow1);
        assert!(75 == *cow2);

        *cow0.make_unique() += 1;

        assert!(76 == *cow0);
        assert!(75 == *cow1);
        assert!(75 == *cow2);

        // cow1 and cow2 should share the same contents
        // cow0 should have a unique reference
        assert!(*cow0 != *cow1);
        assert!(*cow0 != *cow2);
        assert!(*cow1 == *cow2);
    }

    #[test]
    fn test_live() {
        let x = Arc::new(5);
        let y = x.downgrade();
        assert!(y.upgrade().is_some());
    }

    #[test]
    fn test_dead() {
        let x = Arc::new(5);
        let y = x.downgrade();
        drop(x);
        assert!(y.upgrade().is_none());
    }

    #[test]
    fn weak_self_cyclic() {
        struct Cycle {
            x: Mutex<Option<Weak<Cycle>>>
        }

        let a = Arc::new(Cycle { x: Mutex::new(None) });
        let b = a.clone().downgrade();
        *a.x.lock() = Some(b);

        // hopefully we don't double-free (or leak)...
    }

    #[test]
    fn drop_arc() {
        let mut canary = atomics::AtomicUint::new(0);
        let x = Arc::new(Canary(&mut canary as *mut atomics::AtomicUint));
        drop(x);
        assert!(canary.load(atomics::Acquire) == 1);
    }

    #[test]
    fn drop_arc_weak() {
        let mut canary = atomics::AtomicUint::new(0);
        let arc = Arc::new(Canary(&mut canary as *mut atomics::AtomicUint));
        let arc_weak = arc.downgrade();
        assert!(canary.load(atomics::Acquire) == 0);
        drop(arc);
        assert!(canary.load(atomics::Acquire) == 1);
        drop(arc_weak);
    }
}
<commit_msg>Issue #13933: Remove transmute_mut from Arc<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Concurrency-enabled mechanisms for sharing mutable and/or immutable state
 * between tasks.
 */

use core::atomics;
use core::clone::Clone;
use core::kinds::{Share, Send};
use core::mem::{min_align_of, size_of, drop};
use core::mem;
use core::ops::{Drop, Deref};
use core::option::{Some, None, Option};
use core::ptr;
use core::ptr::RawPtr;
use heap::deallocate;

/// An atomically reference counted wrapper for shared state.
///
/// # Example
///
/// In this example, a large vector of floats is shared between several tasks.
/// With simple pipes, without `Arc`, a copy would have to be made for each
/// task.
///
/// ```rust
/// extern crate sync;
///
/// use sync::Arc;
///
/// fn main() {
///     let numbers = Vec::from_fn(100, |i| i as f32);
///     let shared_numbers = Arc::new(numbers);
///
///     for _ in range(0, 10) {
///         let child_numbers = shared_numbers.clone();
///
///         spawn(proc() {
///             let local_numbers = child_numbers.as_slice();
///
///             // Work with the local numbers
///         });
///     }
/// }
/// ```
#[unsafe_no_drop_flag]
pub struct Arc<T> {
    // FIXME #12808: strange name to try to avoid interfering with
    // field accesses of the contained type via Deref
    _ptr: *mut ArcInner<T>,
}

/// A weak pointer to an `Arc`.
///
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
/// used to break cycles between `Arc` pointers.
#[unsafe_no_drop_flag]
pub struct Weak<T> {
    // FIXME #12808: strange name to try to avoid interfering with
    // field accesses of the contained type via Deref
    _ptr: *mut ArcInner<T>,
}

struct ArcInner<T> {
    strong: atomics::AtomicUint,
    weak: atomics::AtomicUint,
    data: T,
}

impl<T: Share + Send> Arc<T> {
    /// Create an atomically reference counted wrapper.
    #[inline]
    pub fn new(data: T) -> Arc<T> {
        // Start the weak pointer count as 1 which is the weak pointer that's
        // held by all the strong pointers (kinda), see std/rc.rs for more info
        let x = box ArcInner {
            strong: atomics::AtomicUint::new(1),
            weak: atomics::AtomicUint::new(1),
            data: data,
        };
        Arc { _ptr: unsafe { mem::transmute(x) } }
    }

    #[inline]
    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
        // This unsafety is ok because while this arc is alive we're guaranteed
        // that the inner pointer is valid. Furthermore, we know that the
        // `ArcInner` structure itself is `Share` because the inner data is
        // `Share` as well, so we're ok loaning out an immutable pointer to
        // these contents.
        unsafe { &*self._ptr }
    }

    /// Downgrades a strong pointer to a weak pointer
    ///
    /// Weak pointers will not keep the data alive. Once all strong references
    /// to the underlying data have been dropped, the data itself will be
    /// destroyed.
    pub fn downgrade(&self) -> Weak<T> {
        // See the clone() impl for why this is relaxed
        self.inner().weak.fetch_add(1, atomics::Relaxed);
        Weak { _ptr: self._ptr }
    }
}

impl<T: Share + Send> Clone for Arc<T> {
    /// Duplicate an atomically reference counted wrapper.
    ///
    /// The resulting two `Arc` objects will point to the same underlying data
    /// object. However, one of the `Arc` objects can be sent to another task,
    /// allowing them to share the underlying data.
    #[inline]
    fn clone(&self) -> Arc<T> {
        // Using a relaxed ordering is alright here, as knowledge of the
        // original reference prevents other threads from erroneously deleting
        // the object.
        //
        // As explained in the [Boost documentation][1], Increasing the
        // reference counter can always be done with memory_order_relaxed: New
        // references to an object can only be formed from an existing
        // reference, and passing an existing reference from one thread to
        // another must already provide any required synchronization.
        //
        // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
        self.inner().strong.fetch_add(1, atomics::Relaxed);
        Arc { _ptr: self._ptr }
    }
}

impl<T: Send + Share> Deref<T> for Arc<T> {
    #[inline]
    fn deref<'a>(&'a self) -> &'a T {
        &self.inner().data
    }
}

impl<T: Send + Share + Clone> Arc<T> {
    /// Acquires a mutable pointer to the inner contents by guaranteeing that
    /// the reference count is one (no sharing is possible).
    ///
    /// This is also referred to as a copy-on-write operation because the inner
    /// data is cloned if the reference count is greater than one.
    #[inline]
    #[experimental]
    pub fn make_unique<'a>(&'a mut self) -> &'a mut T {
        if self.inner().strong.load(atomics::SeqCst) != 1 {
            *self = Arc::new(self.deref().clone())
        }
        // This unsafety is ok because we're guaranteed that the pointer
        // returned is the *only* pointer that will ever be returned to T. Our
        // reference count is guaranteed to be 1 at this point, and we required
        // the Arc itself to be `mut`, so we're returning the only possible
        // reference to the inner data.
        let inner = unsafe { &mut *self._ptr };
        &mut inner.data
    }
}

#[unsafe_destructor]
impl<T: Share + Send> Drop for Arc<T> {
    fn drop(&mut self) {
        // This structure has #[unsafe_no_drop_flag], so this drop glue may run
        // more than once (but it is guaranteed to be zeroed after the first if
        // it's run more than once)
        if self._ptr.is_null() { return }

        // Because `fetch_sub` is already atomic, we do not need to synchronize
        // with other threads unless we are going to delete the object. This
        // same logic applies to the below `fetch_sub` to the `weak` count.
        if self.inner().strong.fetch_sub(1, atomics::Release) != 1 { return }

        // This fence is needed to prevent reordering of use of the data and
        // deletion of the data. Because it is marked `Release`, the
        // decreasing of the reference count sychronizes with this `Acquire`
        // fence. This means that use of the data happens before decreasing
        // the refernce count, which happens before this fence, which
        // happens before the deletion of the data.
        //
        // As explained in the [Boost documentation][1],
        //
        // It is important to enforce any possible access to the object in
        // one thread (through an existing reference) to *happen before*
        // deleting the object in a different thread. This is achieved by a
        // "release" operation after dropping a reference (any access to the
        // object through this reference must obviously happened before),
        // and an "acquire" operation before deleting the object.
        //
        // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
        atomics::fence(atomics::Acquire);

        // Destroy the data at this time, even though we may not free the box
        // allocation itself (there may still be weak pointers lying around).
        unsafe { drop(ptr::read(&self.inner().data)); }

        if self.inner().weak.fetch_sub(1, atomics::Release) == 1 {
            atomics::fence(atomics::Acquire);
            unsafe { deallocate(self._ptr as *mut u8, size_of::<ArcInner<T>>(),
                                min_align_of::<ArcInner<T>>()) }
        }
    }
}

impl<T: Share + Send> Weak<T> {
    /// Attempts to upgrade this weak reference to a strong reference.
    ///
    /// This method will fail to upgrade this reference if the strong reference
    /// count has already reached 0, but if there are still other active strong
    /// references this function will return a new strong reference to the data
    pub fn upgrade(&self) -> Option<Arc<T>> {
        // We use a CAS loop to increment the strong count instead of a
        // fetch_add because once the count hits 0 is must never be above 0.
        let inner = self.inner();
        loop {
            let n = inner.strong.load(atomics::SeqCst);
            if n == 0 { return None }
            let old = inner.strong.compare_and_swap(n, n + 1, atomics::SeqCst);
            if old == n { return Some(Arc { _ptr: self._ptr }) }
        }
    }

    #[inline]
    fn inner<'a>(&'a self) -> &'a ArcInner<T> {
        // See comments above for why this is "safe"
        unsafe { &*self._ptr }
    }
}

impl<T: Share + Send> Clone for Weak<T> {
    #[inline]
    fn clone(&self) -> Weak<T> {
        // See comments in Arc::clone() for why this is relaxed
        self.inner().weak.fetch_add(1, atomics::Relaxed);
        Weak { _ptr: self._ptr }
    }
}

#[unsafe_destructor]
impl<T: Share + Send> Drop for Weak<T> {
    fn drop(&mut self) {
        // see comments above for why this check is here
        if self._ptr.is_null() { return }

        // If we find out that we were the last weak pointer, then its time to
        // deallocate the data entirely. See the discussion in Arc::drop() about
        // the memory orderings
        if self.inner().weak.fetch_sub(1, atomics::Release) == 1 {
            atomics::fence(atomics::Acquire);
            unsafe { deallocate(self._ptr as *mut u8, size_of::<ArcInner<T>>(),
                                min_align_of::<ArcInner<T>>()) }
        }
    }
}

#[cfg(test)]
#[allow(experimental)]
mod tests {
    use std::clone::Clone;
    use std::comm::channel;
    use std::mem::drop;
    use std::ops::Drop;
    use std::option::{Option, Some, None};
    use std::sync::atomics;
    use std::task;
    use std::vec::Vec;
    use super::{Arc, Weak};
    use sync::Mutex;

    struct Canary(*mut atomics::AtomicUint);

    impl Drop for Canary
    {
        fn drop(&mut self) {
            unsafe {
                match *self {
                    Canary(c) => {
                        (*c).fetch_add(1, atomics::SeqCst);
                    }
                }
            }
        }
    }

    #[test]
    fn manually_share_arc() {
        let v = vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        let arc_v = Arc::new(v);

        let (tx, rx) = channel();

        task::spawn(proc() {
            let arc_v: Arc<Vec<int>> = rx.recv();
            assert_eq!(*arc_v.get(3), 4);
        });

        tx.send(arc_v.clone());

        assert_eq!(*arc_v.get(2), 3);
        assert_eq!(*arc_v.get(4), 5);

        info!("{:?}", arc_v);
    }

    #[test]
    fn test_cowarc_clone_make_unique() {
        let mut cow0 = Arc::new(75u);
        let mut cow1 = cow0.clone();
        let mut cow2 = cow1.clone();

        assert!(75 == *cow0.make_unique());
        assert!(75 == *cow1.make_unique());
        assert!(75 == *cow2.make_unique());

        *cow0.make_unique() += 1;
        *cow1.make_unique() += 2;
        *cow2.make_unique() += 3;

        assert!(76 == *cow0);
        assert!(77 == *cow1);
        assert!(78 == *cow2);

        // none should point to the same backing memory
        assert!(*cow0 != *cow1);
        assert!(*cow0 != *cow2);
        assert!(*cow1 != *cow2);
    }

    #[test]
    fn test_cowarc_clone_unique2() {
        let mut cow0 = Arc::new(75u);
        let cow1 = cow0.clone();
        let cow2 = cow1.clone();

        assert!(75 == *cow0);
        assert!(75 == *cow1);
        assert!(75 == *cow2);

        *cow0.make_unique() += 1;

        assert!(76 == *cow0);
        assert!(75 == *cow1);
        assert!(75 == *cow2);

        // cow1 and cow2 should share the same contents
        // cow0 should have a unique reference
        assert!(*cow0 != *cow1);
        assert!(*cow0 != *cow2);
        assert!(*cow1 == *cow2);
    }

    #[test]
    fn test_live() {
        let x = Arc::new(5);
        let y = x.downgrade();
        assert!(y.upgrade().is_some());
    }

    #[test]
    fn test_dead() {
        let x = Arc::new(5);
        let y = x.downgrade();
        drop(x);
        assert!(y.upgrade().is_none());
    }

    #[test]
    fn weak_self_cyclic() {
        struct Cycle {
            x: Mutex<Option<Weak<Cycle>>>
        }

        let a = Arc::new(Cycle { x: Mutex::new(None) });
        let b = a.clone().downgrade();
        *a.x.lock() = Some(b);

        // hopefully we don't double-free (or leak)...
    }

    #[test]
    fn drop_arc() {
        let mut canary = atomics::AtomicUint::new(0);
        let x = Arc::new(Canary(&mut canary as *mut atomics::AtomicUint));
        drop(x);
        assert!(canary.load(atomics::Acquire) == 1);
    }

    #[test]
    fn drop_arc_weak() {
        let mut canary = atomics::AtomicUint::new(0);
        let arc = Arc::new(Canary(&mut canary as *mut atomics::AtomicUint));
        let arc_weak = arc.downgrade();
        assert!(canary.load(atomics::Acquire) == 0);
        drop(arc);
        assert!(canary.load(atomics::Acquire) == 1);
        drop(arc_weak);
    }
}
<|endoftext|>