<commit_before>use std::cell::RefCell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::io;
use std::rc::Rc;
use std::{i32, u64};

use bytes::BytesMut;
use futures::sync::mpsc;
use futures::{self, Async, Poll, StartSend, Stream};
use tokio_core::reactor::Handle;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_proto::multiplex::{ClientProto, RequestId};

use lber::common::TagClass;
use lber::{Consumer, ConsumerState, Input, IResult, Move};
use lber::structure::{PL, StructureTag};
use lber::structures::{ASNTag, Integer, Null, Sequence, Tag};
use lber::parse::parse_uint;
use lber::parse::Parser;
use lber::universal::Types;
use lber::write;

use controls::Control;
use controls_impl::parse_controls;
use exop::Exop;
use ldap::LdapOp;
use search::SearchItem;

pub type LdapRequestId = i32;

pub struct ProtoBundle {
    pub search_helpers: HashMap<RequestId, SearchHelper>,
    pub abandoned: HashSet<RequestId>,
    pub id_map: HashMap<LdapRequestId, RequestId>,
    pub next_id: LdapRequestId,
    pub handle: Handle,
    pub solo_ops: VecDeque<RequestId>,
}

impl ProtoBundle {
    fn create_search_helper(&mut self, id: RequestId, tx: mpsc::UnboundedSender<SearchItem>) {
        self.search_helpers.insert(id, SearchHelper {
            seen: false,
            msgid: 0,           // not valid, must be properly initialized later
            tx: tx,
        });
    }

    fn inc_next_id(&mut self) -> LdapRequestId {
        if self.next_id == i32::MAX {
            self.next_id = 0;
        }
        self.next_id += 1;
        self.next_id
    }
}

pub struct SearchHelper {
    pub seen: bool,
    pub msgid: LdapRequestId,
    pub tx: mpsc::UnboundedSender<SearchItem>,
}

impl SearchHelper {
    fn send_item(&mut self, item: SearchItem) -> io::Result<()> {
        self.tx.send(item).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
    }
}

/// Common components of an LDAP operation result.
///
/// This structure faithfully replicates the components dictated by the standard,
/// and is distinctly C-like with its reliance on numeric codes for the indication
/// of outcome. It would be tempting to hide it behind an automatic `Result`-like
/// interface, but there are scenarios where this would preclude intentional
/// incorporation of error conditions into query design.
///
/// A series of helper methods to provide idiomatic error handling is planned.
///
/// __Note__: this structure will probably be extended with the vector of
/// response controls in version 0.5.x, since controls are always part of the
/// response message.
#[derive(Clone, Debug)]
pub struct LdapResult {
    /// Result code.
    ///
    /// Generally, the value of zero indicates successful completion, but there's
    /// a number of other non-error codes arising as a result of various operations.
    /// See [Section A.1 of RFC 4511](https://tools.ietf.org/html/rfc4511#appendix-A.1).
    pub rc: u8,
    /// Matched component DN, where applicable.
    pub matched: String,
    /// Additional diagnostic text.
    pub text: String,
    /// Referrals.
    ///
    /// In the current implementation, all referrals received during a Search
    /// operation will be accumulated in this vector.
    pub refs: Vec<HashSet<String>>,
}

#[derive(Clone, Debug)]
pub struct LdapResultExt(pub LdapResult, pub Exop);

impl From<Tag> for LdapResultExt {
    fn from(t: Tag) -> LdapResultExt {
        let t = match t {
            Tag::StructureTag(t) => t,
            _ => unimplemented!(),
        };
        let mut tags = t.expect_constructed().expect("result sequence").into_iter();
        let rc = match parse_uint(tags.next().expect("element")
                .match_class(TagClass::Universal)
                .and_then(|t| t.match_id(Types::Enumerated as u64))
                .and_then(|t| t.expect_primitive()).expect("result code")
                .as_slice()) {
            IResult::Done(_, rc) => rc as u8,
            _ => panic!("failed to parse result code"),
        };
        let matched = String::from_utf8(tags.next().expect("element").expect_primitive().expect("octet string"))
            .expect("matched dn");
        let text = String::from_utf8(tags.next().expect("element").expect_primitive().expect("octet string"))
            .expect("diagnostic message");
        let mut refs = Vec::new();
        let mut exop_name = None;
        let mut exop_val = None;
        loop {
            match tags.next() {
                None => break,
                Some(comp) => match comp.id {
                    3 => {
                        let raw_refs = match comp.expect_constructed() {
                            Some(rr) => rr,
                            None => panic!("failed to parse referrals"),
                        };
                        refs.push(raw_refs.into_iter()
                            .map(|t| t.expect_primitive().expect("octet string"))
                            .map(String::from_utf8)
                            .map(|s| s.expect("uri"))
                            .collect());
                    },
                    10 => {
                        exop_name = Some(String::from_utf8(comp.expect_primitive().expect("octet string")).expect("exop name"));
                    }
                    11 => {
                        exop_val = Some(comp.expect_primitive().expect("octet string"));
                    }
                    _ => (),
                },
            }
        }
        LdapResultExt(
            LdapResult {
                rc: rc,
                matched: matched,
                text: text,
                refs: refs,
            },
            Exop {
                name: exop_name,
                val: exop_val
            })
    }
}

#[doc(hidden)]
impl From<Tag> for LdapResult {
    fn from(t: Tag) -> LdapResult {
        <LdapResultExt as From<Tag>>::from(t).0
    }
}

pub struct LdapCodec {
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl Decoder for LdapCodec {
    type Item = (RequestId, (Tag, Vec<Control>));
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        let decoding_error = io::Error::new(io::ErrorKind::Other, "decoding error");
        let mut parser = Parser::new();
        let (amt, tag) = match *parser.handle(Input::Element(buf)) {
            ConsumerState::Continue(_) => return Ok(None),
            ConsumerState::Error(_e) => return Err(decoding_error),
            ConsumerState::Done(amt, ref tag) => (amt, tag),
        };
        let amt = match amt {
            Move::Await(_) => return Ok(None),
            Move::Seek(_) => return Err(decoding_error),
            Move::Consume(amt) => amt,
        };
        buf.split_to(amt);
        let tag = tag.clone();
        let mut tags = match tag.match_id(Types::Sequence as u64).and_then(|t| t.expect_constructed()) {
            Some(tags) => tags,
            None => return Err(decoding_error),
        };
        let maybe_controls = tags.pop().expect("element");
        let has_controls = match maybe_controls {
            StructureTag { id, class, ref payload } if class == TagClass::Context && id == 0 => match *payload {
                PL::C(_) => true,
                PL::P(_) => return Err(decoding_error),
            },
            _ => false,
        };
        let (protoop, controls) = if has_controls {
            (tags.pop().expect("element"), Some(maybe_controls))
        } else {
            (maybe_controls, None)
        };
        let controls = match controls {
            Some(controls) => parse_controls(controls),
            None => vec![],
        };
        let msgid = match parse_uint(tags.pop().expect("element")
                .match_class(TagClass::Universal)
                .and_then(|t| t.match_id(Types::Integer as u64))
                .and_then(|t| t.expect_primitive()).expect("message id")
                .as_slice()) {
            IResult::Done(_, id) => id as i32,
            _ => return Err(decoding_error),
        };
        let id = match self.bundle.borrow().id_map.get(&msgid) {
            Some(&id) => id,
            None => {
                warn!("discarding frame with unmatched msgid: {}", msgid);
                let null_tag = Tag::Null(Null { ..Default::default() });
                return Ok(Some((u64::MAX, (null_tag, vec![]))));
            },
        };
        match protoop.id {
            op_id @ 4 | op_id @ 5 | op_id @ 19 => {
                let null_tag = Tag::Null(Null { ..Default::default() });
                let id_tag = Tag::Integer(Integer {
                    inner: id as i64,
                    .. Default::default()
                });
                let mut bundle = self.bundle.borrow_mut();
                let mut helper = match bundle.search_helpers.get_mut(&id) {
                    Some(h) => h,
                    None => return Err(io::Error::new(io::ErrorKind::Other, format!("id mismatch: {}", id))),
                };
                helper.send_item(match op_id {
                    4 => SearchItem::Entry(protoop),
                    5 => SearchItem::Done(id, Tag::StructureTag(protoop).into(), controls),
                    19 => SearchItem::Referral(protoop),
                    _ => panic!("impossible op_id"),
                })?;
                if helper.seen {
                    Ok(Some((u64::MAX, (null_tag, vec![]))))
                } else {
                    helper.seen = true;
                    Ok(Some((id, (id_tag, vec![]))))
                }
            },
            _ => {
                self.bundle.borrow_mut().id_map.remove(&msgid);
                Ok(Some((id, (Tag::StructureTag(protoop), controls))))
            },
        }
    }
}

impl Encoder for LdapCodec {
    type Item = (RequestId, LdapOp);
    type Error = io::Error;

