<commit_before>use syn;
use syn::*;
use quote::Tokens;

use ::util::*;

#[derive(Default, Debug)]
struct EnumAttrs {
    name: Option<String>,
    description: Option<String>,
}

impl EnumAttrs {
    fn from_input(input: &DeriveInput) -> EnumAttrs {
        let mut res = EnumAttrs::default();

        // Check attributes for name and description.
        if let Some(items) = get_graphl_attr(&input.attrs) {
            for item in items {
                if let Some(val) = keyed_item_value(item, "name", true) {
                    res.name = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "description", true) {
                    res.description = Some(val);
                    continue;
                }
                panic!(format!(
                    "Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
                    item));
            }
        }
        res
    }
}

#[derive(Default)]
struct EnumVariantAttrs {
    name: Option<String>,
    description: Option<String>,
    deprecation: Option<String>,
}

impl EnumVariantAttrs {
    fn from_input(variant: &Variant) -> EnumVariantAttrs {
        let mut res = EnumVariantAttrs::default();

        // Check attributes for name and description.
        if let Some(items) = get_graphl_attr(&variant.attrs) {
            for item in items {
                if let Some(val) = keyed_item_value(item, "name", true) {
                    res.name = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "description", true) {
                    res.description = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "deprecated", true) {
                    res.deprecation = Some(val);
                    continue;
                }
                panic!(format!(
                    "Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
                    item));
            }
        }
        res
    }
}

pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
    let variants = match ast.body {
        Body::Enum(ref var) => var,
        Body::Struct(_) => {
            panic!("#[derive(GraphlQLEnum)] may only be applied to enums, not to structs");
        },
    };

    // Parse attributes.
    let ident = &ast.ident;
    let attrs = EnumAttrs::from_input(ast);
    let name = attrs.name.unwrap_or(ast.ident.to_string());

    let mut values = Vec::<Tokens>::new();
    let mut resolves = Vec::<Tokens>::new();
    let mut from_inputs = Vec::<Tokens>::new();
    let mut to_inputs = Vec::<Tokens>::new();

    for variant in variants {
        if variant.data != VariantData::Unit {
            panic!(format!(
                "Invalid enum variant {}.\nGraphQL enums may only contain unit variants.",
                variant.ident));
        }
        let vattrs = EnumVariantAttrs::from_input(variant);
        let vident = &variant.ident;

        // Build value.
        let name = vattrs.name.unwrap_or(variant.ident.to_string());
        let descr = match vattrs.description {
            Some(s) => quote!{ Some(#s.to_string())  },
            None => quote!{ None },
        };
        let depr = match vattrs.deprecation {
            Some(s) => quote!{ Some(#s.to_string())  },
            None => quote!{ None },
        };
        let value = quote!{
            ::juniper::meta::EnumValue{
                name: #name.to_string(),
                description: #descr,
                deprecation_reason: #depr,
            },
        };
        values.push(value);

        // Build resolve match clause.
        let resolve = quote!{
            &#ident::#vident => ::juniper::Value::String(#name.to_string()),
        };
        resolves.push(resolve);

        // Buil from_input clause.
        let from_input = quote!{
            Some(#name) => Some(#ident::#vident),
        };
        from_inputs.push(from_input);

        // Buil to_input clause.
        let to_input = quote!{
            &#ident::#vident =>
                ::juniper::InputValue::string(#name.to_string()),
        };
        to_inputs.push(to_input);
    };

    quote! {
        impl ::juniper::GraphQLType for #ident {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some(#name)
            }

            fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> {
                registry.build_enum_type::<#ident>(&[
                    #(#values)*
                ])
                .into_meta()
            }

            fn resolve(&self, _: Option<&[::juniper::Selection]>, _: &::juniper::Executor<Self::Context>) -> ::juniper::Value {
                match self {
                    #(#resolves)*
                }
            }
        }

        impl ::juniper::FromInputValue for #ident {
            fn from(v: &::juniper::InputValue) -> Option<#ident> {
                match v.as_enum_value().or_else(|| v.as_string_value()) {
                    #(#from_inputs)*
                    _ => None,
                }
            }
        }

        impl ::juniper::ToInputValue for #ident {
            fn to(&self) -> ::juniper::InputValue {
                match self {
                    #(#to_inputs)*
                }
            }
        }
    }
}
<commit_msg>Use more descriptive variant variable names for enum deriving<commit_after>use syn;
use syn::*;
use quote::Tokens;

use ::util::*;

#[derive(Default, Debug)]
struct EnumAttrs {
    name: Option<String>,
    description: Option<String>,
}

impl EnumAttrs {
    fn from_input(input: &DeriveInput) -> EnumAttrs {
        let mut res = EnumAttrs::default();

        // Check attributes for name and description.
        if let Some(items) = get_graphl_attr(&input.attrs) {
            for item in items {
                if let Some(val) = keyed_item_value(item, "name", true) {
                    res.name = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "description", true) {
                    res.description = Some(val);
                    continue;
                }
                panic!(format!(
                    "Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
                    item));
            }
        }
        res
    }
}

#[derive(Default)]
struct EnumVariantAttrs {
    name: Option<String>,
    description: Option<String>,
    deprecation: Option<String>,
}

impl EnumVariantAttrs {
    fn from_input(variant: &Variant) -> EnumVariantAttrs {
        let mut res = EnumVariantAttrs::default();

        // Check attributes for name and description.
        if let Some(items) = get_graphl_attr(&variant.attrs) {
            for item in items {
                if let Some(val) = keyed_item_value(item, "name", true) {
                    res.name = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "description", true) {
                    res.description = Some(val);
                    continue;
                }
                if let Some(val) = keyed_item_value(item, "deprecated", true) {
                    res.deprecation = Some(val);
                    continue;
                }
                panic!(format!(
                    "Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
                    item));
            }
        }
        res
    }
}

pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
    let variants = match ast.body {
        Body::Enum(ref var) => var,
        Body::Struct(_) => {
            panic!("#[derive(GraphlQLEnum)] may only be applied to enums, not to structs");
        },
    };

    // Parse attributes.
    let ident = &ast.ident;
    let attrs = EnumAttrs::from_input(ast);
    let name = attrs.name.unwrap_or(ast.ident.to_string());

    let mut values = Vec::<Tokens>::new();
    let mut resolves = Vec::<Tokens>::new();
    let mut from_inputs = Vec::<Tokens>::new();
    let mut to_inputs = Vec::<Tokens>::new();

    for variant in variants {
        if variant.data != VariantData::Unit {
            panic!(format!(
                "Invalid enum variant {}.\nGraphQL enums may only contain unit variants.",
                variant.ident));
        }
        let var_attrs = EnumVariantAttrs::from_input(variant);
        let var_ident = &variant.ident;

        // Build value.
        let name = var_attrs.name.unwrap_or(variant.ident.to_string());
        let descr = match var_attrs.description {
            Some(s) => quote!{ Some(#s.to_string())  },
            None => quote!{ None },
        };
        let depr = match var_attrs.deprecation {
            Some(s) => quote!{ Some(#s.to_string())  },
            None => quote!{ None },
        };
        let value = quote!{
            ::juniper::meta::EnumValue{
                name: #name.to_string(),
                description: #descr,
                deprecation_reason: #depr,
            },
        };
        values.push(value);

        // Build resolve match clause.
        let resolve = quote!{
            &#ident::#var_ident => ::juniper::Value::String(#name.to_string()),
        };
        resolves.push(resolve);

        // Buil from_input clause.
        let from_input = quote!{
            Some(#name) => Some(#ident::#var_ident),
        };
        from_inputs.push(from_input);

        // Buil to_input clause.
        let to_input = quote!{
            &#ident::#var_ident =>
                ::juniper::InputValue::string(#name.to_string()),
        };
        to_inputs.push(to_input);
    };

    quote! {
        impl ::juniper::GraphQLType for #ident {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some(#name)
            }

            fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> {
                registry.build_enum_type::<#ident>(&[
                    #(#values)*
                ])
                .into_meta()
            }

            fn resolve(&self, _: Option<&[::juniper::Selection]>, _: &::juniper::Executor<Self::Context>) -> ::juniper::Value {
                match self {
                    #(#resolves)*
                }
            }
        }

        impl ::juniper::FromInputValue for #ident {
            fn from(v: &::juniper::InputValue) -> Option<#ident> {
                match v.as_enum_value().or_else(|| v.as_string_value()) {
                    #(#from_inputs)*
                    _ => None,
                }
            }
        }

        impl ::juniper::ToInputValue for #ident {
            fn to(&self) -> ::juniper::InputValue {
                match self {
                    #(#to_inputs)*
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use mio;
use mio::tcp::*;
use mio::{TryRead, TryWrite};
use serde::ser::Serialize;
use serde::de::Deserialize;
use spki_sexp as sexp;
use std::fmt;
use std::marker::PhantomData;
use std::collections::VecDeque;

use super::{ChainRepl,ChainReplMsg};
use data::{OpResp, Operation, PeerMsg, ReplicationMessage, Seqno, Buf};
use config::Epoch;
use crexp_client_proto::messages::{ClientReq,ClientResp};
use hybrid_clocks::{Timestamp, WallT};

const NL: u8 = '\n' as u8;
const DEFAULT_BUFSZ: usize = 1 << 12;

pub trait Encoder<T> {
    fn encode(&self, s: T) -> Vec<u8>;
}

pub trait Reader<T> {
    fn feed(&mut self, slice: &[u8]);
    fn new(mio::Token) -> Self;

    fn process<P: Protocol<Recv=T>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool ;
}

pub trait Protocol : fmt::Debug{
    type Send;
    type Recv;
 }

pub trait UpstreamEvents {
    fn hello_downstream(&mut self, source: mio::Token, at: Timestamp<WallT>, epoch: Epoch);
    fn operation(&mut self, source: mio::Token, epoch: Epoch, seqno: Seqno, op: Buf);
    fn client_request(&mut self, source: mio::Token, op: Buf);
    fn commit(&mut self, source: mio::Token, epoch: Epoch, seqno: Seqno);
}

pub trait DownstreamEvents {
    fn okay(&mut self, epoch: Epoch, seqno: Seqno, data: Option<Buf>);
    fn hello_i_want(&mut self, at: Timestamp<WallT>, seqno: Seqno);
    fn error(&mut self, epoch: Epoch, seqno: Seqno, data: String);
}

pub trait LineConnEvents : UpstreamEvents + DownstreamEvents {
}

#[derive(Debug)]
pub struct PeerClientProto;
impl Protocol for PeerClientProto {
    type Send = OpResp;
    type Recv = ReplicationMessage;
}

#[derive(Debug)]
pub struct LineConn<T, P> {
    socket: TcpStream,
    sock_status: mio::EventSet,
    token: mio::Token,
    read_eof: bool,
    failed: bool,
    write_buf: Vec<u8>,
    read_buf: Vec<u8>,
    codec: T,
    proto: PhantomData<P>,
}

impl<T, P> LineConn<T, P>
    where P: Protocol,
          T: fmt::Debug
{
    fn new(socket: TcpStream, token: mio::Token, codec: T) -> LineConn<T, P> {
        trace!("New client connection {:?} from {:?}",
               token,
               socket.local_addr());
        LineConn {
            socket: socket,
            sock_status: mio::EventSet::none(),
            token: token,
            write_buf: Vec::with_capacity(DEFAULT_BUFSZ).into(),
            read_buf: Vec::with_capacity(DEFAULT_BUFSZ).into(),
            read_eof: false,
            failed: false,
            codec: codec,
            proto: PhantomData,
        }
    }

    pub fn initialize(&self, event_loop: &mut mio::EventLoop<ChainRepl>, token: mio::Token) {
        event_loop.register_opt(&self.socket,
                                token,
                                mio::EventSet::readable(),
                                mio::PollOpt::edge() | mio::PollOpt::oneshot())
                  .expect("event loop initialize");
    }

    // Event updates arrive here
    pub fn handle_event(&mut self,
                        _event_loop: &mut mio::EventLoop<ChainRepl>,
                        events: mio::EventSet) {
        self.sock_status.insert(events);
        trace!("LineConn::handle_event: {:?}; this time: {:?}; now: {:?}",
               self.socket.peer_addr(),
               events,
               self.sock_status);
    }
}

impl<T, P> LineConn<T, P>
    where P: Protocol,
          T: Reader<P::Recv> + Encoder<P::Send> + fmt::Debug
{
    pub fn process_rules<E: LineConnEvents>(&mut self,
                                                 event_loop: &mut mio::EventLoop<ChainRepl>,
                                                 events: &mut E)
                                                 -> bool {

        if self.sock_status.is_readable() {
            self.read();
            self.sock_status.remove(mio::EventSet::readable());
        }

        let changed = self.process_buffer(events);

        if self.sock_status.is_writable() {
            self.write();
            self.sock_status.remove(mio::EventSet::writable());
        }

        if !self.should_close() {
            self.reinitialize(event_loop)
        }
        changed
    }

    fn process_buffer<E: LineConnEvents>(&mut self, events: &mut E) -> bool {
        self.codec.process::<P, E>(self.token, events)
    }

    fn read(&mut self) {
        match self.socket.try_read_buf(&mut self.read_buf) {
            Ok(Some(0)) => {
                debug!("{:?}: EOF!", self.socket.peer_addr());
                self.read_eof = true
            }
            Ok(Some(n)) => {
                trace!("{:?}: Read {}bytes", self.socket.peer_addr(), n);
                self.codec.feed(&self.read_buf);
                self.read_buf.clear();
            }
            Ok(None) => {
                trace!("{:?}: Noop!", self.socket.peer_addr());
            }
            Err(e) => {
                error!("got an error trying to read; err={:?}", e);
                self.failed = true;
            }
        }
    }

    fn write(&mut self) {
        match self.socket.try_write(&mut self.write_buf) {
            Ok(Some(n)) => {
                trace!("{:?}: Wrote {} of {} in buffer",
                       self.socket.peer_addr(),
                       n,
                       self.write_buf.len());
                self.write_buf = self.write_buf[n..].to_vec().into();
                trace!("{:?}: Now {:?}b",
                       self.socket.peer_addr(),
                       self.write_buf.len());
            }
            Ok(None) => {
                trace!("Write unready");
            }
            Err(e) => {
                error!("got an error trying to write; err={:?}", e);
                self.failed = true;
            }
        }
    }

    fn reinitialize(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>) {
        let mut flags = mio::EventSet::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::EventSet::writable());
        }
        trace!("Registering {:?} with {:?}", self, flags);

        event_loop.reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
                  .expect("EventLoop#reinitialize")
    }

    pub fn should_close(&self) -> bool {
        trace!("Closed? failed: {:?}; read_eof:{:?}; write_empty: {:?}",
               self.failed,
               self.read_eof,
               self.write_buf.is_empty());
        self.failed || (self.read_eof && self.write_buf.is_empty())
    }

    // Per item to output
    pub fn response(&mut self, s: P::Send) {
        let chunk = self.codec.encode(s);
        self.write_buf.extend(chunk);
    }
}

#[derive(Debug)]
pub struct SexpPeer {
    token: mio::Token,
    packets: sexp::Packetiser,
}

impl SexpPeer {
    pub fn fresh(token: mio::Token) -> SexpPeer {
        SexpPeer {
            token: token,
            packets: sexp::Packetiser::new(),
        }
    }
}

impl<T: Serialize> Encoder<T> for SexpPeer {
    fn encode(&self, s: T) -> Vec<u8> {
        sexp::as_bytes(&s).expect("Encode json response").into()
    }
}

impl Reader<ReplicationMessage> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=ReplicationMessage>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                ReplicationMessage { epoch, ts, msg: PeerMsg::HelloDownstream } => events.hello_downstream(token, ts, epoch),
                ReplicationMessage { epoch, ts, msg: PeerMsg::Prepare(seqno, op) } => events.operation(token, epoch, seqno, op.into()),
                ReplicationMessage { epoch, ts, msg: PeerMsg::CommitTo(seqno) } => events.commit(token, epoch, seqno),
            }
            changed = true;
        }

        changed
    }
}

impl Reader<Operation> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=Operation>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            trace!("{:?}: Read buffer: {:?}", self.token, msg);
            match msg {
                ReplicationMessage { epoch, ts, msg: PeerMsg::HelloDownstream } => events.hello_downstream(token, ts, epoch),
                ReplicationMessage { epoch, ts, msg: PeerMsg::Prepare(seqno, op) } => events.operation(token, epoch, seqno, op.into()),
                ReplicationMessage { epoch, ts, msg: PeerMsg::CommitTo(seqno) } => events.commit(token, epoch, seqno),
            }
            changed = true;
        }

        changed
    }
}

impl Reader<OpResp> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=OpResp>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                OpResp::Ok(epoch, seqno, data) => events.okay(epoch, seqno, data),
                OpResp::HelloIWant(ts, seqno) => events.hello_i_want(ts, seqno),
                OpResp::Err(epoch, seqno, data) => events.error(epoch, seqno, data),
            }
            changed = true;
        }

        changed
    }
}

impl Reader<ClientReq> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=ClientReq>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                ClientReq::Publish(data)  => events.client_request(token, data.into()),
            }
            changed = true;
        }

        changed
    }
}

impl<P> LineConn<SexpPeer, P>
    where P: Protocol,
          SexpPeer: Reader<P::Recv> + Encoder<P::Send> + fmt::Debug
{
    pub fn peer(socket: TcpStream, token: mio::Token) -> LineConn<SexpPeer, P> {
        Self::new(socket, token, SexpPeer::fresh(token))
    }
}

#[derive(Debug)]
pub struct ClientProto;
impl Protocol for ClientProto {
    type Send = ClientResp;
    type Recv = ClientReq;
}
<commit_msg>GC unused impl.<commit_after>use mio;
use mio::tcp::*;
use mio::{TryRead, TryWrite};
use serde::ser::Serialize;
use serde::de::Deserialize;
use spki_sexp as sexp;
use std::fmt;
use std::marker::PhantomData;
use std::collections::VecDeque;

use super::{ChainRepl,ChainReplMsg};
use data::{OpResp, Operation, PeerMsg, ReplicationMessage, Seqno, Buf};
use config::Epoch;
use crexp_client_proto::messages::{ClientReq,ClientResp};
use hybrid_clocks::{Timestamp, WallT};

const NL: u8 = '\n' as u8;
const DEFAULT_BUFSZ: usize = 1 << 12;

pub trait Encoder<T> {
    fn encode(&self, s: T) -> Vec<u8>;
}

pub trait Reader<T> {
    fn feed(&mut self, slice: &[u8]);
    fn new(mio::Token) -> Self;

    fn process<P: Protocol<Recv=T>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool ;
}

pub trait Protocol : fmt::Debug{
    type Send;
    type Recv;
 }

pub trait UpstreamEvents {
    fn hello_downstream(&mut self, source: mio::Token, at: Timestamp<WallT>, epoch: Epoch);
    fn operation(&mut self, source: mio::Token, epoch: Epoch, seqno: Seqno, op: Buf);
    fn client_request(&mut self, source: mio::Token, op: Buf);
    fn commit(&mut self, source: mio::Token, epoch: Epoch, seqno: Seqno);
}

pub trait DownstreamEvents {
    fn okay(&mut self, epoch: Epoch, seqno: Seqno, data: Option<Buf>);
    fn hello_i_want(&mut self, at: Timestamp<WallT>, seqno: Seqno);
    fn error(&mut self, epoch: Epoch, seqno: Seqno, data: String);
}

pub trait LineConnEvents : UpstreamEvents + DownstreamEvents {
}

#[derive(Debug)]
pub struct PeerClientProto;
impl Protocol for PeerClientProto {
    type Send = OpResp;
    type Recv = ReplicationMessage;
}

#[derive(Debug)]
pub struct LineConn<T, P> {
    socket: TcpStream,
    sock_status: mio::EventSet,
    token: mio::Token,
    read_eof: bool,
    failed: bool,
    write_buf: Vec<u8>,
    read_buf: Vec<u8>,
    codec: T,
    proto: PhantomData<P>,
}

impl<T, P> LineConn<T, P>
    where P: Protocol,
          T: fmt::Debug
{
    fn new(socket: TcpStream, token: mio::Token, codec: T) -> LineConn<T, P> {
        trace!("New client connection {:?} from {:?}",
               token,
               socket.local_addr());
        LineConn {
            socket: socket,
            sock_status: mio::EventSet::none(),
            token: token,
            write_buf: Vec::with_capacity(DEFAULT_BUFSZ).into(),
            read_buf: Vec::with_capacity(DEFAULT_BUFSZ).into(),
            read_eof: false,
            failed: false,
            codec: codec,
            proto: PhantomData,
        }
    }

    pub fn initialize(&self, event_loop: &mut mio::EventLoop<ChainRepl>, token: mio::Token) {
        event_loop.register_opt(&self.socket,
                                token,
                                mio::EventSet::readable(),
                                mio::PollOpt::edge() | mio::PollOpt::oneshot())
                  .expect("event loop initialize");
    }

    // Event updates arrive here
    pub fn handle_event(&mut self,
                        _event_loop: &mut mio::EventLoop<ChainRepl>,
                        events: mio::EventSet) {
        self.sock_status.insert(events);
        trace!("LineConn::handle_event: {:?}; this time: {:?}; now: {:?}",
               self.socket.peer_addr(),
               events,
               self.sock_status);
    }
}