    fn encode(&mut self, msg: Self::Item, into: &mut BytesMut) -> io::Result<()> {
        let (id, op) = msg;
        let (tag, controls) = match op {
            LdapOp::Single(tag, controls) => (tag, controls),
            LdapOp::Multi(tag, tx, controls, set_id_in_op) => {
                self.bundle.borrow_mut().create_search_helper(id, tx);
                set_id_in_op(id);
                (tag, controls)
            },
            LdapOp::Solo(tag, controls) => {
                self.bundle.borrow_mut().solo_ops.push_back(id);
                (tag, controls)
            },
        };
        let outstruct = {
            // tokio-proto ids are u64, and LDAP (client) message ids are i32 > 0,
            // so we must have wraparound logic and a mapping from the latter to
            // the former
            let mut bundle = self.bundle.borrow_mut();
            let prev_ldap_id = bundle.next_id;
            let mut next_ldap_id = prev_ldap_id;
            while bundle.id_map.entry(next_ldap_id).or_insert(id) != &id {
                next_ldap_id = bundle.inc_next_id();
                assert_ne!(next_ldap_id, prev_ldap_id, "LDAP message id wraparound with no free slots");
            }
            bundle.inc_next_id();
            if let Some(ref mut helper) = bundle.search_helpers.get_mut(&id) {
                helper.msgid = next_ldap_id;
            }
            let mut msg = vec![
                Tag::Integer(Integer {
                    inner: next_ldap_id as i64,
                    .. Default::default()
                }),
                tag
            ];
            if let Some(controls) = controls {
                msg.push(Tag::StructureTag(StructureTag {
                    id: 0,
                    class: TagClass::Context,
                    payload: PL::C(controls)
                }));
            }
            Tag::Sequence(Sequence {
                inner: msg,
                .. Default::default()
            }).into_structure()
        };
        trace!("Sending packet: {:?}", &outstruct);
        write::encode_into(into, outstruct)?;
        Ok(())
    }
}

pub struct LdapProto {
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl LdapProto {
    pub fn new(handle: Handle) -> LdapProto {
        LdapProto {
            bundle: Rc::new(RefCell::new(ProtoBundle {
                search_helpers: HashMap::new(),
                abandoned: HashSet::new(),
                id_map: HashMap::new(),
                next_id: 1,
                handle: handle,
                solo_ops: VecDeque::new(),
            }))
        }
    }

    pub fn bundle(&self) -> Rc<RefCell<ProtoBundle>> {
        self.bundle.clone()
    }
}

pub struct ResponseFilter<T> {
    upstream: T,
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl<T> Stream for ResponseFilter<T>
    where T: Stream<Item=(RequestId, (Tag, Vec<Control>)), Error=io::Error>
{
    type Item = (RequestId, (Tag, Vec<Control>));
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            if let Some(id) = self.bundle.borrow_mut().solo_ops.pop_front() {
                let null_tag = Tag::Null(Null { ..Default::default() });
                return Ok(Async::Ready(Some((id, (null_tag, vec![])))));
            }
            match try_ready!(self.upstream.poll()) {
                Some((id, _)) if id == u64::MAX => continue,
                msg => return Ok(Async::Ready(msg)),
            }
        }
    }
}

impl<T> futures::Sink for ResponseFilter<T>
    where T: futures::Sink<SinkItem=(RequestId, LdapOp), SinkError=io::Error>
{
    type SinkItem = (RequestId, LdapOp);
    type SinkError = io::Error;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.upstream.poll_complete()
    }
}

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LdapProto {
    type Request = LdapOp;
    type Response = (Tag, Vec<Control>);

    type Transport = ResponseFilter<Framed<T, LdapCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        let ldapcodec = LdapCodec {
            bundle: self.bundle.clone(),
        };
        Ok(ResponseFilter {
            upstream: io.framed(ldapcodec),
            bundle: self.bundle.clone(),
        })
    }
}
<commit_msg>Release msgid for solo ops<commit_after>use std::cell::RefCell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::io;
use std::rc::Rc;
use std::{i32, u64};

use bytes::BytesMut;
use futures::sync::mpsc;
use futures::{self, Async, Poll, StartSend, Stream};
use tokio_core::reactor::Handle;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_proto::multiplex::{ClientProto, RequestId};

use lber::common::TagClass;
use lber::{Consumer, ConsumerState, Input, IResult, Move};
use lber::structure::{PL, StructureTag};
use lber::structures::{ASNTag, Integer, Null, Sequence, Tag};
use lber::parse::parse_uint;
use lber::parse::Parser;
use lber::universal::Types;
use lber::write;

use controls::Control;
use controls_impl::parse_controls;
use exop::Exop;
use ldap::LdapOp;
use search::SearchItem;

pub type LdapRequestId = i32;

pub struct ProtoBundle {
    pub search_helpers: HashMap<RequestId, SearchHelper>,
    pub abandoned: HashSet<RequestId>,
    pub id_map: HashMap<LdapRequestId, RequestId>,
    pub next_id: LdapRequestId,
    pub handle: Handle,
    pub solo_ops: VecDeque<RequestId>,
}

impl ProtoBundle {
    fn create_search_helper(&mut self, id: RequestId, tx: mpsc::UnboundedSender<SearchItem>) {
        self.search_helpers.insert(id, SearchHelper {
            seen: false,
            msgid: 0,           // not valid, must be properly initialized later
            tx: tx,
        });
    }

    fn inc_next_id(&mut self) -> LdapRequestId {
        if self.next_id == i32::MAX {
            self.next_id = 0;
        }
        self.next_id += 1;
        self.next_id
    }
}

pub struct SearchHelper {
    pub seen: bool,
    pub msgid: LdapRequestId,
    pub tx: mpsc::UnboundedSender<SearchItem>,
}

impl SearchHelper {
    fn send_item(&mut self, item: SearchItem) -> io::Result<()> {
        self.tx.send(item).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
    }
}

/// Common components of an LDAP operation result.
///
/// This structure faithfully replicates the components dictated by the standard,
/// and is distinctly C-like with its reliance on numeric codes for the indication
/// of outcome. It would be tempting to hide it behind an automatic `Result`-like
/// interface, but there are scenarios where this would preclude intentional
/// incorporation of error conditions into query design.
///
/// A series of helper methods to provide idiomatic error handling is planned.
///
/// __Note__: this structure will probably be extended with the vector of
/// response controls in version 0.5.x, since controls are always part of the
/// response message.
#[derive(Clone, Debug)]
pub struct LdapResult {
    /// Result code.
    ///
    /// Generally, the value of zero indicates successful completion, but there's
    /// a number of other non-error codes arising as a result of various operations.
    /// See [Section A.1 of RFC 4511](https://tools.ietf.org/html/rfc4511#appendix-A.1).
    pub rc: u8,
    /// Matched component DN, where applicable.
    pub matched: String,
    /// Additional diagnostic text.
    pub text: String,
    /// Referrals.
    ///
    /// In the current implementation, all referrals received during a Search
    /// operation will be accumulated in this vector.
    pub refs: Vec<HashSet<String>>,
}

#[derive(Clone, Debug)]
pub struct LdapResultExt(pub LdapResult, pub Exop);

impl From<Tag> for LdapResultExt {
    fn from(t: Tag) -> LdapResultExt {
        let t = match t {
            Tag::StructureTag(t) => t,
            _ => unimplemented!(),
        };
        let mut tags = t.expect_constructed().expect("result sequence").into_iter();
        let rc = match parse_uint(tags.next().expect("element")
                .match_class(TagClass::Universal)
                .and_then(|t| t.match_id(Types::Enumerated as u64))
                .and_then(|t| t.expect_primitive()).expect("result code")
                .as_slice()) {
            IResult::Done(_, rc) => rc as u8,
            _ => panic!("failed to parse result code"),
        };
        let matched = String::from_utf8(tags.next().expect("element").expect_primitive().expect("octet string"))
            .expect("matched dn");
        let text = String::from_utf8(tags.next().expect("element").expect_primitive().expect("octet string"))
            .expect("diagnostic message");
        let mut refs = Vec::new();
        let mut exop_name = None;
        let mut exop_val = None;
        loop {
            match tags.next() {
                None => break,
                Some(comp) => match comp.id {
                    3 => {
                        let raw_refs = match comp.expect_constructed() {
                            Some(rr) => rr,
                            None => panic!("failed to parse referrals"),
                        };
                        refs.push(raw_refs.into_iter()
                            .map(|t| t.expect_primitive().expect("octet string"))
                            .map(String::from_utf8)
                            .map(|s| s.expect("uri"))
                            .collect());
                    },
                    10 => {
                        exop_name = Some(String::from_utf8(comp.expect_primitive().expect("octet string")).expect("exop name"));
                    }
                    11 => {
                        exop_val = Some(comp.expect_primitive().expect("octet string"));
                    }
                    _ => (),
                },
            }
        }
        LdapResultExt(
            LdapResult {
                rc: rc,
                matched: matched,
                text: text,
                refs: refs,
            },
            Exop {
                name: exop_name,
                val: exop_val
            })
    }
}

#[doc(hidden)]
impl From<Tag> for LdapResult {
    fn from(t: Tag) -> LdapResult {
        <LdapResultExt as From<Tag>>::from(t).0
    }
}

pub struct LdapCodec {
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl Decoder for LdapCodec {
    type Item = (RequestId, (Tag, Vec<Control>));
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        let decoding_error = io::Error::new(io::ErrorKind::Other, "decoding error");
        let mut parser = Parser::new();
        let (amt, tag) = match *parser.handle(Input::Element(buf)) {
            ConsumerState::Continue(_) => return Ok(None),
            ConsumerState::Error(_e) => return Err(decoding_error),
            ConsumerState::Done(amt, ref tag) => (amt, tag),
        };
        let amt = match amt {
            Move::Await(_) => return Ok(None),
            Move::Seek(_) => return Err(decoding_error),
            Move::Consume(amt) => amt,
        };
        buf.split_to(amt);
        let tag = tag.clone();
        let mut tags = match tag.match_id(Types::Sequence as u64).and_then(|t| t.expect_constructed()) {
            Some(tags) => tags,
            None => return Err(decoding_error),
        };
        let maybe_controls = tags.pop().expect("element");
        let has_controls = match maybe_controls {
            StructureTag { id, class, ref payload } if class == TagClass::Context && id == 0 => match *payload {
                PL::C(_) => true,
                PL::P(_) => return Err(decoding_error),
            },
            _ => false,
        };
        let (protoop, controls) = if has_controls {
            (tags.pop().expect("element"), Some(maybe_controls))
        } else {
            (maybe_controls, None)
        };
        let controls = match controls {
            Some(controls) => parse_controls(controls),
            None => vec![],
        };
        let msgid = match parse_uint(tags.pop().expect("element")
                .match_class(TagClass::Universal)
                .and_then(|t| t.match_id(Types::Integer as u64))
                .and_then(|t| t.expect_primitive()).expect("message id")
                .as_slice()) {
            IResult::Done(_, id) => id as i32,
            _ => return Err(decoding_error),
        };
        let id = match self.bundle.borrow().id_map.get(&msgid) {
            Some(&id) => id,
            None => {
                warn!("discarding frame with unmatched msgid: {}", msgid);
                let null_tag = Tag::Null(Null { ..Default::default() });
                return Ok(Some((u64::MAX, (null_tag, vec![]))));
            },
        };
        match protoop.id {
            op_id @ 4 | op_id @ 5 | op_id @ 19 => {
                let null_tag = Tag::Null(Null { ..Default::default() });
                let id_tag = Tag::Integer(Integer {
                    inner: id as i64,
                    .. Default::default()
                });
                let mut bundle = self.bundle.borrow_mut();
                let mut helper = match bundle.search_helpers.get_mut(&id) {
                    Some(h) => h,
                    None => return Err(io::Error::new(io::ErrorKind::Other, format!("id mismatch: {}", id))),
                };
                helper.send_item(match op_id {
                    4 => SearchItem::Entry(protoop),
                    5 => SearchItem::Done(id, Tag::StructureTag(protoop).into(), controls),
                    19 => SearchItem::Referral(protoop),
                    _ => panic!("impossible op_id"),
                })?;
                if helper.seen {
                    Ok(Some((u64::MAX, (null_tag, vec![]))))
                } else {
                    helper.seen = true;
                    Ok(Some((id, (id_tag, vec![]))))
                }
            },
            _ => {
                self.bundle.borrow_mut().id_map.remove(&msgid);
                Ok(Some((id, (Tag::StructureTag(protoop), controls))))
            },
        }
    }
}

impl Encoder for LdapCodec {
    type Item = (RequestId, LdapOp);
    type Error = io::Error;

    fn encode(&mut self, msg: Self::Item, into: &mut BytesMut) -> io::Result<()> {
        let (id, op) = msg;
        let (tag, controls, is_solo) = match op {
            LdapOp::Single(tag, controls) => (tag, controls, false),
            LdapOp::Multi(tag, tx, controls, set_id_in_op) => {
                self.bundle.borrow_mut().create_search_helper(id, tx);
                set_id_in_op(id);
                (tag, controls, false)
            },
            LdapOp::Solo(tag, controls) => {
                self.bundle.borrow_mut().solo_ops.push_back(id);
                (tag, controls, true)
            },
        };
        let outstruct = {
            // tokio-proto ids are u64, and LDAP (client) message ids are i32 > 0,
            // so we must have wraparound logic and a mapping from the latter to
            // the former
            let mut bundle = self.bundle.borrow_mut();
            let prev_ldap_id = bundle.next_id;
            let mut next_ldap_id = prev_ldap_id;
            while bundle.id_map.entry(next_ldap_id).or_insert(id) != &id {
                next_ldap_id = bundle.inc_next_id();
                assert_ne!(next_ldap_id, prev_ldap_id, "LDAP message id wraparound with no free slots");
            }
            bundle.inc_next_id();
            if let Some(ref mut helper) = bundle.search_helpers.get_mut(&id) {
                helper.msgid = next_ldap_id;
            }
            if is_solo {
                bundle.id_map.remove(&next_ldap_id);
            }
            let mut msg = vec![
                Tag::Integer(Integer {
                    inner: next_ldap_id as i64,
                    .. Default::default()
                }),
                tag
            ];
            if let Some(controls) = controls {
                msg.push(Tag::StructureTag(StructureTag {
                    id: 0,
                    class: TagClass::Context,
                    payload: PL::C(controls)
                }));
            }
            Tag::Sequence(Sequence {
                inner: msg,
                .. Default::default()
            }).into_structure()
        };
        trace!("Sending packet: {:?}", &outstruct);
        write::encode_into(into, outstruct)?;
        Ok(())
    }
}

pub struct LdapProto {
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl LdapProto {
    pub fn new(handle: Handle) -> LdapProto {
        LdapProto {
            bundle: Rc::new(RefCell::new(ProtoBundle {
                search_helpers: HashMap::new(),
                abandoned: HashSet::new(),
                id_map: HashMap::new(),
                next_id: 1,
                handle: handle,
                solo_ops: VecDeque::new(),
            }))
        }
    }

    pub fn bundle(&self) -> Rc<RefCell<ProtoBundle>> {
        self.bundle.clone()
    }
}

pub struct ResponseFilter<T> {
    upstream: T,
    bundle: Rc<RefCell<ProtoBundle>>,
}

impl<T> Stream for ResponseFilter<T>
    where T: Stream<Item=(RequestId, (Tag, Vec<Control>)), Error=io::Error>
{
    type Item = (RequestId, (Tag, Vec<Control>));
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            if let Some(id) = self.bundle.borrow_mut().solo_ops.pop_front() {
                let null_tag = Tag::Null(Null { ..Default::default() });
                return Ok(Async::Ready(Some((id, (null_tag, vec![])))));
            }
            match try_ready!(self.upstream.poll()) {
                Some((id, _)) if id == u64::MAX => continue,
                msg => return Ok(Async::Ready(msg)),
            }
        }
    }
}