impl<T, P> LineConn<T, P>
    where P: Protocol,
          T: Reader<P::Recv> + Encoder<P::Send> + fmt::Debug
{
    pub fn process_rules<E: LineConnEvents>(&mut self,
                                                 event_loop: &mut mio::EventLoop<ChainRepl>,
                                                 events: &mut E)
                                                 -> bool {

        if self.sock_status.is_readable() {
            self.read();
            self.sock_status.remove(mio::EventSet::readable());
        }

        let changed = self.process_buffer(events);

        if self.sock_status.is_writable() {
            self.write();
            self.sock_status.remove(mio::EventSet::writable());
        }

        if !self.should_close() {
            self.reinitialize(event_loop)
        }
        changed
    }

    fn process_buffer<E: LineConnEvents>(&mut self, events: &mut E) -> bool {
        self.codec.process::<P, E>(self.token, events)
    }

    fn read(&mut self) {
        match self.socket.try_read_buf(&mut self.read_buf) {
            Ok(Some(0)) => {
                debug!("{:?}: EOF!", self.socket.peer_addr());
                self.read_eof = true
            }
            Ok(Some(n)) => {
                trace!("{:?}: Read {}bytes", self.socket.peer_addr(), n);
                self.codec.feed(&self.read_buf);
                self.read_buf.clear();
            }
            Ok(None) => {
                trace!("{:?}: Noop!", self.socket.peer_addr());
            }
            Err(e) => {
                error!("got an error trying to read; err={:?}", e);
                self.failed = true;
            }
        }
    }

    fn write(&mut self) {
        match self.socket.try_write(&mut self.write_buf) {
            Ok(Some(n)) => {
                trace!("{:?}: Wrote {} of {} in buffer",
                       self.socket.peer_addr(),
                       n,
                       self.write_buf.len());
                self.write_buf = self.write_buf[n..].to_vec().into();
                trace!("{:?}: Now {:?}b",
                       self.socket.peer_addr(),
                       self.write_buf.len());
            }
            Ok(None) => {
                trace!("Write unready");
            }
            Err(e) => {
                error!("got an error trying to write; err={:?}", e);
                self.failed = true;
            }
        }
    }

    fn reinitialize(&mut self, event_loop: &mut mio::EventLoop<ChainRepl>) {
        let mut flags = mio::EventSet::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::EventSet::writable());
        }
        trace!("Registering {:?} with {:?}", self, flags);

        event_loop.reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
                  .expect("EventLoop#reinitialize")
    }

    pub fn should_close(&self) -> bool {
        trace!("Closed? failed: {:?}; read_eof:{:?}; write_empty: {:?}",
               self.failed,
               self.read_eof,
               self.write_buf.is_empty());
        self.failed || (self.read_eof && self.write_buf.is_empty())
    }

    // Per item to output
    pub fn response(&mut self, s: P::Send) {
        let chunk = self.codec.encode(s);
        self.write_buf.extend(chunk);
    }
}

#[derive(Debug)]
pub struct SexpPeer {
    token: mio::Token,
    packets: sexp::Packetiser,
}

impl SexpPeer {
    pub fn fresh(token: mio::Token) -> SexpPeer {
        SexpPeer {
            token: token,
            packets: sexp::Packetiser::new(),
        }
    }
}

impl<T: Serialize> Encoder<T> for SexpPeer {
    fn encode(&self, s: T) -> Vec<u8> {
        sexp::as_bytes(&s).expect("Encode json response").into()
    }
}

impl Reader<ReplicationMessage> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=ReplicationMessage>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                ReplicationMessage { epoch, ts, msg: PeerMsg::HelloDownstream } => events.hello_downstream(token, ts, epoch),
                ReplicationMessage { epoch, ts, msg: PeerMsg::Prepare(seqno, op) } => events.operation(token, epoch, seqno, op.into()),
                ReplicationMessage { epoch, ts, msg: PeerMsg::CommitTo(seqno) } => events.commit(token, epoch, seqno),
            }
            changed = true;
        }

        changed
    }
}

impl Reader<OpResp> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=OpResp>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                OpResp::Ok(epoch, seqno, data) => events.okay(epoch, seqno, data),
                OpResp::HelloIWant(ts, seqno) => events.hello_i_want(ts, seqno),
                OpResp::Err(epoch, seqno, data) => events.error(epoch, seqno, data),
            }
            changed = true;
        }

        changed
    }
}

impl Reader<ClientReq> for SexpPeer {
    fn new(token: mio::Token) -> SexpPeer {
        Self::fresh(token)
    }
    fn feed(&mut self, slice: &[u8]) {
        self.packets.feed(slice)
    }

    fn process<P: Protocol<Recv=ClientReq>, E: LineConnEvents>(&mut self, token: mio::Token, events: &mut E) -> bool {
        let mut changed = false;
        // trace!("{:?}: Read buffer: {:?}", self.socket.peer_addr(), self.read_buf);
        while let Some(msg) = self.packets.take().expect("Pull packet") {
            match msg {
                ClientReq::Publish(data)  => events.client_request(token, data.into()),
            }
            changed = true;
        }

        changed
    }
}

impl<P> LineConn<SexpPeer, P>
    where P: Protocol,
          SexpPeer: Reader<P::Recv> + Encoder<P::Send> + fmt::Debug
{
    pub fn peer(socket: TcpStream, token: mio::Token) -> LineConn<SexpPeer, P> {
        Self::new(socket, token, SexpPeer::fresh(token))
    }
}

#[derive(Debug)]
pub struct ClientProto;
impl Protocol for ClientProto {
    type Send = ClientResp;
    type Recv = ClientReq;
}
<|endoftext|>


<commit_before>use std::env;
use std::io::Read;
use std::ascii::AsciiExt;
use std::default::Default;
use std::collections::BTreeMap;

use url::Url;
use tendril::SliceExt;
use hyper::header::UserAgent;
use hyper::Client as HyperClient;
use hyper::client::RedirectPolicy;
use hyper::client::Response as HttpResponse;
use hyper::status::StatusCode;
use robotparser::RobotFileParser;
use html5ever::tokenizer::Tokenizer;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::create_redis_pool;
use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_8;

pub use self::page::Page;
mod page;

const MAMAN_ENV: &'static str = "MAMAN_ENV";

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Url>,
    pub unvisited_urls: Vec<Url>,
    pub extra: Vec<String>,
    pub env: String,
    pub limit: isize,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(base_url: Url, limit: isize, extra: Vec<String>) -> Spider<'a> {
        let maman_env = env::var(&MAMAN_ENV.to_string()).unwrap_or("development".to_string());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts =
            SidekiqClientOpts { namespace: Some(maman_env.to_string()), ..Default::default() };
        let sidekiq = SidekiqClient::new(create_redis_pool(), client_opts);
        Spider {
            base_url: base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            extra: extra,
            sidekiq: sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit: limit,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in page.urls.iter() {
            self.unvisited_urls.push(u.clone());
        }
        match self.sidekiq.push(page.to_job()) {
            Err(err) => {
                println!("SidekiqClient push failed: {}", err);
            }
            Ok(_) => {}
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref()) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref()) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        tok.feed(document.to_tendril());
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            if let Some(page) = Spider::read_response(page_url, response, self.extra.clone()) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser.can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url,
                     mut response: HttpResponse,
                     extra: Vec<String>)
                     -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for h in response.headers.iter() {
                headers.insert(h.name().to_ascii_lowercase(), h.value_string());
            }
        }
        let mut document = vec![];
        let _ = response.read_to_end(&mut document);
        match UTF_8.decode(&document, DecoderTrap::Ignore) {
            Ok(doc) => {
                let page = Page::new(page_url.clone(), doc.to_string(), headers.clone(), extra);
                let read = Spider::read_page(page, &doc).unwrap();
                Some(read)
            }
            Err(_) => None,
        }
    }

    fn load_url(url: &str) -> Option<HttpResponse> {
        let mut client = HyperClient::new();
        client.set_redirect_policy(RedirectPolicy::FollowNone);
        let request = client.get(url).header(UserAgent(maman_user_agent!().to_owned()));
        match request.send() {
            Ok(response) => {
                match response.status {
                    StatusCode::Ok | StatusCode::NotModified => Some(response),
                    _ => None,
                }
            }
            Err(_) => None,
        }
    }
}
<commit_msg>Print sidekiq error to stderr<commit_after>use std::env;
use std::io::{Read, Write};
use std::ascii::AsciiExt;
use std::default::Default;
use std::collections::BTreeMap;

use url::Url;
use tendril::SliceExt;
use hyper::header::UserAgent;
use hyper::Client as HyperClient;
use hyper::client::RedirectPolicy;
use hyper::client::Response as HttpResponse;
use hyper::status::StatusCode;
use robotparser::RobotFileParser;
use html5ever::tokenizer::Tokenizer;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::create_redis_pool;
use encoding::{Encoding, DecoderTrap};
use encoding::all::UTF_8;

pub use self::page::Page;
mod page;

const MAMAN_ENV: &'static str = "MAMAN_ENV";