impl<T> futures::Sink for ResponseFilter<T>
    where T: futures::Sink<SinkItem=(RequestId, LdapOp), SinkError=io::Error>
{
    type SinkItem = (RequestId, LdapOp);
    type SinkError = io::Error;

    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.upstream.poll_complete()
    }
}

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LdapProto {
    type Request = LdapOp;
    type Response = (Tag, Vec<Control>);

    type Transport = ResponseFilter<Framed<T, LdapCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        let ldapcodec = LdapCodec {
            bundle: self.bundle.clone(),
        };
        Ok(ResponseFilter {
            upstream: io.framed(ldapcodec),
            bundle: self.bundle.clone(),
        })
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.

use geom::rect::Rect;
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use hyper::header::Headers;
use hyper::method::Method;
use layers::geometry::DevicePixel;
use util::cursor::Cursor;
use util::geometry::{PagePx, ViewportPx};
use std::sync::mpsc::{channel, Sender, Receiver};
use url::Url;

#[derive(Clone)]
pub struct ConstellationChan(pub Sender<Msg>);

impl ConstellationChan {
    pub fn new() -> (Receiver<Msg>, ConstellationChan) {
        let (chan, port) = channel();
        (port, ConstellationChan(chan))
    }
}

#[derive(PartialEq, Eq, Copy, Debug)]
pub enum IFrameSandboxState {
    IFrameSandboxed,
    IFrameUnsandboxed
}

// We pass this info to various tasks, so it lives in a separate, cloneable struct.
#[derive(Clone, Copy)]
pub struct Failure {
    pub pipeline_id: PipelineId,
    pub parent_info: Option<(PipelineId, SubpageId)>,
}

#[derive(Copy)]
pub struct WindowSizeData {
    /// The size of the initial layout viewport, before parsing an
    /// http://www.w3.org/TR/css-device-adapt/#initial-viewport
    pub initial_viewport: TypedSize2D<ViewportPx, f32>,

    /// The "viewing area" in page px. See `PagePx` documentation for details.
    pub visible_viewport: TypedSize2D<PagePx, f32>,

    /// The resolution of the window in dppx, not including any "pinch zoom" factor.
    pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum KeyState {
    Pressed,
    Released,
    Repeated,
}

//N.B. Based on the glutin key enum
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Key {
    Space,
    Apostrophe,
    Comma,
    Minus,
    Period,
    Slash,
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    Semicolon,
    Equal,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    LeftBracket,
    Backslash,
    RightBracket,
    GraveAccent,
    World1,
    World2,

    Escape,
    Enter,
    Tab,
    Backspace,
    Insert,
    Delete,
    Right,
    Left,
    Down,
    Up,
    PageUp,
    PageDown,
    Home,
    End,
    CapsLock,
    ScrollLock,
    NumLock,
    PrintScreen,
    Pause,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    F21,
    F22,
    F23,
    F24,
    F25,
    Kp0,
    Kp1,
    Kp2,
    Kp3,
    Kp4,
    Kp5,
    Kp6,
    Kp7,
    Kp8,
    Kp9,
    KpDecimal,
    KpDivide,
    KpMultiply,
    KpSubtract,
    KpAdd,
    KpEnter,
    KpEqual,
    LeftShift,
    LeftControl,
    LeftAlt,
    LeftSuper,
    RightShift,
    RightControl,
    RightAlt,
    RightSuper,
    Menu,
}

bitflags! {
    flags KeyModifiers: u8 {
        const SHIFT = 0x01,
        const CONTROL = 0x02,
        const ALT = 0x04,
        const SUPER = 0x08,
    }
}

/// Messages from the compositor and script to the constellation.
pub enum Msg {
    Exit,
    Failure(Failure),
    InitLoadUrl(Url),
    LoadComplete,
    FrameRect(PipelineId, SubpageId, Rect<f32>),
    LoadUrl(PipelineId, LoadData),
    ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
    Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
    PainterReady(PipelineId),
    ResizedWindow(WindowSizeData),
    KeyEvent(Key, KeyState, KeyModifiers),
    /// Requests that the constellation inform the compositor of the title of the pipeline
    /// immediately.
    GetPipelineTitle(PipelineId),
    /// Requests that the constellation inform the compositor of the a cursor change.
    SetCursor(Cursor),
    /// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode.
    MozBrowserEventMsg(PipelineId, SubpageId, MozBrowserEvent),
}

// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
pub enum MozBrowserEvent {
    /// Sent when the scroll position within a browser <iframe> changes.
    AsyncScroll,
    /// Sent when window.close() is called within a browser <iframe>.
    Close,
    /// Sent when a browser <iframe> tries to open a context menu. This allows  handling <menuitem> element available within the browser <iframe>'s content.
    ContextMenu,
    /// Sent when an error occurred while trying to load content within a browser <iframe>.
    Error,
    /// Sent when the favicon of a browser <iframe> changes.
    IconChange,
    /// Sent when the browser <iframe> has finished loading all its assets.
    LoadEnd,
    /// Sent when the browser <iframe> starts to load a new page.
    LoadStart,
    /// Sent when a browser <iframe>'s location changes.
    LocationChange(String),
    /// Sent when window.open() is called within a browser <iframe>.
    OpenWindow,
    /// Sent when the SSL state changes within a browser <iframe>.
    SecurityChange,
    /// Sent when alert(), confirm(), or prompt() is called within a browser <iframe>.
    ShowModalPrompt,
    /// Sent when the document.title changes within a browser <iframe>.
    TitleChange(String),
    /// Sent when an HTTP authentification is requested.
    UsernameAndPasswordRequired,
    /// Sent when a link to a search engine is found.
    OpenSearch,
}

impl MozBrowserEvent {
    pub fn name(&self) -> &'static str {
        match *self {
            MozBrowserEvent::AsyncScroll => "mozbrowserasyncscroll",
            MozBrowserEvent::Close => "mozbrowserclose",
            MozBrowserEvent::ContextMenu => "mozbrowsercontextmenu",
            MozBrowserEvent::Error => "mozbrowsererror",
            MozBrowserEvent::IconChange => "mozbrowsericonchange",
            MozBrowserEvent::LoadEnd => "mozbrowserloadend",
            MozBrowserEvent::LoadStart => "mozbrowserloadstart",
            MozBrowserEvent::LocationChange(_) => "mozbrowserlocationchange",
            MozBrowserEvent::OpenWindow => "mozbrowseropenwindow",
            MozBrowserEvent::SecurityChange => "mozbrowsersecuritychange",
            MozBrowserEvent::ShowModalPrompt => "mozbrowsershowmodalprompt",
            MozBrowserEvent::TitleChange(_) => "mozbrowsertitlechange",
            MozBrowserEvent::UsernameAndPasswordRequired => "mozbrowserusernameandpasswordrequired",
            MozBrowserEvent::OpenSearch => "mozbrowseropensearch"
        }
    }
    pub fn detail(&self) -> Option<String> {
        match *self {
            MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
            MozBrowserEvent::Error | MozBrowserEvent::IconChange | MozBrowserEvent::LoadEnd |
            MozBrowserEvent::LoadStart | MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange |
            MozBrowserEvent::ShowModalPrompt | MozBrowserEvent::UsernameAndPasswordRequired | MozBrowserEvent::OpenSearch => None,
            MozBrowserEvent::LocationChange(ref new_location) => Some(new_location.clone()),
            MozBrowserEvent::TitleChange(ref new_title) => Some(new_title.clone()),
        }
    }
}

/// Similar to net::resource_task::LoadData
/// can be passed to LoadUrl to load a page with GET/POST
/// parameters or headers
#[derive(Clone)]
pub struct LoadData {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub data: Option<Vec<u8>>,
}

impl LoadData {
    pub fn new(url: Url) -> LoadData {
        LoadData {
            url: url,
            method: Method::Get,
            headers: Headers::new(),
            data: None,
        }
    }
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub enum NavigationDirection {
    Forward,
    Back,
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct FrameId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct PipelineId(pub uint);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct SubpageId(pub uint);

// The type of pipeline exit. During complete shutdowns, pipelines do not have to
// release resources automatically released on process termination.
#[derive(Copy)]
pub enum PipelineExitType {
    PipelineOnly,
    Complete,
}
<commit_msg>Use u32 for PipelineId.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.

use geom::rect::Rect;
use geom::size::TypedSize2D;
use geom::scale_factor::ScaleFactor;
use hyper::header::Headers;
use hyper::method::Method;
use layers::geometry::DevicePixel;
use util::cursor::Cursor;
use util::geometry::{PagePx, ViewportPx};
use std::sync::mpsc::{channel, Sender, Receiver};
use url::Url;

#[derive(Clone)]
pub struct ConstellationChan(pub Sender<Msg>);

impl ConstellationChan {
    pub fn new() -> (Receiver<Msg>, ConstellationChan) {
        let (chan, port) = channel();
        (port, ConstellationChan(chan))
    }
}

#[derive(PartialEq, Eq, Copy, Debug)]
pub enum IFrameSandboxState {
    IFrameSandboxed,
    IFrameUnsandboxed
}

// We pass this info to various tasks, so it lives in a separate, cloneable struct.
#[derive(Clone, Copy)]
pub struct Failure {
    pub pipeline_id: PipelineId,
    pub parent_info: Option<(PipelineId, SubpageId)>,
}

#[derive(Copy)]
pub struct WindowSizeData {
    /// The size of the initial layout viewport, before parsing an
    /// http://www.w3.org/TR/css-device-adapt/#initial-viewport
    pub initial_viewport: TypedSize2D<ViewportPx, f32>,

    /// The "viewing area" in page px. See `PagePx` documentation for details.
    pub visible_viewport: TypedSize2D<PagePx, f32>,

    /// The resolution of the window in dppx, not including any "pinch zoom" factor.
    pub device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>,
}

#[derive(PartialEq, Eq, Copy, Clone)]
pub enum KeyState {
    Pressed,
    Released,
    Repeated,
}

//N.B. Based on the glutin key enum
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Key {
    Space,
    Apostrophe,
    Comma,
    Minus,
    Period,
    Slash,
    Num0,
    Num1,
    Num2,
    Num3,
    Num4,
    Num5,
    Num6,
    Num7,
    Num8,
    Num9,
    Semicolon,
    Equal,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z,
    LeftBracket,
    Backslash,
    RightBracket,
    GraveAccent,
    World1,
    World2,

    Escape,
    Enter,
    Tab,
    Backspace,
    Insert,
    Delete,
    Right,
    Left,
    Down,
    Up,
    PageUp,
    PageDown,
    Home,
    End,
    CapsLock,
    ScrollLock,
    NumLock,
    PrintScreen,
    Pause,
    F1,
    F2,
    F3,
    F4,
    F5,
    F6,
    F7,
    F8,
    F9,
    F10,
    F11,
    F12,
    F13,
    F14,
    F15,
    F16,
    F17,
    F18,
    F19,
    F20,
    F21,
    F22,
    F23,
    F24,
    F25,
    Kp0,
    Kp1,
    Kp2,
    Kp3,
    Kp4,
    Kp5,
    Kp6,
    Kp7,
    Kp8,
    Kp9,
    KpDecimal,
    KpDivide,
    KpMultiply,
    KpSubtract,
    KpAdd,
    KpEnter,
    KpEqual,
    LeftShift,
    LeftControl,
    LeftAlt,
    LeftSuper,
    RightShift,
    RightControl,
    RightAlt,
    RightSuper,
    Menu,
}

bitflags! {
    flags KeyModifiers: u8 {
        const SHIFT = 0x01,
        const CONTROL = 0x02,
        const ALT = 0x04,
        const SUPER = 0x08,
    }
}

/// Messages from the compositor and script to the constellation.
pub enum Msg {
    Exit,
    Failure(Failure),
    InitLoadUrl(Url),
    LoadComplete,
    FrameRect(PipelineId, SubpageId, Rect<f32>),
    LoadUrl(PipelineId, LoadData),
    ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option<SubpageId>, IFrameSandboxState),
    Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
    PainterReady(PipelineId),
    ResizedWindow(WindowSizeData),
    KeyEvent(Key, KeyState, KeyModifiers),
    /// Requests that the constellation inform the compositor of the title of the pipeline
    /// immediately.
    GetPipelineTitle(PipelineId),
    /// Requests that the constellation inform the compositor of the a cursor change.
    SetCursor(Cursor),
    /// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode.
    MozBrowserEventMsg(PipelineId, SubpageId, MozBrowserEvent),
}

// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
pub enum MozBrowserEvent {
    /// Sent when the scroll position within a browser <iframe> changes.
    AsyncScroll,
    /// Sent when window.close() is called within a browser <iframe>.
    Close,
    /// Sent when a browser <iframe> tries to open a context menu. This allows  handling <menuitem> element available within the browser <iframe>'s content.
    ContextMenu,
    /// Sent when an error occurred while trying to load content within a browser <iframe>.
    Error,
    /// Sent when the favicon of a browser <iframe> changes.
    IconChange,
    /// Sent when the browser <iframe> has finished loading all its assets.
    LoadEnd,
    /// Sent when the browser <iframe> starts to load a new page.
    LoadStart,
    /// Sent when a browser <iframe>'s location changes.
    LocationChange(String),
    /// Sent when window.open() is called within a browser <iframe>.
    OpenWindow,
    /// Sent when the SSL state changes within a browser <iframe>.
    SecurityChange,
    /// Sent when alert(), confirm(), or prompt() is called within a browser <iframe>.
    ShowModalPrompt,
    /// Sent when the document.title changes within a browser <iframe>.
    TitleChange(String),
    /// Sent when an HTTP authentification is requested.
    UsernameAndPasswordRequired,
    /// Sent when a link to a search engine is found.
    OpenSearch,
}

impl MozBrowserEvent {
    pub fn name(&self) -> &'static str {
        match *self {
            MozBrowserEvent::AsyncScroll => "mozbrowserasyncscroll",
            MozBrowserEvent::Close => "mozbrowserclose",
            MozBrowserEvent::ContextMenu => "mozbrowsercontextmenu",
            MozBrowserEvent::Error => "mozbrowsererror",
            MozBrowserEvent::IconChange => "mozbrowsericonchange",
            MozBrowserEvent::LoadEnd => "mozbrowserloadend",
            MozBrowserEvent::LoadStart => "mozbrowserloadstart",
            MozBrowserEvent::LocationChange(_) => "mozbrowserlocationchange",
            MozBrowserEvent::OpenWindow => "mozbrowseropenwindow",
            MozBrowserEvent::SecurityChange => "mozbrowsersecuritychange",
            MozBrowserEvent::ShowModalPrompt => "mozbrowsershowmodalprompt",
            MozBrowserEvent::TitleChange(_) => "mozbrowsertitlechange",
            MozBrowserEvent::UsernameAndPasswordRequired => "mozbrowserusernameandpasswordrequired",
            MozBrowserEvent::OpenSearch => "mozbrowseropensearch"
        }
    }
    pub fn detail(&self) -> Option<String> {
        match *self {
            MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
            MozBrowserEvent::Error | MozBrowserEvent::IconChange | MozBrowserEvent::LoadEnd |
            MozBrowserEvent::LoadStart | MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange |
            MozBrowserEvent::ShowModalPrompt | MozBrowserEvent::UsernameAndPasswordRequired | MozBrowserEvent::OpenSearch => None,
            MozBrowserEvent::LocationChange(ref new_location) => Some(new_location.clone()),
            MozBrowserEvent::TitleChange(ref new_title) => Some(new_title.clone()),
        }
    }
}

/// Similar to net::resource_task::LoadData
/// can be passed to LoadUrl to load a page with GET/POST
/// parameters or headers
#[derive(Clone)]
pub struct LoadData {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub data: Option<Vec<u8>>,
}

impl LoadData {
    pub fn new(url: Url) -> LoadData {
        LoadData {
            url: url,
            method: Method::Get,
            headers: Headers::new(),
            data: None,
        }
    }
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub enum NavigationDirection {
    Forward,
    Back,
}

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct FrameId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct WorkerId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct PipelineId(pub u32);

#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug)]
pub struct SubpageId(pub uint);

// The type of pipeline exit. During complete shutdowns, pipelines do not have to
// release resources automatically released on process termination.
#[derive(Copy)]
pub enum PipelineExitType {
    PipelineOnly,
    Complete,
}
<|endoftext|>


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

//! Convenience RNGs

pub mod adapter;

#[cfg(feature="std")] mod entropy;
#[doc(hidden)] pub mod jitter;
pub mod mock;   // Public so we don't export `StepRng` directly, making it a bit
                // more clear it is intended for testing.
#[cfg(feature="std")] #[doc(hidden)] pub mod os;
mod small;
mod std;
#[cfg(feature="std")] pub(crate) mod thread;

pub use self::jitter::{JitterRng, TimerError};
#[cfg(feature="std")] pub use self::entropy::EntropyRng;
#[cfg(feature="std")] pub use self::os::OsRng;

pub use self::small::SmallRng;
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;
<commit_msg>Add documentation to the rngs module<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Random number generators and adapters for common usage:
//!
//! - [`ThreadRng`], a fast, secure, auto-seeded thread-local generator
//! - [`StdRng`] and [`SmallRng`], algorithms to cover typical usage
//! - [`EntropyRng`], [`OsRng`] and [`JitterRng`] as entropy sources
//! - [`mock::StepRng`] as a simple counter for tests
//! - [`adapter::ReadRng`] to read from a file/stream
//!
//! # Background — Random number generators (RNGs)
//!
//! Computers are inherently deterministic, so to get *random* numbers one
//! either has to use a hardware generator or collect bits of *entropy* from
//! various sources (e.g. event timestamps, or jitter). This is a relatively
//! slow and complicated operation.
//!
//! Generally the operating system will collect some entropy, remove bias, and
//! use that to seed its own PRNG; [`OsRng`] provides an interface to this.
//! [`JitterRng`] is an entropy collector included with Rand that measures
//! jitter in the CPU execution time, and jitter in memory access time.
//! [`EntropyRng`] is a wrapper that uses the best entropy source that is
//! available.
//!
//! ## Pseudo-random number generators
//!
//! What is commonly used instead of "true" random number renerators, are
//! *pseudo-random number generators* (PRNGs), deterministic algorithms that
//! produce an infinite stream of pseudo-random numbers from a small random
//! seed. PRNGs are faster, and have better provable properties. The numbers
//! produced can be statistically of very high quality and can be impossible to
//! predict. (They can also have obvious correlations and be trivial to predict;
//! quality varies.)
//!
//! There are two different types of PRNGs: those developed for simulations
//! and statistics, and those developed for use in cryptography; the latter are
//! called Cryptographically Secure PRNGs (CSPRNG or CPRNG). Both types can
//! have good statistical quality but the latter also have to be impossible to
//! predict, even after seeing many previous output values. Rand provides a good
//! default algorithm from each class:
//!
//! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and
//!   good statistical quality.
//!   The current algorithm (plain Xorshift) unfortunately performs
//!   poorly in statistical quality test suites (TestU01 and PractRand) and will
//!   be replaced in the next major release.
//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security
//!   (based on reviews, maturity and usage). The current algorithm is HC-128,
//!   which is one of the recommendations by ECRYPT's eSTREAM project.
//!
//! The above PRNGs do not cover all use-cases; more algorithms can be found in
//! the [`prng` module], as well as in several other crates. For example, you
//! may wish a CSPRNG with significantly lower memory usage than [`StdRng`]
//! while being less concerned about performance, in which case [`ChaChaRng`]
//! is a good choice.
//!
//! One complexity is that the internal state of a PRNG must change with every
//! generated number. For APIs this generally means a mutable reference to the
//! state of the PRNG has to be passed around.
//!
//! A solution is [`ThreadRng`]. This is a thread-local implementation of
//! [`StdRng`] with automatic seeding on first use. It is the best choice if you
//! "just" want a convenient, secure, fast random number source. Use via the
//! [`thread_rng`] function, which gets a reference to the current thread's
//! local instance.
//!
//! ## Seeding
//!
//! As mentioned above, PRNGs require a random seed in order to produce random
//! output. This is especially important for CSPRNGs, which are still
//! deterministic algorithms, thus can only be secure if their seed value is
//! also secure. To seed a PRNG, use one of:
//!
//! - [`FromEntropy::from_entropy`]; this is the most convenient way to seed
//!   with fresh, secure random data.
//! - [`SeedableRng::from_rng`]; this allows seeding from another PRNG or
//!   from an entropy source such as [`EntropyRng`].
//! - [`SeedableRng::from_seed`]; this is mostly useful if you wish to be able
//!   to reproduce the output sequence by using a fixed seed. (Don't use
//!   [`StdRng`] or [`SmallRng`] in this case since different algorithms may be
//!   used by future versions of Rand; use an algorithm from the
//!   [`prng` module].)
//!
//! ## Conclusion
//!
//! - [`thread_rng`] is what you often want to use.
//! - If you want more control, flexibility, or better performance, use
//!   [`StdRng`], [`SmallRng`] or an algorithm from the [`prng` module].
//! - Use [`FromEntropy::from_entropy`] to seed new PRNGs.
//! - If you need reproducibility, use [`SeedableRng::from_seed`] combined with
//!   a named PRNG.
//!
//! More information and notes on cryptographic security can be found
//! in the [`prng` module].
//!
//! ## Examples
//!
//! Examples of seeding PRNGs:
//!
//! ```
//! use rand::prelude::*;
//! # use rand::Error;
//!
//! // StdRng seeded securely by the OS or local entropy collector:
//! let mut rng = StdRng::from_entropy();
//! # let v: u32 = rng.gen();
//!
//! // SmallRng seeded from thread_rng:
//! # fn try_inner() -> Result<(), Error> {
//! let mut rng = SmallRng::from_rng(thread_rng())?;
//! # let v: u32 = rng.gen();
//! # Ok(())
//! # }
//! # try_inner().unwrap();
//!
//! // SmallRng seeded by a constant, for deterministic results:
//! let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]; // byte array
//! let mut rng = SmallRng::from_seed(seed);
//! # let v: u32 = rng.gen();
//! ```
//!
//!
//! # Implementing custom RNGs
//!
//! If you want to implement custom RNG, see the [`rand_core`] crate. The RNG
//! will have to implement the [`RngCore`] trait, where the [`Rng`] trait is
//! build on top of.
//!
//! If the RNG needs seeding, also implement the [`SeedableRng`] trait.
//!
//! [`CryptoRng`] is a marker trait cryptographically secure PRNGs can
//! implement.
//!
//!
// This module:
//! [`ThreadRng`]: struct.ThreadRng.html
//! [`StdRng`]: struct.StdRng.html
//! [`SmallRng`]: struct.SmallRng.html
//! [`EntropyRng`]: struct.EntropyRng.html
//! [`OsRng`]: struct.OsRng.html
//! [`JitterRng`]: struct.JitterRng.html
// Other traits and functions:
//! [`rand_core`]: https://crates.io/crates/rand_core
//! [`prng` module]: ../prng/index.html
//! [`CryptoRng`]: ../trait.CryptoRng.html
//! [`FromEntropy`]: ../trait.FromEntropy.html
//! [`FromEntropy::from_entropy`]: ../trait.FromEntropy.html#tymethod.from_entropy
//! [`RngCore`]: ../trait.RngCore.html
//! [`Rng`]: ../trait.Rng.html
//! [`SeedableRng`]: ../trait.SeedableRng.html
//! [`SeedableRng::from_rng`]: ../trait.SeedableRng.html#tymethod.from_rng
//! [`SeedableRng::from_seed`]: ../trait.SeedableRng.html#tymethod.from_seed
//! [`thread_rng`]: ../fn.thread_rng.html
//! [`mock::StepRng`]: mock/struct.StepRng.html
//! [`adapter::ReadRng`]: adapter/struct.ReadRng.html
//! [`ChaChaRng`]: ../prng/chacha/struct.ChaChaRng.html

pub mod adapter;

#[cfg(feature="std")] mod entropy;
#[doc(hidden)] pub mod jitter;
pub mod mock;   // Public so we don't export `StepRng` directly, making it a bit
                // more clear it is intended for testing.
#[cfg(feature="std")] #[doc(hidden)] pub mod os;
mod small;
mod std;
#[cfg(feature="std")] pub(crate) mod thread;

pub use self::jitter::{JitterRng, TimerError};
#[cfg(feature="std")] pub use self::entropy::EntropyRng;
#[cfg(feature="std")] pub use self::os::OsRng;

pub use self::small::SmallRng;
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;
<|endoftext|>


<commit_before>//! # Getting started
//!
//! ```rust
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i))
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, transmute_ptr_to_ref))]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<commit_msg>Add a semicolon and set the test to not execute<commit_after>//! # Getting started
//!
//! ```rust,no_run
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, transmute_ptr_to_ref))]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<|endoftext|>