macro_rules! println_err(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
    );

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Url>,
    pub unvisited_urls: Vec<Url>,
    pub extra: Vec<String>,
    pub env: String,
    pub limit: isize,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(base_url: Url, limit: isize, extra: Vec<String>) -> Spider<'a> {
        let maman_env = env::var(&MAMAN_ENV.to_string()).unwrap_or("development".to_string());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts =
            SidekiqClientOpts { namespace: Some(maman_env.to_string()), ..Default::default() };
        let sidekiq = SidekiqClient::new(create_redis_pool(), client_opts);
        Spider {
            base_url: base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            extra: extra,
            sidekiq: sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit: limit,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in page.urls.iter() {
            self.unvisited_urls.push(u.clone());
        }
        match self.sidekiq.push(page.to_job()) {
            Err(err) => {
                println_err!("SidekiqClient push failed: {}", err);
            }
            Ok(_) => {}
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref()) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref()) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        tok.feed(document.to_tendril());
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            if let Some(page) = Spider::read_response(page_url, response, self.extra.clone()) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser.can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url,
                     mut response: HttpResponse,
                     extra: Vec<String>)
                     -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for h in response.headers.iter() {
                headers.insert(h.name().to_ascii_lowercase(), h.value_string());
            }
        }
        let mut document = vec![];
        let _ = response.read_to_end(&mut document);
        match UTF_8.decode(&document, DecoderTrap::Ignore) {
            Ok(doc) => {
                let page = Page::new(page_url.clone(), doc.to_string(), headers.clone(), extra);
                let read = Spider::read_page(page, &doc).unwrap();
                Some(read)
            }
            Err(_) => None,
        }
    }

    fn load_url(url: &str) -> Option<HttpResponse> {
        let mut client = HyperClient::new();
        client.set_redirect_policy(RedirectPolicy::FollowNone);
        let request = client.get(url).header(UserAgent(maman_user_agent!().to_owned()));
        match request.send() {
            Ok(response) => {
                match response.status {
                    StatusCode::Ok | StatusCode::NotModified => Some(response),
                    _ => None,
                }
            }
            Err(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>use {MESSAGES, REFRESH_KEY};

use channel::{Archive, ArchiveServer};
use discordown;

use iron::prelude::*;
use iron::status;

use handlebars_iron::handlebars::*;

use url::Url;

use serde_json;

use discord::model::Message;

use std::path::PathBuf;
use std::fs::{self, File};
use std::collections::HashMap;

// FIXME: .<@!123> and the like aren't accounted for
//         <@!123>. and the like are account for, however

pub fn _refresh() {
  let archives = fs::read_dir("archives").unwrap();
  for server in archives {
    let server = server.unwrap().path();
    if server.is_dir() {
      let server_id: u64 = server.file_stem().unwrap().to_string_lossy().parse().unwrap();
      for channel in fs::read_dir(server).unwrap() {
        let channel = channel.unwrap().path();
        let channel_id: u64 = channel.file_stem().unwrap().to_string_lossy().parse().unwrap();
        add_messages(channel, server_id, channel_id);
      }
    }
  }
}

pub fn refresh(req: &mut Request) -> IronResult<Response> {
  let query: HashMap<_, _> = req.url.as_ref().query_pairs().collect();
  let key = query.get("key").map(ToOwned::to_owned).unwrap_or_else(Default::default);
  if key != *REFRESH_KEY {
    return Ok(Response::with(("Get outta here", status::Forbidden)));
  }
  _refresh();
  Ok(Response::with(("We gucci", status::Ok)))
}

fn find_id(part: &mut String, index: usize) -> Option<(u64, usize)> {
  let end = part.find('>').unwrap_or_else(|| part.len() - 1);
  let id: u64 = match part[index..end].parse() {
    Ok(u) => u,
    Err(_) => return None
  };
  Some((id, end))
}

fn parse_user(server: &ArchiveServer, message: &Message, part: &mut String, index: usize) -> bool {
  let (id, end) = match find_id(part, index) { Some(x) => x, None => return false };
  let name = match server.members.iter().find(|m| m.user.id.0 == id) {
    Some(member) => member.nick.as_ref().unwrap_or(&member.user.name),
    None => match message.mentions.iter().find(|m| m.id.0 == id) {
      Some(mention) => &mention.name,
      None => return false
    }
  };
  *part = format!("@{}{}",
    html_escape(name),
    html_escape(&part[end + 1..]));
  true
}

fn parse_user_mention(server: &ArchiveServer, message: &Message, part: &mut String) -> bool {
  parse_user(server, message, part, 2)
}

fn parse_user_nick_mention(server: &ArchiveServer, message: &Message, part: &mut String) -> bool {
  parse_user(server, message, part, 3)
}

fn parse_channel_mention(server: &ArchiveServer, part: &mut String) -> bool {
let (id, end) = match find_id(part, 2) { Some(x) => x, None => return false };
  match server.channels.iter().find(|c| c.id.0 == id) {
    Some(channel) => {
      *part = format!("#{}{}",
        html_escape(&channel.name),
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn parse_role_mention(server: &ArchiveServer, part: &mut String) -> bool {
  let (id, end) = match find_id(part, 3) { Some(x) => x, None => return false };
  match server.roles.iter().find(|r| r.id.0 == id) {
    Some(role) => {
      let name = if role.name == "@everyone" { role.name.clone() } else { format!("@{}", role.name) };
      *part = format!("{}{}",
        html_escape(&name),
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn parse_custom_emoji(part: &mut String) -> bool {
  match part[2..].find(':') {
    Some(index) => {
      let end = part[2 + index..].find('>').map(|x| x + 2 + index).unwrap_or_else(|| part.len() - 1);
      let id: u64 = match part[3 + index..end].parse() {
        Ok(u) => u,
        Err(_) => return false
      };
      *part = format!("{}",
        html_escape(&part[2..index]),
        id,
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn add_messages(channel: PathBuf, server_id: u64, channel_id: u64) {
  let f = File::open(channel).unwrap();
  let mut archive: Archive = serde_json::from_reader(f).unwrap();
  for message in &mut archive.messages {
    if let Some(member) = archive.server.members.iter().find(|mem| mem.user.id == message.author.id) {
      if let Some(ref nick) = member.nick {
        message.author.name = nick.clone();
      }
    }
    let mut parts: Vec<String> = message.content.split(' ').map(ToOwned::to_owned).collect();
    for part in &mut parts {
      let escaped = if part.starts_with("<@!") {
        parse_user_nick_mention(&archive.server, message, part)
      } else if part.starts_with("<@&") {
        parse_role_mention(&archive.server, part)
      } else if part.starts_with("<@") {
        parse_user_mention(&archive.server, message, part)
      } else if part.starts_with("<#") {
        parse_channel_mention(&archive.server, part)
      } else if part.starts_with("<:") {
        parse_custom_emoji(part)
      } else {
        false
      };

      if !escaped {
        *part = html_escape(part);
      }

      if let Ok(url) = Url::parse(part) {
        if url.has_host() {
          *part = format!("{url}", url=part)
        }
      }
    }
    message.content = discordown::parse(&parts.join(" "));
  }
  let mut msgs = MESSAGES.write().unwrap();
  let server = msgs.entry(server_id).or_insert_with(Default::default);
  server.insert(channel_id, archive);
}
<commit_msg>fix(archive_viewer): check for tags in the middle of words<commit_after>use {MESSAGES, REFRESH_KEY};

use channel::{Archive, ArchiveServer};
use discordown;

use iron::prelude::*;
use iron::status;

use handlebars_iron::handlebars::*;

use url::Url;

use serde_json;

use discord::model::Message;

use std::path::PathBuf;
use std::fs::{self, File};
use std::collections::HashMap;

pub fn _refresh() {
  let archives = fs::read_dir("archives").unwrap();
  for server in archives {
    let server = server.unwrap().path();
    if server.is_dir() {
      let server_id: u64 = server.file_stem().unwrap().to_string_lossy().parse().unwrap();
      for channel in fs::read_dir(server).unwrap() {
        let channel = channel.unwrap().path();
        let channel_id: u64 = channel.file_stem().unwrap().to_string_lossy().parse().unwrap();
        add_messages(channel, server_id, channel_id);
      }
    }
  }
}

pub fn refresh(req: &mut Request) -> IronResult<Response> {
  let query: HashMap<_, _> = req.url.as_ref().query_pairs().collect();
  let key = query.get("key").map(ToOwned::to_owned).unwrap_or_else(Default::default);
  if key != *REFRESH_KEY {
    return Ok(Response::with(("Get outta here", status::Forbidden)));
  }
  _refresh();
  Ok(Response::with(("We gucci", status::Ok)))
}

fn find_id(part: &mut String, index: usize, start: usize) -> Option<(u64, usize)> {
  let end = part.find('>').unwrap_or_else(|| part.len() - 1);
  let id: u64 = match part[start + index..end].parse() {
    Ok(u) => u,
    Err(_) => return None
  };
  Some((id, end))
}

fn parse_user(server: &ArchiveServer, message: &Message, part: &mut String, index: usize, start: usize) -> bool {
  let (id, end) = match find_id(part, index, start) { Some(x) => x, None => return false };
  let name = match server.members.iter().find(|m| m.user.id.0 == id) {
    Some(member) => member.nick.as_ref().unwrap_or(&member.user.name),
    None => match message.mentions.iter().find(|m| m.id.0 == id) {
      Some(mention) => &mention.name,
      None => return false
    }
  };
  *part = format!("{}@{}{}",
    html_escape(&part[..start]),
    html_escape(name),
    html_escape(&part[end + 1..]));
  true
}

fn parse_user_mention(server: &ArchiveServer, message: &Message, part: &mut String, start: usize) -> bool {
  parse_user(server, message, part, 2, start)
}

fn parse_user_nick_mention(server: &ArchiveServer, message: &Message, part: &mut String, start: usize) -> bool {
  parse_user(server, message, part, 3, start)
}

fn parse_channel_mention(server: &ArchiveServer, part: &mut String, start: usize) -> bool {
let (id, end) = match find_id(part, 2, start) { Some(x) => x, None => return false };
  match server.channels.iter().find(|c| c.id.0 == id) {
    Some(channel) => {
      *part = format!("{}#{}{}",
        html_escape(&part[..start]),
        html_escape(&channel.name),
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn parse_role_mention(server: &ArchiveServer, part: &mut String, start: usize) -> bool {
  let (id, end) = match find_id(part, 3, start) { Some(x) => x, None => return false };
  match server.roles.iter().find(|r| r.id.0 == id) {
    Some(role) => {
      let name = if role.name == "@everyone" { role.name.clone() } else { format!("@{}", role.name) };
      *part = format!("{}{}{}",
        html_escape(&part[..start]),
        html_escape(&name),
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn parse_custom_emoji(part: &mut String, start: usize) -> bool {
  match part[start + 2..].find(':') {
    Some(index) => {
      let end = part[start + 2 + index..].find('>').map(|x| x + 2 + start + index).unwrap_or_else(|| part.len() - 1);
      let id: u64 = match part[start + 3 + index..end].parse() {
        Ok(u) => u,
        Err(_) => return false
      };
      *part = format!("{}{}",
        html_escape(&part[..start]),
        html_escape(&part[start + 2..start + index]),
        id,
        html_escape(&part[end + 1..]));
      true
    },
    None => false
  }
}

fn add_messages(channel: PathBuf, server_id: u64, channel_id: u64) {
  let f = File::open(channel).unwrap();
  let mut archive: Archive = serde_json::from_reader(f).unwrap();
  for message in &mut archive.messages {
    if let Some(member) = archive.server.members.iter().find(|mem| mem.user.id == message.author.id) {
      if let Some(ref nick) = member.nick {
        message.author.name = nick.clone();
      }
    }
    let mut parts: Vec<String> = message.content.split(' ').map(ToOwned::to_owned).collect();
    for part in &mut parts {
      let escaped = if let Some(start_index) = part.find('<') {
        let tag = part[start_index..].to_owned();
        if tag.starts_with("<@!") {
          parse_user_nick_mention(&archive.server, message, part, start_index)
        } else if tag.starts_with("<@&") {
          parse_role_mention(&archive.server, part, start_index)
        } else if tag.starts_with("<@") {
          parse_user_mention(&archive.server, message, part, start_index)
        } else if tag.starts_with("<#") {
          parse_channel_mention(&archive.server, part, start_index)
        } else if tag.starts_with("<:") {
          parse_custom_emoji(part, start_index)
        } else {
          false
        }
      } else {
        false
      };

      if !escaped {
        *part = html_escape(part);
      }

      if let Ok(url) = Url::parse(part) {
        if url.has_host() {
          *part = format!("{url}", url=part)
        }
      }
    }
    message.content = discordown::parse(&parts.join(" "));
  }
  let mut msgs = MESSAGES.write().unwrap();
  let server = msgs.entry(server_id).or_insert_with(Default::default);
  server.insert(channel_id, archive);
}
<|endoftext|>


<commit_before>use std::cmp::Ordering::Equal;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::fs::File;
use std::io::{BufRead, BufReader, Write, Result};
use std::path::Path;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input_filename: &Path, output_filename: &Path) -> Result<u32> {
    let reader = BufReader::with_capacity(2048, File::open(input_filename).unwrap());
    let mut count = 0;
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
                count += 1;
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
                count += 1;
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
                count += 1;
            },
            _ => () // Ignore bad lines
        }
    }
    try!(write_tally(&results, output_filename));
    Ok(count)
}

fn write_tally(results: &HashMap<String, TeamResult>, output_filename: &Path) -> Result<()> {
    let mut v: Vec<(&String, u32, &TeamResult, u32)> = Vec::new();
    for (team, r) in results.iter() {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        v.push((team, games, r, points));
    }
    // Sort by points, then games played, in reverse order.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.1.cmp(&(b.1)).reverse(),
                  other => other
              });
    let mut f = try!(File::create(output_filename));
    try!(writeln!(&mut f, "{:30} | MP |  W |  D |  L |  P", "Team"));
    for &(ref team, games, r, points) in v.iter() {
        try!(writeln!(&mut f, "{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                      team, games, r.wins, r.draws, r.losses, points));
    }
    Ok(())
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    match results.entry(team) {
        Entry::Vacant(entry) => {
            let mut tr = TeamResult::new();
            tr.add_game_result(result);
            entry.insert(tr);
        }
        Entry::Occupied(mut entry) => {
            (*entry.get_mut()).add_game_result(result);
        }
    };
}
<commit_msg>tournament: Use `Entry#or_insert` in `add_game_result`<commit_after>use std::cmp::Ordering::Equal;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Write, Result};
use std::path::Path;

enum GameResult {
    Win,
    Draw,
    Loss
}

struct TeamResult {
    wins: u32,
    draws: u32,
    losses: u32,
}

impl TeamResult {
    fn new() -> TeamResult {
        TeamResult { wins: 0, draws: 0, losses: 0 }
    }
    fn add_game_result(&mut self, result: GameResult) {
        match result {
            GameResult::Win => self.wins += 1,
            GameResult::Draw => self.draws += 1,
            GameResult::Loss => self.losses += 1,
        }
    }
}

pub fn tally(input_filename: &Path, output_filename: &Path) -> Result<u32> {
    let reader = BufReader::with_capacity(2048, File::open(input_filename).unwrap());
    let mut count = 0;
    let mut results: HashMap<String, TeamResult> = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<&str> = line.trim_right().split(';').collect();
        if parts.len() != 3 { continue; }
        let team1 = parts[0];
        let team2 = parts[1];
        let outcome = parts[2];
        match outcome {
            "win" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Win);
                add_game_result(&mut results, team2.to_string(), GameResult::Loss);
                count += 1;
            },
            "draw" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Draw);
                add_game_result(&mut results, team2.to_string(), GameResult::Draw);
                count += 1;
            },
            "loss" => {
                add_game_result(&mut results, team1.to_string(), GameResult::Loss);
                add_game_result(&mut results, team2.to_string(), GameResult::Win);
                count += 1;
            },
            _ => () // Ignore bad lines
        }
    }
    try!(write_tally(&results, output_filename));
    Ok(count)
}

fn write_tally(results: &HashMap<String, TeamResult>, output_filename: &Path) -> Result<()> {
    let mut v: Vec<(&String, u32, &TeamResult, u32)> = Vec::new();
    for (team, r) in results.iter() {
        let games = r.wins + r.draws + r.losses;
        let points = r.wins * 3 + r.draws;
        v.push((team, games, r, points));
    }
    // Sort by points, then games played, in reverse order.
    v.sort_by(|a, b|
              match a.3.cmp(&(b.3)).reverse() {
                  Equal => a.1.cmp(&(b.1)).reverse(),
                  other => other
              });
    let mut f = try!(File::create(output_filename));
    try!(writeln!(&mut f, "{:30} | MP |  W |  D |  L |  P", "Team"));
    for &(ref team, games, r, points) in v.iter() {
        try!(writeln!(&mut f, "{:30} | {:2} | {:2} | {:2} | {:2} | {:2}",
                      team, games, r.wins, r.draws, r.losses, points));
    }
    Ok(())
}

fn add_game_result(results: &mut HashMap<String, TeamResult>, team: String, result: GameResult) {
    results.entry(team).or_insert(TeamResult::new()).add_game_result(result);
}
<|endoftext|>


<commit_before>use serde_json;

use std::collections::BTreeMap;

use storage::StorageValue;
use events::Milliseconds;
use crypto::{hash, PublicKey, Hash};

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StoredConfiguration {
    pub previous_cfg_hash: Hash,
    pub actual_from: u64,
    /// List of validator's consensus and service public keys.
    pub validators: Vec<(PublicKey, PublicKey)>,
    pub consensus: ConsensusConfig,
    pub services: BTreeMap<String, serde_json::Value>,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ConsensusConfig {
    pub round_timeout: Milliseconds,
    pub status_timeout: Milliseconds,
    pub peers_timeout: Milliseconds,
    pub propose_timeout: Milliseconds,
    pub txs_block_limit: u32,
}

impl Default for ConsensusConfig {
    fn default() -> Self {
        ConsensusConfig {
            round_timeout: 3000,
            propose_timeout: 500,
            status_timeout: 5000,
            peers_timeout: 10000,
            txs_block_limit: 1000,
        }
    }
}

impl StoredConfiguration {
    pub fn try_serialize(&self) -> Result<Vec<u8>, serde_json::error::Error> {
        serde_json::to_vec(&self)
    }

    pub fn try_deserialize(serialized: &[u8]) -> Result<StoredConfiguration, serde_json::error::Error> {
        let config = serde_json::from_slice(serialized)?;
        // TODO: FIXME.
        Ok(config)
    }
}

impl StorageValue for StoredConfiguration {
    fn serialize(self) -> Vec<u8> {
        self.try_serialize().unwrap()
    }

    fn deserialize(v: Vec<u8>) -> Self {
        StoredConfiguration::try_deserialize(&v).unwrap()
    }

    fn hash(&self) -> Hash {
        let vec_bytes = self.try_serialize().unwrap();
        hash(&vec_bytes)
    }

}
<commit_msg>Add check for keys duplication<commit_after>use serde_json;

use std::collections::{BTreeMap, HashSet};

use storage::StorageValue;
use events::Milliseconds;
use crypto::{hash, PublicKey, Hash};

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct StoredConfiguration {
    pub previous_cfg_hash: Hash,
    pub actual_from: u64,
    /// List of validator's consensus and service public keys.
    pub validators: Vec<(PublicKey, PublicKey)>,
    pub consensus: ConsensusConfig,
    pub services: BTreeMap<String, serde_json::Value>,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ConsensusConfig {
    pub round_timeout: Milliseconds,
    pub status_timeout: Milliseconds,
    pub peers_timeout: Milliseconds,
    pub propose_timeout: Milliseconds,
    pub txs_block_limit: u32,
}

impl Default for ConsensusConfig {
    fn default() -> Self {
        ConsensusConfig {
            round_timeout: 3000,
            propose_timeout: 500,
            status_timeout: 5000,
            peers_timeout: 10000,
            txs_block_limit: 1000,
        }
    }
}

impl StoredConfiguration {
    pub fn try_serialize(&self) -> Result<Vec<u8>, serde_json::error::Error> {
        serde_json::to_vec(&self)
    }

    pub fn try_deserialize(serialized: &[u8]) -> Result<StoredConfiguration, serde_json::error::Error> {
        let config: StoredConfiguration = serde_json::from_slice(serialized)?;

        // Check that there are no duplicated keys.
        let mut keys: HashSet<_> = config.validators.iter().map(|x| x.0).collect();
        keys.extend(config.validators.iter().map(|x| x.1));
        if keys.len() != config.validators.len() * 2 {
            panic!("Duplicated validator keys are found");
        }

        Ok(config)
    }
}

impl StorageValue for StoredConfiguration {
    fn serialize(self) -> Vec<u8> {
        self.try_serialize().unwrap()
    }

    fn deserialize(v: Vec<u8>) -> Self {
        StoredConfiguration::try_deserialize(&v).unwrap()
    }

    fn hash(&self) -> Hash {
        let vec_bytes = self.try_serialize().unwrap();
        hash(&vec_bytes)
    }

}
<|endoftext|>


<commit_before>// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
//
// Example 2-8: Mutual Attraction
extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::app(model, event, view).run();
}

struct Model {
    movers: Vec<Mover>,
}

struct Mover {
    position: Point2<f32>,
    velocity: Vector2<f32>,
    acceleration: Vector2<f32>,
    mass: f32,
}

impl Mover {
    fn new(m: f32, x: f32, y: f32) -> Self {
        let mass = m;
        let position = pt2(x, y);
        let velocity = vec2(0.0, 0.0);
        let acceleration = vec2(0.0, 0.0);
        Mover {
            position,
            velocity,
            acceleration,
            mass,
        }
    }

    fn apply_force(&mut self, force: Vector2<f32>) {
        let f = force / self.mass;
        self.acceleration += f;
    }

    fn update(&mut self) {
        self.velocity += self.acceleration;
        self.position += self.velocity;
        self.acceleration *= 0.0;
    }

    fn attract(&self, m: &Mover) -> Vector2<f32> {
        let mut force = self.position - m.position; // Calculate direction of force
        let mut distance = force.magnitude(); // Distance between objects
        distance = distance.max(5.0).min(25.0); // Limiting the distance to eliminate "extreme" results for very cose or very far object
        force = force.normalize(); // Normalize vector (distance doesn't matter, we just want this vector for direction)
        let g = 0.4;
        let strength = (g * self.mass * m.mass) / (distance * distance); // Calculate gravitational force magnitude
        force * strength // Get force vector --> magnitude * direction
    }

    fn display(&self, draw: &app::Draw) {
        draw.ellipse()
            .xy(self.position)
            .w_h(self.mass * 24.0, self.mass * 24.0)
            .rgba(0.0, 0.0, 0.0, 0.5);
    }
}

fn model(app: &App) -> Model {
    let rect = Rect::from_w_h(640.0, 360.0);
    let _window = app.new_window()
        .with_dimensions(rect.w() as u32, rect.h() as u32)
        .build()
        .unwrap();

    let movers = (0..1000)
        .map(|_| {
            Mover::new(
                random_range(0.1f32, 2.0),
                random_range(rect.left(), rect.right()),
                random_range(rect.top(), rect.bottom()),
            )
        })
        .collect();

    Model { movers }
}

fn event(_app: &App, mut m: Model, event: Event) -> Model {
    // update gets called just before view every frame
    if let Event::Update(_update) = event {
        for i in 0..m.movers.len() {
            for j in 0..m.movers.len() {
                if i != j {
                    let force = m.movers[j].attract(&m.movers[i]);
                    m.movers[i].apply_force(force);
                }
            }
            m.movers[i].update();
        }
    }
    m
}

fn view(app: &App, m: &Model, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();
    draw.background().color(WHITE);

    // Draw movers
    for mover in &m.movers {
        mover.display(&draw);
    }

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}
<commit_msg>Fix bug in nature of code ch2 n8 where random_range values reversed<commit_after>// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
//
// Example 2-8: Mutual Attraction
extern crate nannou;

use nannou::prelude::*;

fn main() {
    nannou::app(model, event, view).run();
}

struct Model {
    movers: Vec<Mover>,
}

struct Mover {
    position: Point2<f32>,
    velocity: Vector2<f32>,
    acceleration: Vector2<f32>,
    mass: f32,
}

impl Mover {
    fn new(m: f32, x: f32, y: f32) -> Self {
        let mass = m;
        let position = pt2(x, y);
        let velocity = vec2(0.0, 0.0);
        let acceleration = vec2(0.0, 0.0);
        Mover {
            position,
            velocity,
            acceleration,
            mass,
        }
    }

    fn apply_force(&mut self, force: Vector2<f32>) {
        let f = force / self.mass;
        self.acceleration += f;
    }

    fn update(&mut self) {
        self.velocity += self.acceleration;
        self.position += self.velocity;
        self.acceleration *= 0.0;
    }

    fn attract(&self, m: &Mover) -> Vector2<f32> {
        let mut force = self.position - m.position; // Calculate direction of force
        let mut distance = force.magnitude(); // Distance between objects
        distance = distance.max(5.0).min(25.0); // Limiting the distance to eliminate "extreme" results for very cose or very far object
        force = force.normalize(); // Normalize vector (distance doesn't matter, we just want this vector for direction)
        let g = 0.4;
        let strength = (g * self.mass * m.mass) / (distance * distance); // Calculate gravitational force magnitude
        force * strength // Get force vector --> magnitude * direction
    }

    fn display(&self, draw: &app::Draw) {
        draw.ellipse()
            .xy(self.position)
            .w_h(self.mass * 24.0, self.mass * 24.0)
            .rgba(0.0, 0.0, 0.0, 0.5);
    }
}

fn model(app: &App) -> Model {
    let rect = Rect::from_w_h(640.0, 360.0);
    let _window = app.new_window()
        .with_dimensions(rect.w() as u32, rect.h() as u32)
        .build()
        .unwrap();

    let movers = (0..1000)
        .map(|_| {
            Mover::new(
                random_range(0.1f32, 2.0),
                random_range(rect.left(), rect.right()),
                random_range(rect.bottom(), rect.top()),
            )
        })
        .collect();

    Model { movers }
}

fn event(_app: &App, mut m: Model, event: Event) -> Model {
    // update gets called just before view every frame
    if let Event::Update(_update) = event {
        for i in 0..m.movers.len() {
            for j in 0..m.movers.len() {
                if i != j {
                    let force = m.movers[j].attract(&m.movers[i]);
                    m.movers[i].apply_force(force);
                }
            }
            m.movers[i].update();
        }
    }
    m
}

fn view(app: &App, m: &Model, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();
    draw.background().color(WHITE);

    // Draw movers
    for mover in &m.movers {
        mover.display(&draw);
    }

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap, HashSet};

use super::types::ConflictReason;
use core::resolver::Context;
use core::{Dependency, PackageId};

/// This is a Trie for storing a large number of Sets designed to
/// efficiently see if any of the stored Sets are a subset of a search Set.
enum ConflictStoreTrie {
    /// a Leaf is one of the stored Sets.
    Leaf(BTreeMap<PackageId, ConflictReason>),
    /// a Node is a map from an element to a subTrie where
    /// all the Sets in the subTrie contains that element.
    Node(HashMap<PackageId, ConflictStoreTrie>),
}

impl ConflictStoreTrie {
    /// Finds any known set of conflicts, if any,
    /// which are activated in `cx` and pass the `filter` specified?
    fn find_conflicting<F>(
        &self,
        cx: &Context,
        filter: &F,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>>
    where
        for<'r> F: Fn(&'r &BTreeMap<PackageId, ConflictReason>) -> bool,
    {
        match self {
            ConflictStoreTrie::Leaf(c) => {
                if filter(&c) {
                    // is_conflicting checks that all the elements are active,
                    // but we have checked each one by the recursion of this function.
                    debug_assert!(cx.is_conflicting(None, c));
                    Some(c)
                } else {
                    None
                }
            }
            ConflictStoreTrie::Node(m) => {
                for (&pid, store) in m {
                    // if the key is active then we need to check all of the corresponding subTrie.
                    if cx.is_active(pid) {
                        if let Some(o) = store.find_conflicting(cx, filter) {
                            return Some(o);
                        }
                    } // else, if it is not active then there is no way any of the corresponding
                      // subTrie will be conflicting.
                }
                None
            }
        }
    }

    fn insert(
        &mut self,
        mut iter: impl Iterator<Item = PackageId>,
        con: BTreeMap<PackageId, ConflictReason>,
    ) {
        if let Some(pid) = iter.next() {
            if let ConflictStoreTrie::Node(p) = self {
                p.entry(pid)
                    .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new()))
                    .insert(iter, con);
            } // else, We already have a subset of this in the ConflictStore
        } else {
            // we are at the end of the set we are adding, there are 3 cases for what to do next:
            // 1. self is a empty dummy Node inserted by `or_insert_with`
            //      in witch case we should replace it with `Leaf(con)`.
            // 2. self is a Node because we previously inserted a superset of
            //      the thing we are working on (I don't know if this happens in practice)
            //      but the subset that we are working on will
            //      always match any time the larger set would have
            //      in witch case we can replace it with `Leaf(con)`.
            // 3. self is a Leaf that is in the same spot in the structure as
            //      the thing we are working on. So it is equivalent.
            //      We can replace it with `Leaf(con)`.
            if cfg!(debug_assertions) {
                if let ConflictStoreTrie::Leaf(c) = self {
                    let a: Vec<_> = con.keys().collect();
                    let b: Vec<_> = c.keys().collect();
                    assert_eq!(a, b);
                }
            }
            *self = ConflictStoreTrie::Leaf(con)
        }
    }
}

pub(super) struct ConflictCache {
    // `con_from_dep` is a cache of the reasons for each time we
    // backtrack. For example after several backtracks we may have:
    //
    //  con_from_dep[`foo = "^1.0.2"`] = map!{
    //      `foo=1.0.1`: map!{`foo=1.0.1`: Semver},
    //      `foo=1.0.0`: map!{`foo=1.0.0`: Semver},
    //  };
    //
    // This can be read as "we cannot find a candidate for dep `foo = "^1.0.2"`
    // if either `foo=1.0.1` OR `foo=1.0.0` are activated".
    //
    // Another example after several backtracks we may have:
    //
    //  con_from_dep[`foo = ">=0.8.2, <=0.9.3"`] = map!{
    //      `foo=0.8.1`: map!{
    //          `foo=0.9.4`: map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver},
    //      }
    //  };
    //
    // This can be read as "we cannot find a candidate for dep `foo = ">=0.8.2,
    // <=0.9.3"` if both `foo=0.8.1` AND `foo=0.9.4` are activated".
    //
    // This is used to make sure we don't queue work we know will fail. See the
    // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this
    // is so important. The nested HashMaps act as a kind of btree, that lets us
    // look up which entries are still active without
    // linearly scanning through the full list.
    //
    // Also, as a final note, this map is *not* ever removed from. This remains
    // as a global cache which we never delete from. Any entry in this map is
    // unconditionally true regardless of our resolution history of how we got
    // here.
    con_from_dep: HashMap<Dependency, ConflictStoreTrie>,
    // `dep_from_pid` is an inverse-index of `con_from_dep`.
    // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`.
    dep_from_pid: HashMap<PackageId, HashSet<Dependency>>,
}

impl ConflictCache {
    pub fn new() -> ConflictCache {
        ConflictCache {
            con_from_dep: HashMap::new(),
            dep_from_pid: HashMap::new(),
        }
    }
    /// Finds any known set of conflicts, if any,
    /// which are activated in `cx` and pass the `filter` specified?
    pub fn find_conflicting<F>(
        &self,
        cx: &Context,
        dep: &Dependency,
        filter: F,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>>
    where
        for<'r> F: Fn(&'r &BTreeMap<PackageId, ConflictReason>) -> bool,
    {
        self.con_from_dep.get(dep)?.find_conflicting(cx, &filter)
    }
    pub fn conflicting(
        &self,
        cx: &Context,
        dep: &Dependency,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>> {
        self.find_conflicting(cx, dep, |_| true)
    }

    /// Add to the cache a conflict of the form:
    /// `dep` is known to be unresolvable if
    /// all the `PackageId` entries are activated
    pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap<PackageId, ConflictReason>) {
        self.con_from_dep
            .entry(dep.clone())
            .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new()))
            .insert(con.keys().cloned(), con.clone());

        trace!(
            "{} = \"{}\" adding a skip {:?}",
            dep.package_name(),
            dep.version_req(),
            con
        );

        for c in con.keys() {
            self.dep_from_pid
                .entry(c.clone())
                .or_insert_with(HashSet::new)
                .insert(dep.clone());
        }
    }
    pub fn dependencies_conflicting_with(&self, pid: PackageId) -> Option<&HashSet<Dependency>> {
        self.dep_from_pid.get(&pid)
    }
}
<commit_msg>regain determinism<commit_after>use std::collections::{BTreeMap, HashMap, HashSet};

use super::types::ConflictReason;
use core::resolver::Context;
use core::{Dependency, PackageId};

/// This is a Trie for storing a large number of Sets designed to
/// efficiently see if any of the stored Sets are a subset of a search Set.
enum ConflictStoreTrie {
    /// a Leaf is one of the stored Sets.
    Leaf(BTreeMap<PackageId, ConflictReason>),
    /// a Node is a map from an element to a subTrie where
    /// all the Sets in the subTrie contains that element.
    Node(BTreeMap<PackageId, ConflictStoreTrie>),
}

impl ConflictStoreTrie {
    /// Finds any known set of conflicts, if any,
    /// which are activated in `cx` and pass the `filter` specified?
    fn find_conflicting<F>(
        &self,
        cx: &Context,
        filter: &F,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>>
    where
        for<'r> F: Fn(&'r &BTreeMap<PackageId, ConflictReason>) -> bool,
    {
        match self {
            ConflictStoreTrie::Leaf(c) => {
                if filter(&c) {
                    // is_conflicting checks that all the elements are active,
                    // but we have checked each one by the recursion of this function.
                    debug_assert!(cx.is_conflicting(None, c));
                    Some(c)
                } else {
                    None
                }
            }
            ConflictStoreTrie::Node(m) => {
                for (&pid, store) in m {
                    // if the key is active then we need to check all of the corresponding subTrie.
                    if cx.is_active(pid) {
                        if let Some(o) = store.find_conflicting(cx, filter) {
                            return Some(o);
                        }
                    } // else, if it is not active then there is no way any of the corresponding
                      // subTrie will be conflicting.
                }
                None
            }
        }
    }

    fn insert(
        &mut self,
        mut iter: impl Iterator<Item = PackageId>,
        con: BTreeMap<PackageId, ConflictReason>,
    ) {
        if let Some(pid) = iter.next() {
            if let ConflictStoreTrie::Node(p) = self {
                p.entry(pid)
                    .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new()))
                    .insert(iter, con);
            } // else, We already have a subset of this in the ConflictStore
        } else {
            // we are at the end of the set we are adding, there are 3 cases for what to do next:
            // 1. self is a empty dummy Node inserted by `or_insert_with`
            //      in witch case we should replace it with `Leaf(con)`.
            // 2. self is a Node because we previously inserted a superset of
            //      the thing we are working on (I don't know if this happens in practice)
            //      but the subset that we are working on will
            //      always match any time the larger set would have
            //      in witch case we can replace it with `Leaf(con)`.
            // 3. self is a Leaf that is in the same spot in the structure as
            //      the thing we are working on. So it is equivalent.
            //      We can replace it with `Leaf(con)`.
            if cfg!(debug_assertions) {
                if let ConflictStoreTrie::Leaf(c) = self {
                    let a: Vec<_> = con.keys().collect();
                    let b: Vec<_> = c.keys().collect();
                    assert_eq!(a, b);
                }
            }
            *self = ConflictStoreTrie::Leaf(con)
        }
    }
}

pub(super) struct ConflictCache {
    // `con_from_dep` is a cache of the reasons for each time we
    // backtrack. For example after several backtracks we may have:
    //
    //  con_from_dep[`foo = "^1.0.2"`] = map!{
    //      `foo=1.0.1`: map!{`foo=1.0.1`: Semver},
    //      `foo=1.0.0`: map!{`foo=1.0.0`: Semver},
    //  };
    //
    // This can be read as "we cannot find a candidate for dep `foo = "^1.0.2"`
    // if either `foo=1.0.1` OR `foo=1.0.0` are activated".
    //
    // Another example after several backtracks we may have:
    //
    //  con_from_dep[`foo = ">=0.8.2, <=0.9.3"`] = map!{
    //      `foo=0.8.1`: map!{
    //          `foo=0.9.4`: map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver},
    //      }
    //  };
    //
    // This can be read as "we cannot find a candidate for dep `foo = ">=0.8.2,
    // <=0.9.3"` if both `foo=0.8.1` AND `foo=0.9.4` are activated".
    //
    // This is used to make sure we don't queue work we know will fail. See the
    // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this
    // is so important. The nested HashMaps act as a kind of btree, that lets us
    // look up which entries are still active without
    // linearly scanning through the full list.
    //
    // Also, as a final note, this map is *not* ever removed from. This remains
    // as a global cache which we never delete from. Any entry in this map is
    // unconditionally true regardless of our resolution history of how we got
    // here.
    con_from_dep: HashMap<Dependency, ConflictStoreTrie>,
    // `dep_from_pid` is an inverse-index of `con_from_dep`.
    // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`.
    dep_from_pid: HashMap<PackageId, HashSet<Dependency>>,
}

impl ConflictCache {
    pub fn new() -> ConflictCache {
        ConflictCache {
            con_from_dep: HashMap::new(),
            dep_from_pid: HashMap::new(),
        }
    }
    /// Finds any known set of conflicts, if any,
    /// which are activated in `cx` and pass the `filter` specified?
    pub fn find_conflicting<F>(
        &self,
        cx: &Context,
        dep: &Dependency,
        filter: F,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>>
    where
        for<'r> F: Fn(&'r &BTreeMap<PackageId, ConflictReason>) -> bool,
    {
        self.con_from_dep.get(dep)?.find_conflicting(cx, &filter)
    }
    pub fn conflicting(
        &self,
        cx: &Context,
        dep: &Dependency,
    ) -> Option<&BTreeMap<PackageId, ConflictReason>> {
        self.find_conflicting(cx, dep, |_| true)
    }

    /// Add to the cache a conflict of the form:
    /// `dep` is known to be unresolvable if
    /// all the `PackageId` entries are activated
    pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap<PackageId, ConflictReason>) {
        self.con_from_dep
            .entry(dep.clone())
            .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new()))
            .insert(con.keys().cloned(), con.clone());

        trace!(
            "{} = \"{}\" adding a skip {:?}",
            dep.package_name(),
            dep.version_req(),
            con
        );

        for c in con.keys() {
            self.dep_from_pid
                .entry(c.clone())
                .or_insert_with(HashSet::new)
                .insert(dep.clone());
        }
    }
    pub fn dependencies_conflicting_with(&self, pid: PackageId) -> Option<&HashSet<Dependency>> {
        self.dep_from_pid.get(&pid)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Alexander Reece
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]
extern crate env_logger;

#[cfg(feature = "amqp0-codegen")]
extern crate amqp0_codegen as codegen;
#[cfg(feature = "amqp0-specs")]
extern crate amqp0_specs as specs;

fn main() {
    amqp0::build();
}

#[cfg(not(feature = "amqp0-specs"))]
mod amqp0 {
    pub fn build() {
        println!("Skipping build (neither amqp0-build-primitives nor amqp0-pregen-primitives specified)");
    }
}

#[cfg(feature = "amqp0-specs")]
mod amqp0 {
    use std::env;
    use std::path::{Path, PathBuf};

    use env_logger;
    use codegen;
    use codegen::primalgen::ModulesWriter;
    use specs::specs as amqp0_specs;

    const BUILDER_CRATES: &'static [&'static str] = &["amqp0-codegen"];
    const BUILDER_REBUILD: &'static [&'static str] = &["amqp0-build-primitives"];
    const BUILDER_PREGEN: &'static [&'static str] = &["amqp0-pregen-primitives"];

    struct PrimitivesSource {
        base_dir: PathBuf,
    }

    impl codegen::Source for PrimitivesSource {
        fn name(&self) -> &str { "amqp0-primitives" }
        fn crates(&self) -> &[&str] { BUILDER_CRATES }

        fn rebuild_features(&self) -> &[&str] { BUILDER_REBUILD }
        fn pregeneration_features(&self) -> &[&str] { BUILDER_PREGEN }

        fn base_dir(&self) -> &Path { &self.base_dir }
        fn should_format(&self) -> bool { cfg!(feature = "amqp0-pregen-primitives") }
    }

    pub fn build() {
        let base_dir = if cfg!(feature = "amqp0-pregen-primitives") {
            PathBuf::from("pregen")
        } else {
            env::var_os("OUT_DIR")
                .map(PathBuf::from)
                .expect("Error: OUT_DIR not set")
        };

        env_logger::init().unwrap();
        println!("Building primitives from amqpspec");

        let source = PrimitivesSource { base_dir: base_dir };
        let writer = ModulesWriter::new(&source, amqp0_specs());
        writer.write_files().unwrap();
    }
}<commit_msg>[primitives] Update the build script output.<commit_after>// Copyright 2016 Alexander Reece
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]
extern crate env_logger;

#[cfg(feature = "amqp0-codegen")]
extern crate amqp0_codegen as codegen;
#[cfg(feature = "amqp0-specs")]
extern crate amqp0_specs as specs;

fn main() {
    amqp0::build();
}

#[cfg(not(feature = "amqp0-specs"))]
mod amqp0 {
    pub fn build() {
        println!("Skipping build (neither amqp0-build-primitives nor amqp0-pregen-primitives specified)");
    }
}

#[cfg(feature = "amqp0-specs")]
mod amqp0 {
    use std::env;
    use std::path::{Path, PathBuf};

    use env_logger;
    use codegen;
    use codegen::primalgen::ModulesWriter;
    use specs::specs as amqp0_specs;

    const BUILDER_CRATES: &'static [&'static str] = &["amqp0-codegen"];
    const BUILDER_REBUILD: &'static [&'static str] = &["amqp0-build-primitives"];
    const BUILDER_PREGEN: &'static [&'static str] = &["amqp0-pregen-primitives"];

    struct PrimitivesSource {
        base_dir: PathBuf,
    }

    impl codegen::Source for PrimitivesSource {
        fn name(&self) -> &str { "amqp0-primitives" }
        fn crates(&self) -> &[&str] { BUILDER_CRATES }

        fn rebuild_features(&self) -> &[&str] { BUILDER_REBUILD }
        fn pregeneration_features(&self) -> &[&str] { BUILDER_PREGEN }

        fn base_dir(&self) -> &Path { &self.base_dir }
        fn should_format(&self) -> bool { cfg!(feature = "amqp0-pregen-primitives") }
    }

    pub fn build() {
        let base_dir = if cfg!(feature = "amqp0-pregen-primitives") {
            PathBuf::from("pregen")
        } else {
            env::var_os("OUT_DIR")
                .map(PathBuf::from)
                .expect("Error: OUT_DIR not set")
        };

        env_logger::init().unwrap();
        println!("Building amqp0-primitives");

        let source = PrimitivesSource { base_dir: base_dir };
        let writer = ModulesWriter::new(&source, amqp0_specs());
        writer.write_files().unwrap();
    }
}<|endoftext|>