<commit_before>// Copyright 2015 Joe Neeman.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use aho_corasick::{Automaton, FullAcAutomaton};
use ascii_set::AsciiSet;
use memchr::memchr;

/// A set of chars that either is entirely ASCII or else contains every non-ASCII char.
#[derive(Clone, Debug, PartialEq)]
pub struct ExtAsciiSet {
    pub set: AsciiSet,
    pub contains_non_ascii: bool,
}

impl ExtAsciiSet {
    pub fn contains_byte(&self, b: u8) -> bool {
        if self.contains_non_ascii {
            b >= 128 || self.set.contains_byte(b)
        } else {
            self.set.contains_byte(b)
        }
    }

    pub fn complement(&self) -> ExtAsciiSet {
        ExtAsciiSet {
            set: self.set.complement(),
            contains_non_ascii: !self.contains_non_ascii,
        }
    }
}

#[derive(Clone, Debug)]
pub enum Search {
    Empty,
    AsciiChar(AsciiSet, usize),
    Byte(u8, usize),
    Lit(String, usize),
    Ac(FullAcAutomaton<String>, Vec<usize>),
    LoopUntil(ExtAsciiSet, usize),
}

/// An iterator that searchest for a given byte. The second position is the one after the matched
/// byte.
pub struct ByteIter<'a> {
    input: &'a str,
    byte: u8,
    pos: usize,
    state: usize,
}

impl<'a> ByteIter<'a> {
    pub fn new(s: &'a str, b: u8, state: usize) -> ByteIter<'a> {
        if b >= 128 {
            panic!("can only use ASCII bytes");
        } else {
            ByteIter {
                input: s,
                byte: b,
                pos: 0,
                state: state,
            }
        }
    }
}

impl<'a> Iterator for ByteIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        let ret =
        memchr(self.byte, &self.input.as_bytes()[self.pos..])
            .map(|pos| {
                self.pos += pos + 1;
                (self.pos - 1, self.pos, self.state)
            });
        ret
    }
}

/// An iterator over (possibly overlapping) matches of a string. The second position is the one
/// after the end of the match.
pub struct StrIter<'hay, 'needle> {
    input: &'hay str,
    needle: &'needle str,
    pos: usize,
    state: usize,
}

impl<'hay, 'needle> StrIter<'hay, 'needle> {
    pub fn new(hay: &'hay str, needle: &'needle str, state: usize) -> StrIter<'hay, 'needle> {
        StrIter {
            input: hay,
            needle: needle,
            pos: 0,
            state: state,
        }
    }
}

impl<'hay, 'needle> Iterator for StrIter<'hay, 'needle> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input[self.pos..].find(self.needle) {
            self.pos += pos;
            let ret = Some((self.pos, self.pos + self.needle.len(), self.state));
            self.pos += self.input.char_at(pos).len_utf8();
            ret
        } else {
            None
        }
    }
}

/// An iterator over all non-overlapping (but possibly empty) strings of chars belonging to a given
/// set. The second position is the one after the end of the match.
pub struct LoopIter<'a> {
    chars: ExtAsciiSet,
    input: &'a str,
    pos: usize,
    state: usize,
}

impl<'a> LoopIter<'a> {
    pub fn new(input: &'a str, chars: ExtAsciiSet, state: usize) -> LoopIter<'a> {
        LoopIter {
            chars: chars,
            input: input,
            pos: 0,
            state: state,
        }
    }
}

impl<'a> Iterator for LoopIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input.as_bytes()[self.pos..].iter()
                .position(|c| self.chars.contains_byte(*c)) {
            let ret = Some((self.pos, self.pos + pos, self.state));
            self.pos += pos + self.input.char_at(pos).len_utf8();
            ret
        } else {
            None
        }
    }
}

/// An iterator over all characters belonging to a certain ASCII set. The second position is the
/// position of the match.
pub struct AsciiSetIter<'a> {
    chars: AsciiSet,
    input: &'a str,
    pos: usize,
    state: usize,
}

impl<'a> AsciiSetIter<'a> {
    pub fn new(input: &'a str, chars: AsciiSet, state: usize) -> AsciiSetIter<'a> {
        AsciiSetIter {
            chars: chars,
            input: input,
            pos: 0,
            state: state,
        }
    }
}

impl<'a> Iterator for AsciiSetIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input.as_bytes()[self.pos..].iter()
                .position(|c| self.chars.contains_byte(*c)) {
            self.pos += pos + 1;
            Some((self.pos - 1, self.pos - 1, self.state))
        } else {
            None
        }
    }
}

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

    #[test]
    fn test_byte_iter() {
        let bi = ByteIter::new("abcaba", 'a' as u8, 5);
        assert_eq!(bi.collect::<Vec<_>>(),
            vec![(0, 1, 5), (3, 4, 5), (5, 6, 5)]);
    }

    #[test]
    fn test_str_iter() {
        let si = StrIter::new("abcaba", "ab", 5);
        assert_eq!(si.collect::<Vec<_>>(),
            vec![(0, 2, 5), (3, 5, 5)]);

        let si = StrIter::new("aaaa", "aa", 5);
        assert_eq!(si.collect::<Vec<_>>(),
            vec![(0, 2, 5), (1, 3, 5), (2, 4, 5)]);
    }

    #[test]
    fn test_loop_iter() {
        let cs = ExtAsciiSet {
            set: AsciiSet::from_chars("b".chars()),
            contains_non_ascii: false,
        };
        let li = LoopIter::new("baaababaa", cs, 5);
        assert_eq!(li.collect::<Vec<_>>(),
            vec![(0, 0, 5), (1, 4, 5), (5, 6, 5)]);
    }

    #[test]
    fn test_ascii_set_iter() {
        let cs = AsciiSet::from_chars("ac".chars());
        let asi = AsciiSetIter::new("abcba", cs, 5);
        assert_eq!(asi.collect::<Vec<_>>(),
            vec![(0, 0, 5), (2, 2, 5), (4, 4, 5)]);
    }
}
<commit_msg>Document searcher.<commit_after>// Copyright 2015 Joe Neeman.
//
// 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.