<commit_before>use super::{SeriesParams, SeriesPath, UpdateParams};
use crate::database::schema::series_configs;
use crate::database::{self, Database};
use crate::err::{Error, Result};
use anime::local::EpisodeParser;
use diesel::prelude::*;

#[derive(Clone, Debug, Queryable, Insertable)]
pub struct SeriesConfig {
    pub id: i32,
    pub nickname: String,
    pub path: SeriesPath,
    pub episode_parser: EpisodeParser,
    pub player_args: database::PlayerArgs,
}

impl SeriesConfig {
    pub fn new(id: i32, params: SeriesParams, db: &Database) -> Result<Self> {
        if let Some(existing) = Self::exists(db, id) {
            return Err(Error::SeriesAlreadyExists { name: existing });
        }

        Ok(Self {
            id,
            nickname: params.name,
            path: params.path,
            episode_parser: params.parser,
            player_args: database::PlayerArgs::new(),
        })
    }

    pub fn update(&mut self, params: UpdateParams, db: &Database) -> Result<()> {
        if let Some(id) = params.id {
            if let Some(existing) = Self::exists(db, id) {
                return Err(Error::SeriesAlreadyExists { name: existing });
            }

            self.id = id;
        }

        if let Some(path) = params.path {
            self.path = path;
        }

        if let Some(parser) = params.parser {
            self.episode_parser = parser;
        }

        Ok(())
    }

    pub fn save(&self, db: &Database) -> diesel::QueryResult<usize> {
        use crate::database::schema::series_configs::dsl::*;

        diesel::replace_into(series_configs)
            .values(self)
            .execute(db.conn())
    }

    pub fn load_all(db: &Database) -> diesel::QueryResult<Vec<Self>> {
        use crate::database::schema::series_configs::dsl::*;

        series_configs.load(db.conn())
    }

    pub fn load_by_name<S>(db: &Database, name: S) -> diesel::QueryResult<Self>
    where
        S: AsRef<str>,
    {
        use crate::database::schema::series_configs::dsl::*;

        series_configs
            .filter(nickname.eq(name.as_ref()))
            .get_result(db.conn())
    }

    /// Delete the series configuration from the database.
    ///
    /// This will also remove the series info and entry, if it exists.
    pub fn delete(&self, db: &Database) -> diesel::QueryResult<usize> {
        use crate::database::schema::series_configs::dsl::*;

        diesel::delete(series_configs.filter(id.eq(self.id))).execute(db.conn())
    }

    pub fn exists(db: &Database, config_id: i32) -> Option<String> {
        use crate::database::schema::series_configs::dsl::*;

        series_configs
            .filter(id.eq(config_id))
            .select(nickname)
            .get_result(db.conn())
            .ok()
    }
}