/*!
This module provides functions for quickly skipping through the haystack, looking for places that
might conceivably be the start of a match. Just about everything in this module is an iterator over
`(usize, usize, usize)` triples.

  - The first `usize` is the index where the match begun. If this does turn out to be a match, the
    DFA should report the match as beginning here. This should always be at a character boundary.
  - The second `usize` is the index that the DFA should begin matching from. This could be
    different from the first index because we might already know what state the DFA would be in
    if it encountered the prefix we found. In that case, there is no need for the DFA to go back
    and re-examine the prefix. This should always be at a character boundary.
  - The third `usize` is the state that the DFA should start in.
 */

use aho_corasick::{Automaton, FullAcAutomaton};
use ascii_set::AsciiSet;
use memchr::memchr;

/// A set of chars that either is entirely ASCII or else contains every non-ASCII char.
#[derive(Clone, Debug, PartialEq)]
pub struct ExtAsciiSet {
    pub set: AsciiSet,
    pub contains_non_ascii: bool,
}

impl ExtAsciiSet {
    pub fn contains_byte(&self, b: u8) -> bool {
        if self.contains_non_ascii {
            b >= 128 || self.set.contains_byte(b)
        } else {
            self.set.contains_byte(b)
        }
    }

    pub fn complement(&self) -> ExtAsciiSet {
        ExtAsciiSet {
            set: self.set.complement(),
            contains_non_ascii: !self.contains_non_ascii,
        }
    }
}

#[derive(Clone, Debug)]
pub enum Search {
    Empty,
    AsciiChar(AsciiSet, usize),
    Byte(u8, usize),
    Lit(String, usize),
    Ac(FullAcAutomaton<String>, Vec<usize>),
    LoopUntil(ExtAsciiSet, usize),
}

/// An iterator that searchest for a given byte. The second position is the one after the matched
/// byte.
pub struct ByteIter<'a> {
    input: &'a str,
    byte: u8,
    pos: usize,
    state: usize,
}

impl<'a> ByteIter<'a> {
    pub fn new(s: &'a str, b: u8, state: usize) -> ByteIter<'a> {
        if b >= 128 {
            panic!("can only use ASCII bytes");
        } else {
            ByteIter {
                input: s,
                byte: b,
                pos: 0,
                state: state,
            }
        }
    }
}

impl<'a> Iterator for ByteIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        let ret =
        memchr(self.byte, &self.input.as_bytes()[self.pos..])
            .map(|pos| {
                self.pos += pos + 1;
                (self.pos - 1, self.pos, self.state)
            });
        ret
    }
}

/// An iterator over (possibly overlapping) matches of a string. The second position is the one
/// after the end of the match.
pub struct StrIter<'hay, 'needle> {
    input: &'hay str,
    needle: &'needle str,
    pos: usize,
    state: usize,
}

impl<'hay, 'needle> StrIter<'hay, 'needle> {
    pub fn new(hay: &'hay str, needle: &'needle str, state: usize) -> StrIter<'hay, 'needle> {
        StrIter {
            input: hay,
            needle: needle,
            pos: 0,
            state: state,
        }
    }
}

impl<'hay, 'needle> Iterator for StrIter<'hay, 'needle> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input[self.pos..].find(self.needle) {
            self.pos += pos;
            let ret = Some((self.pos, self.pos + self.needle.len(), self.state));
            self.pos += self.input.char_at(pos).len_utf8();
            ret
        } else {
            None
        }
    }
}

/// An iterator over all non-overlapping (but possibly empty) strings of chars belonging to a given
/// set. The second position is the one after the end of the match.
pub struct LoopIter<'a> {
    chars: ExtAsciiSet,
    input: &'a str,
    pos: usize,
    state: usize,
}

impl<'a> LoopIter<'a> {
    pub fn new(input: &'a str, chars: ExtAsciiSet, state: usize) -> LoopIter<'a> {
        LoopIter {
            chars: chars,
            input: input,
            pos: 0,
            state: state,
        }
    }
}

impl<'a> Iterator for LoopIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input.as_bytes()[self.pos..].iter()
                .position(|c| self.chars.contains_byte(*c)) {
            let ret = Some((self.pos, self.pos + pos, self.state));
            self.pos += pos + self.input.char_at(pos).len_utf8();
            ret
        } else {
            None
        }
    }
}

/// An iterator over all characters belonging to a certain ASCII set. The second position is the
/// position of the match.
pub struct AsciiSetIter<'a> {
    chars: AsciiSet,
    input: &'a str,
    pos: usize,
    state: usize,
}

impl<'a> AsciiSetIter<'a> {
    pub fn new(input: &'a str, chars: AsciiSet, state: usize) -> AsciiSetIter<'a> {
        AsciiSetIter {
            chars: chars,
            input: input,
            pos: 0,
            state: state,
        }
    }
}

impl<'a> Iterator for AsciiSetIter<'a> {
    type Item = (usize, usize, usize);

    fn next(&mut self) -> Option<(usize, usize, usize)> {
        if let Some(pos) = self.input.as_bytes()[self.pos..].iter()
                .position(|c| self.chars.contains_byte(*c)) {
            self.pos += pos + 1;
            Some((self.pos - 1, self.pos - 1, self.state))
        } else {
            None
        }
    }
}

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

    #[test]
    fn test_byte_iter() {
        let bi = ByteIter::new("abcaba", 'a' as u8, 5);
        assert_eq!(bi.collect::<Vec<_>>(),
            vec![(0, 1, 5), (3, 4, 5), (5, 6, 5)]);
    }

    #[test]
    fn test_str_iter() {
        let si = StrIter::new("abcaba", "ab", 5);
        assert_eq!(si.collect::<Vec<_>>(),
            vec![(0, 2, 5), (3, 5, 5)]);

        let si = StrIter::new("aaaa", "aa", 5);
        assert_eq!(si.collect::<Vec<_>>(),
            vec![(0, 2, 5), (1, 3, 5), (2, 4, 5)]);
    }

    #[test]
    fn test_loop_iter() {
        let cs = ExtAsciiSet {
            set: AsciiSet::from_chars("b".chars()),
            contains_non_ascii: false,
        };
        let li = LoopIter::new("baaababaa", cs, 5);
        assert_eq!(li.collect::<Vec<_>>(),
            vec![(0, 0, 5), (1, 4, 5), (5, 6, 5)]);
    }

    #[test]
    fn test_ascii_set_iter() {
        let cs = AsciiSet::from_chars("ac".chars());
        let asi = AsciiSetIter::new("abcba", cs, 5);
        assert_eq!(asi.collect::<Vec<_>>(),
            vec![(0, 0, 5), (2, 2, 5), (4, 4, 5)]);
    }
}
<|endoftext|>


<commit_before>use grid::Grid;
use cell::Cell;

const NEIGHBORS_COUNT: usize = 8;

type Neighbors = [Option<usize>; NEIGHBORS_COUNT];

pub struct SquareGrid<C: Cell + Copy> {
    cells: Vec<C>,
    old_cells: Vec<C>,
    neighbors: Vec<Neighbors>,
    rows: i32,
    cols: i32,
}

impl<C: Cell + Copy> SquareGrid<C> {

    pub fn new(rows: i32, cols: i32, initial: C) -> Self {

        let len = (rows * cols) as usize;
        let cells = vec![initial; len];
        let old_cells = Vec::new();
        let neighbors = Vec::with_capacity(len);

        let mut grid = SquareGrid {
            cells: cells,
            old_cells: old_cells,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
        };
        grid.init_neighbors();

        grid
    }

    #[inline]
    fn offset(&self, i: i32, j: i32) -> usize {
        (i * self.cols + j) as usize
    }

    #[inline]
    fn from_offset(&self, offset: i32) -> (i32, i32) {
        let col = offset % self.cols;
        let row = (offset - col) / self.rows;
        (row, col)
    }

    /// 0 | 1 | 2
    /// 3 | x | 4
    /// 5 | 6 | 7
    fn init_neighbors(&mut self) {

        let len = self.cells.len() as i32;

        for offset in 0 .. len {
            let (i, j) = self.from_offset(offset);

            let neighbors_coords = [
                (i - 1, j - 1), (i - 1, j), (i - 1, j + 1),
                (i, j - 1),     /* x */     (i, j + 1),
                (i + 1, j - 1), (i + 1, j), (i + 1, j + 1)
            ];

            let mut neighbors = [None; NEIGHBORS_COUNT];

            for (serial, coord) in neighbors_coords.iter().enumerate() {
                let (x, y) = *coord;

                if x >= 0 && x < self.cols &&
                   y >= 0 && y < self.rows {
                    neighbors[serial] = Some(self.offset(x, y));
                }
            }

            self.neighbors.push(neighbors);
        }
    }

    fn neighbors_iter<'a>(&self,
                          cells: &'a Vec<C>,
                          neighbors: Neighbors)
        -> MooreSquareGridIterator<'a, C> {

        MooreSquareGridIterator {
            cells: cells,
            neighbors: neighbors,
            index: 0,
        }
    }
}

impl<C: Cell + Copy> Grid for SquareGrid<C> {

    fn step(&mut self) {
        self.old_cells = self.cells.clone();

        for (cell_no, cell) in self.old_cells.iter().enumerate() {
            let neighbors = self.neighbors[cell_no];
            let neighbors_iter = self.neighbors_iter(&self.old_cells, neighbors);
            self.cells[cell_no] = cell.step(neighbors_iter);
        }
    }
}

struct MooreSquareGridIterator<'a, C: Cell + 'a> {
    cells: &'a Vec<C>,
    neighbors: Neighbors,
    index: usize,
}

impl<'a, C: Cell> Iterator for MooreSquareGridIterator<'a, C> {
    type Item = Option<&'a C>;

    fn next(&mut self) -> Option<Self::Item> {
        let next = match self.index {
            i @ _  if i < NEIGHBORS_COUNT => {
                let maybe_index = self.neighbors[i];
                match maybe_index {
                    Some(index) => Some(Some(&self.cells[index])),
                    None => Some(None)
                }
            },
            _ => None
        };
        self.index += 1;

        next
    }
}

mod test {

    use cell::Cell;
    use grid::Grid;

    #[derive(Copy, Clone, PartialEq, Debug)]
    struct MooreTestCell;

    impl Cell for MooreTestCell {

        fn step<'a, I>(&self, neighbors: I) -> Self
            where I: Iterator<Item=Option<&'a Self>> {

            // Initial value should be copied
            // There should be 3 neighbors and 5 None values
            // Overall count of neighbors should be equal to NEIGHBORS_COUNT
            let mut total = 0;
            let mut none_cnt = 0;
            let mut neighbors_cnt = 0;
            for neighbor in neighbors {
                match neighbor {
                    None => {
                        none_cnt += 1;
                    },
                    Some(n) => {
                        assert_eq!(self, n);
                        neighbors_cnt += 1;
                    }
                };
                total += 1;
            }

            assert_eq!(total, super::NEIGHBORS_COUNT);
            assert_eq!(none_cnt, 5);
            assert_eq!(neighbors_cnt, 3);

            self.clone()
        }
    }

    #[test]
    fn test_neighbors() {
        let initial = MooreTestCell;
        let mut grid = super::SquareGrid::new(2, 2, initial);
        grid.step();
    }
}
<commit_msg>Phew.<commit_after>use grid::Grid;
use cell::Cell;

const NEIGHBORS_COUNT: usize = 8;

type Neighbors = [Option<usize>; NEIGHBORS_COUNT];

pub struct SquareGrid<C: Cell + Copy> {
    cells: Vec<C>,
    old_cells: Vec<C>,
    neighbors: Vec<Neighbors>,
    rows: i32,
    cols: i32,
}

impl<C: Cell + Copy> SquareGrid<C> {

    pub fn new(rows: i32, cols: i32, initial: C) -> Self {

        let len = (rows * cols) as usize;
        let cells = vec![initial; len];
        let old_cells = Vec::new();
        let neighbors = Vec::with_capacity(len);

        let mut grid = SquareGrid {
            cells: cells,
            old_cells: old_cells,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
        };
        grid.init_neighbors();

        grid
    }

    #[inline]
    fn offset(&self, i: i32, j: i32) -> usize {
        (i * self.cols + j) as usize
    }

    #[inline]
    fn from_offset(&self, offset: i32) -> (i32, i32) {
        let col = offset % self.cols;
        let row = (offset - col) / self.rows;
        (row, col)
    }

    /// 0 | 1 | 2
    /// 3 | x | 4
    /// 5 | 6 | 7
    fn init_neighbors(&mut self) {

        let len = self.cells.len() as i32;

        for offset in 0 .. len {
            let (i, j) = self.from_offset(offset);

            let neighbors_coords = [
                (i - 1, j - 1), (i - 1, j), (i - 1, j + 1),
                (i, j - 1),     /* x */     (i, j + 1),
                (i + 1, j - 1), (i + 1, j), (i + 1, j + 1)
            ];

            let mut neighbors = [None; NEIGHBORS_COUNT];

            for (serial, coord) in neighbors_coords.iter().enumerate() {
                let (x, y) = *coord;

                if x >= 0 && x < self.cols &&
                   y >= 0 && y < self.rows {
                    neighbors[serial] = Some(self.offset(x, y));
                }
            }

            self.neighbors.push(neighbors);
        }
    }

    fn neighbors_iter<'a>(&self,
                          cells: &'a Vec<C>,
                          neighbors: Neighbors)
        -> MooreSquareGridIterator<'a, C> {

        MooreSquareGridIterator {
            cells: cells,
            neighbors: neighbors,
            index: 0,
        }
    }
}

impl<C: Cell + Copy> Grid for SquareGrid<C> {

    fn step(&mut self) {
        self.old_cells = self.cells.clone();

        for (cell_no, cell) in self.old_cells.iter().enumerate() {
            let neighbors = self.neighbors[cell_no];
            let neighbors_iter = self.neighbors_iter(&self.old_cells, neighbors);
            self.cells[cell_no] = cell.step(neighbors_iter);
        }
    }
}

struct MooreSquareGridIterator<'a, C: Cell + 'a> {
    cells: &'a Vec<C>,
    neighbors: Neighbors,
    index: usize,
}

impl<'a, C: Cell> Iterator for MooreSquareGridIterator<'a, C> {
    type Item = Option<&'a C>;

    fn next(&mut self) -> Option<Self::Item> {
        let next = match self.index {
            i @ _  if i < NEIGHBORS_COUNT => {
                let maybe_index = self.neighbors[i];
                match maybe_index {
                    Some(index) => Some(Some(&self.cells[index])),
                    None => Some(None)
                }
            },
            _ => None
        };
        self.index += 1;

        next
    }
}

mod test {

    use cell::Cell;
    use grid::Grid;

    #[derive(Copy, Clone, PartialEq, Debug)]
    struct MooreTestCell;

    impl Cell for MooreTestCell {

        fn step<'a, I>(&self, neighbors: I) -> Self
            where I: Iterator<Item=Option<&'a Self>> {

            // Initial value should be copied
            // There should be 3 neighbors and 5 None values
            // Overall count of neighbors should be equal to NEIGHBORS_COUNT
            let mut total = 0;
            let mut none_cnt = 0;
            let mut neighbors_cnt = 0;
            for neighbor in neighbors {
                match neighbor {
                    None => {
                        none_cnt += 1;
                    },
                    Some(n) => {
                        assert_eq!(self, n);
                        neighbors_cnt += 1;
                    }
                };
                total += 1;
            }

            assert_eq!(total, super::NEIGHBORS_COUNT);
            assert_eq!(none_cnt, 5);
            assert_eq!(neighbors_cnt, 3);

            self.clone()
        }
    }

    #[test]
    fn test_neighbors() {
        let initial = MooreTestCell;
        let mut grid = super::SquareGrid::new(2, 2, initial);
        grid.step();
    }
}
<|endoftext|>


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

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 3,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 42365,
			pow: core::Proof::new(vec![
				0x5108b5, 0x6de3c4, 0xded539, 0x15d0e7a, 0x1b05bad, 0x24503fb, 0x420ee7a,
				0x5d905bb, 0x615571f, 0x631d3de, 0x740f1a2, 0x763f189, 0x778edd0, 0x916b09e,
				0x9679a4a, 0x99a7081, 0xad03e98, 0xd0f168c, 0xd878881, 0xda3166f, 0xe402699,
				0x10cac1ec, 0x11598a22, 0x11ad8968, 0x11b7f61a, 0x11c744f5, 0x129911ae,
				0x12d983c3, 0x14052a3c, 0x14464051, 0x16148155, 0x16f8577d, 0x18385648,
				0x18c25a31, 0x1ad7924c, 0x1b6c5079, 0x1c27837c, 0x1ce15e64, 0x1ecd7f12,
				0x1ef421bd, 0x1f5f0642, 0x1f97d069,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<commit_msg>Genesis update with correct nonce...<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 3,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 329,
			pow: core::Proof::new(vec![
				0x5108b5, 0x6de3c4, 0xded539, 0x15d0e7a, 0x1b05bad, 0x24503fb, 0x420ee7a,
				0x5d905bb, 0x615571f, 0x631d3de, 0x740f1a2, 0x763f189, 0x778edd0, 0x916b09e,
				0x9679a4a, 0x99a7081, 0xad03e98, 0xd0f168c, 0xd878881, 0xda3166f, 0xe402699,
				0x10cac1ec, 0x11598a22, 0x11ad8968, 0x11b7f61a, 0x11c744f5, 0x129911ae,
				0x12d983c3, 0x14052a3c, 0x14464051, 0x16148155, 0x16f8577d, 0x18385648,
				0x18c25a31, 0x1ad7924c, 0x1b6c5079, 0x1c27837c, 0x1ce15e64, 0x1ecd7f12,
				0x1ef421bd, 0x1f5f0642, 0x1f97d069,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<|endoftext|>