impl PartialEq<String> for SeriesConfig {
    fn eq(&self, nickname: &String) -> bool {
        self.nickname == *nickname
    }
}
<commit_msg>anup: Don't allow series with duplicate nicknames to be added<commit_after>use super::{SeriesParams, SeriesPath, UpdateParams};
use crate::database::schema::series_configs;
use crate::database::{self, Database};
use crate::err::{Error, Result};
use anime::local::EpisodeParser;
use diesel::prelude::*;

#[derive(Clone, Debug, Queryable, Insertable)]
pub struct SeriesConfig {
    pub id: i32,
    pub nickname: String,
    pub path: SeriesPath,
    pub episode_parser: EpisodeParser,
    pub player_args: database::PlayerArgs,
}

impl SeriesConfig {
    pub fn new(id: i32, params: SeriesParams, db: &Database) -> Result<Self> {
        if let Some(existing) = Self::exists(db, id, &params) {
            return Err(Error::SeriesAlreadyExists { name: existing });
        }

        Ok(Self {
            id,
            nickname: params.name,
            path: params.path,
            episode_parser: params.parser,
            player_args: database::PlayerArgs::new(),
        })
    }

    pub fn update(&mut self, params: UpdateParams, db: &Database) -> Result<()> {
        if let Some(id) = params.id {
            if let Some(existing) = Self::id_exists(db, id) {
                return Err(Error::SeriesAlreadyExists { name: existing });
            }

            self.id = id;
        }

        if let Some(path) = params.path {
            self.path = path;
        }

        if let Some(parser) = params.parser {
            self.episode_parser = parser;
        }

        Ok(())
    }

    pub fn save(&self, db: &Database) -> diesel::QueryResult<usize> {
        use crate::database::schema::series_configs::dsl::*;

        diesel::replace_into(series_configs)
            .values(self)
            .execute(db.conn())
    }

    pub fn load_all(db: &Database) -> diesel::QueryResult<Vec<Self>> {
        use crate::database::schema::series_configs::dsl::*;

        series_configs.load(db.conn())
    }

    pub fn load_by_name<S>(db: &Database, name: S) -> diesel::QueryResult<Self>
    where
        S: AsRef<str>,
    {
        use crate::database::schema::series_configs::dsl::*;

        series_configs
            .filter(nickname.eq(name.as_ref()))
            .get_result(db.conn())
    }

    /// Delete the series configuration from the database.
    ///
    /// This will also remove the series info and entry, if it exists.
    pub fn delete(&self, db: &Database) -> diesel::QueryResult<usize> {
        use crate::database::schema::series_configs::dsl::*;

        diesel::delete(series_configs.filter(id.eq(self.id))).execute(db.conn())
    }

    pub fn exists(db: &Database, config_id: i32, params: &SeriesParams) -> Option<String> {
        use crate::database::schema::series_configs::dsl::*;

        series_configs
            .filter(id.eq(config_id).or(nickname.eq(&params.name)))
            .select(nickname)
            .get_result(db.conn())
            .ok()
    }

    fn id_exists(db: &Database, config_id: i32) -> Option<String> {
        use crate::database::schema::series_configs::dsl::*;

        series_configs
            .filter(id.eq(config_id))
            .select(nickname)
            .get_result(db.conn())
            .ok()
    }
}

impl PartialEq<String> for SeriesConfig {
    fn eq(&self, nickname: &String) -> bool {
        self.nickname == *nickname
    }
}
<|endoftext|>


<commit_before>#[inline]
pub fn bits_0_3(n: u16) -> u8 {
    n as u8 & 0b_111
}

#[inline]
pub fn bits_0_4(n: u16) -> u8 {
    n as u8 & 0b_1111
}

#[inline]
pub fn bits_0_7(n: u16) -> u8 {
    (n & 0b111_1111) as u8
}

#[inline]
pub fn bits_0_8(n: u16) -> u8 {
    (n & 0b1111_1111) as u8
}

#[inline]
pub fn bit_0(n: u16) -> u8 {
    ((n & 0b0000_0001) >> 0) as u8
}

#[inline]
pub fn bit_1(n: u16) -> u8 {
    ((n & 0b0000_0010) >> 1) as u8
}

#[inline]
pub fn bit_2(n: u16) -> u8 {
    ((n & 0b0000_0100) >> 2) as u8
}

#[inline]
pub fn bit_3(n: u16) -> u8 {
    ((n & 0b0000_1000) >> 3) as u8
}

#[inline]
pub fn bit_4(n: u16) -> u8 {
    ((n & 0b0001_0000) >> 4) as u8
}

#[inline]
pub fn bit_5(n: u16) -> u8 {
    ((n & 0b0010_0000) >> 5) as u8
}

#[inline]
pub fn bit_6(n: u16) -> u8 {
    ((n & 0b0100_0000) >> 6) as u8
}

#[inline]
pub fn bit_7(n: u16) -> u8 {
    ((n & 0b1000_0000) >> 7) as u8
}

#[inline]
pub fn bit_8(n: u16) -> u8 {
    ((n & 0b_1_0000_0000) >> 8) as u8
}

#[inline]
pub fn bit_31(n: u32) -> u32 {
    ((n & 0b1000_0000_0000_0000) >> 31) as u32
}

#[inline]
pub fn bits_0_11(n: u16) -> u16 {
    n & 0b11_1111_1111
}

#[inline]
pub fn bits_3_6(n: u16) -> u8 {
    ((n & 0b_111_000) >> 3) as u8
}

#[inline]
pub fn bits_3_7(n: u16) -> u8 {
    ((n & 0b1111_000) >> 3) as u8
}

#[inline]
pub fn bits_6_9(n: u16) -> u8 {
    ((n & 0b111_000_000) >> 6) as u8
}

#[inline]
pub fn bits_8_11(n: u16) -> u8 {
    ((n & 0b111_0000_0000) >> 8) as u8
}

#[inline]
pub fn bits_8_12(n: u16) -> u8 {
    ((n & 0b1111_0000_0000) >> 8) as u8
}

#[inline]
pub fn bits_6_11(n: u16) -> u8 {
    ((n & 0b111_1100_0000) >> 6) as u8
}
<commit_msg>new bit funcs<commit_after>#[inline]
pub fn bits_0_3(n: u16) -> u8 {
    n as u8 & 0b_111
}

#[inline]
pub fn bits_0_4(n: u16) -> u8 {
    n as u8 & 0b_1111
}

#[inline]
pub fn bits_0_7(n: u16) -> u8 {
    (n & 0b111_1111) as u8
}

#[inline]
pub fn bits_0_8(n: u16) -> u8 {
    (n & 0b1111_1111) as u8
}

#[inline]
pub fn bit_0(n: u16) -> u8 {
    ((n & 0b0000_0001) >> 0) as u8
}

#[inline]
pub fn bit_1(n: u16) -> u8 {
    ((n & 0b0000_0010) >> 1) as u8
}

#[inline]
pub fn bit_2(n: u16) -> u8 {
    ((n & 0b0000_0100) >> 2) as u8
}

#[inline]
pub fn bit_3(n: u16) -> u8 {
    ((n & 0b0000_1000) >> 3) as u8
}

#[inline]
pub fn bit_4(n: u16) -> u8 {
    ((n & 0b0001_0000) >> 4) as u8
}

#[inline]
pub fn bit_5(n: u16) -> u8 {
    ((n & 0b0010_0000) >> 5) as u8
}

#[inline]
pub fn bit_6(n: u16) -> u8 {
    ((n & 0b0100_0000) >> 6) as u8
}

#[inline]
pub fn bit_7(n: u16) -> u8 {
    ((n & 0b1000_0000) >> 7) as u8
}

#[inline]
pub fn bit_8(n: u16) -> u8 {
    ((n & 0b_1_0000_0000) >> 8) as u8
}

#[inline]
pub fn bit_31(n: u32) -> u32 {
    ((n & 0b1000_0000_0000_0000) >> 31) as u32
}

#[inline]
pub fn bits_31_28(n: u32) -> u32 {
    ((n & 0b1111_0000_0000_0000_0000_0000_0000) >> 24) as u32
}

#[inline]
pub fn bits_27_0(n: u32) -> u32 {
    (n & 0b0000_1111_1111_1111_1111_1111_1111) as u32
}

#[inline]
pub fn bits_0_11(n: u16) -> u16 {
    n & 0b11_1111_1111
}

#[inline]
pub fn bits_3_6(n: u16) -> u8 {
    ((n & 0b_111_000) >> 3) as u8
}

#[inline]
pub fn bits_3_7(n: u16) -> u8 {
    ((n & 0b1111_000) >> 3) as u8
}

#[inline]
pub fn bits_6_9(n: u16) -> u8 {
    ((n & 0b111_000_000) >> 6) as u8
}

#[inline]
pub fn bits_8_11(n: u16) -> u8 {
    ((n & 0b111_0000_0000) >> 8) as u8
}

#[inline]
pub fn bits_8_12(n: u16) -> u8 {
    ((n & 0b1111_0000_0000) >> 8) as u8
}

#[inline]
pub fn bits_6_11(n: u16) -> u8 {
    ((n & 0b111_1100_0000) >> 6) as u8
}
<|endoftext|>