<commit_before>use super::frontend_prelude::*;

use crate::controllers::helpers::pagination::{Page, PaginationOptions};
use crate::controllers::util::AuthenticatedUser;
use crate::models::{Crate, CrateOwnerInvitation, Rights, User};
use crate::schema::{crate_owner_invitations, crates, users};
use crate::util::errors::{forbidden, internal};
use crate::views::{
    EncodableCrateOwnerInvitation, EncodableCrateOwnerInvitationV1, EncodablePublicUser,
    InvitationResponse,
};
use chrono::{Duration, Utc};
use diesel::{pg::Pg, sql_types::Bool};
use indexmap::IndexMap;
use std::collections::{HashMap, HashSet};

/// Handles the `GET /api/v1/me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    let auth = req.authenticate()?.forbid_api_token_auth()?;
    let user_id = auth.user_id();

    let PrivateListResponse {
        invitations, users, ..
    } = prepare_list(req, auth, ListFilter::InviteeId(user_id))?;

    // The schema for the private endpoints is converted to the schema used by v1 endpoints.
    let crate_owner_invitations = invitations
        .into_iter()
        .map(|private| {
            Ok(EncodableCrateOwnerInvitationV1 {
                invited_by_username: users
                    .iter()
                    .find(|u| u.id == private.inviter_id)
                    .ok_or_else(|| internal(&format!("missing user {}", private.inviter_id)))?
                    .login
                    .clone(),
                invitee_id: private.invitee_id,
                inviter_id: private.inviter_id,
                crate_name: private.crate_name,
                crate_id: private.crate_id,
                created_at: private.created_at,
                expires_at: private.expires_at,
            })
        })
        .collect::<AppResult<Vec<EncodableCrateOwnerInvitationV1>>>()?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitationV1>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

/// Handles the `GET /api/private/crate-owner-invitations` route.
pub fn private_list(req: &mut dyn RequestExt) -> EndpointResult {
    let auth = req.authenticate()?.forbid_api_token_auth()?;

    let filter = if let Some(crate_name) = req.query().get("crate_name") {
        ListFilter::CrateName(crate_name.clone())
    } else if let Some(id) = req.query().get("invitee_id").and_then(|i| i.parse().ok()) {
        ListFilter::InviteeId(id)
    } else {
        return Err(bad_request("missing or invalid filter"));
    };

    let list = prepare_list(req, auth, filter)?;
    Ok(req.json(&list))
}

enum ListFilter {
    CrateName(String),
    InviteeId(i32),
}

fn prepare_list(
    req: &mut dyn RequestExt,
    auth: AuthenticatedUser,
    filter: ListFilter,
) -> AppResult<PrivateListResponse> {
    let pagination: PaginationOptions = PaginationOptions::builder()
        .enable_pages(false)
        .enable_seek(true)
        .gather(req)?;

    let user = auth.user();
    let conn = req.db_read_only()?;
    let config = &req.app().config;

    let mut crate_names = HashMap::new();
    let mut users = IndexMap::new();
    users.insert(user.id, user.clone());

    let sql_filter: Box<dyn BoxableExpression<crate_owner_invitations::table, Pg, SqlType = Bool>> =
        match filter {
            ListFilter::CrateName(crate_name) => {
                // Only allow crate owners to query pending invitations for their crate.
                let krate: Crate = Crate::by_name(&crate_name).first(&*conn)?;
                let owners = krate.owners(&*conn)?;
                if user.rights(req.app(), &owners)? != Rights::Full {
                    return Err(forbidden());
                }

                // Cache the crate name to avoid querying it from the database again
                crate_names.insert(krate.id, krate.name.clone());

                Box::new(crate_owner_invitations::crate_id.eq(krate.id))
            }
            ListFilter::InviteeId(invitee_id) => {
                if invitee_id != user.id {
                    return Err(forbidden());
                }
                Box::new(crate_owner_invitations::invited_user_id.eq(invitee_id))
            }
        };

    // Load all the non-expired invitations matching the filter.
    let expire_cutoff = Duration::days(config.ownership_invitations_expiration_days as i64);
    let query = crate_owner_invitations::table
        .filter(sql_filter)
        .filter(crate_owner_invitations::created_at.gt((Utc::now() - expire_cutoff).naive_utc()))
        .order_by((
            crate_owner_invitations::crate_id,
            crate_owner_invitations::invited_user_id,
        ))
        // We fetch one element over the page limit to then detect whether there is a next page.
        .limit(pagination.per_page as i64 + 1);

    // Load and paginate the results.
    let mut raw_invitations: Vec<CrateOwnerInvitation> = match pagination.page {
        Page::Unspecified => query.load(&*conn)?,
        Page::Seek(s) => {
            let seek_key: (i32, i32) = s.decode()?;
            query
                .filter(
                    crate_owner_invitations::crate_id.gt(seek_key.0).or(
                        crate_owner_invitations::crate_id
                            .eq(seek_key.0)
                            .and(crate_owner_invitations::invited_user_id.gt(seek_key.1)),
                    ),
                )
                .load(&*conn)?
        }
        Page::Numeric(_) => unreachable!("page-based pagination is disabled"),
    };
    let next_page = if raw_invitations.len() > pagination.per_page as usize {
        // We fetch `per_page + 1` to check if there are records for the next page. Since the last
        // element is not what the user wanted it's discarded.
        raw_invitations.pop();

        if let Some(last) = raw_invitations.last() {
            let mut params = IndexMap::new();
            params.insert(
                "seek".into(),
                crate::controllers::helpers::pagination::encode_seek((
                    last.crate_id,
                    last.invited_user_id,
                ))?,
            );
            Some(req.query_with_params(params))
        } else {
            None
        }
    } else {
        None
    };

    // Load all the related crates.
    let missing_crate_names = raw_invitations
        .iter()
        .map(|i| i.crate_id)
        .filter(|id| !crate_names.contains_key(id))
        .collect::<Vec<_>>();
    if !missing_crate_names.is_empty() {
        let new_names: Vec<(i32, String)> = crates::table
            .select((crates::id, crates::name))
            .filter(crates::id.eq_any(missing_crate_names))
            .load(&*conn)?;
        for (id, name) in new_names.into_iter() {
            crate_names.insert(id, name);
        }
    }

    // Load all the related users.
    let missing_users = raw_invitations
        .iter()
        .flat_map(|invite| {
            std::iter::once(invite.invited_user_id)
                .chain(std::iter::once(invite.invited_by_user_id))
        })
        .filter(|id| !users.contains_key(id))
        .collect::<Vec<_>>();
    if !missing_users.is_empty() {
        let new_users: Vec<User> = users::table
            .filter(users::id.eq_any(missing_users))
            .load(&*conn)?;
        for user in new_users.into_iter() {
            users.insert(user.id, user);
        }
    }

    // Turn `CrateOwnerInvitation`s into `EncodablePrivateCrateOwnerInvitation`.
    let config = &req.app().config;
    let mut invitations = Vec::new();
    let mut users_in_response = HashSet::new();
    for invitation in raw_invitations.into_iter() {
        invitations.push(EncodableCrateOwnerInvitation {
            invitee_id: invitation.invited_user_id,
            inviter_id: invitation.invited_by_user_id,
            crate_id: invitation.crate_id,
            crate_name: crate_names
                .get(&invitation.crate_id)
                .ok_or_else(|| internal(&format!("missing crate with id {}", invitation.crate_id)))?
                .clone(),
            created_at: invitation.created_at,
            expires_at: invitation.expires_at(config),
        });
        users_in_response.insert(invitation.invited_user_id);
        users_in_response.insert(invitation.invited_by_user_id);
    }

    // Provide a stable response for the users list, only including the referenced users with
    // stable sorting.
    users.retain(|k, _| users_in_response.contains(k));
    users.sort_keys();

    Ok(PrivateListResponse {
        invitations,
        users: users
            .into_iter()
            .map(|(_, user)| EncodablePublicUser::from(user))
            .collect(),
        meta: ResponseMeta { next_page },
    })
}

#[derive(Serialize)]
struct PrivateListResponse {
    invitations: Vec<EncodableCrateOwnerInvitation>,
    users: Vec<EncodablePublicUser>,
    meta: ResponseMeta,
}

#[derive(Serialize)]
struct ResponseMeta {
    next_page: Option<String>,
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /api/v1/me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;
    let config = &req.app().config;

    let invitation = CrateOwnerInvitation::find_by_id(user_id, crate_invite.crate_id, conn)?;
    if crate_invite.accepted {
        invitation.accept(conn, config)?;
    } else {
        invitation.decline(conn)?;
    }

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }
    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}

/// Handles the `PUT /api/v1/me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let config = &req.app().config;
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let invitation = CrateOwnerInvitation::find_by_token(req_token, &conn)?;
    let crate_id = invitation.crate_id;
    invitation.accept(&conn, config)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }
    Ok(req.json(&R {
        crate_owner_invitation: InvitationResponse {
            crate_id,
            accepted: true,
        },
    }))
}
<commit_msg>controllers::crate_owner_invitation: Simplify `users` assignment<commit_after>use super::frontend_prelude::*;

use crate::controllers::helpers::pagination::{Page, PaginationOptions};
use crate::controllers::util::AuthenticatedUser;
use crate::models::{Crate, CrateOwnerInvitation, Rights, User};
use crate::schema::{crate_owner_invitations, crates, users};
use crate::util::errors::{forbidden, internal};
use crate::views::{
    EncodableCrateOwnerInvitation, EncodableCrateOwnerInvitationV1, EncodablePublicUser,
    InvitationResponse,
};
use chrono::{Duration, Utc};
use diesel::{pg::Pg, sql_types::Bool};
use indexmap::IndexMap;
use std::collections::{HashMap, HashSet};

/// Handles the `GET /api/v1/me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    let auth = req.authenticate()?.forbid_api_token_auth()?;
    let user_id = auth.user_id();

    let PrivateListResponse {
        invitations, users, ..
    } = prepare_list(req, auth, ListFilter::InviteeId(user_id))?;

    // The schema for the private endpoints is converted to the schema used by v1 endpoints.
    let crate_owner_invitations = invitations
        .into_iter()
        .map(|private| {
            Ok(EncodableCrateOwnerInvitationV1 {
                invited_by_username: users
                    .iter()
                    .find(|u| u.id == private.inviter_id)
                    .ok_or_else(|| internal(&format!("missing user {}", private.inviter_id)))?
                    .login
                    .clone(),
                invitee_id: private.invitee_id,
                inviter_id: private.inviter_id,
                crate_name: private.crate_name,
                crate_id: private.crate_id,
                created_at: private.created_at,
                expires_at: private.expires_at,
            })
        })
        .collect::<AppResult<Vec<EncodableCrateOwnerInvitationV1>>>()?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitationV1>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

/// Handles the `GET /api/private/crate-owner-invitations` route.
pub fn private_list(req: &mut dyn RequestExt) -> EndpointResult {
    let auth = req.authenticate()?.forbid_api_token_auth()?;

    let filter = if let Some(crate_name) = req.query().get("crate_name") {
        ListFilter::CrateName(crate_name.clone())
    } else if let Some(id) = req.query().get("invitee_id").and_then(|i| i.parse().ok()) {
        ListFilter::InviteeId(id)
    } else {
        return Err(bad_request("missing or invalid filter"));
    };

    let list = prepare_list(req, auth, filter)?;
    Ok(req.json(&list))
}

enum ListFilter {
    CrateName(String),
    InviteeId(i32),
}

fn prepare_list(
    req: &mut dyn RequestExt,
    auth: AuthenticatedUser,
    filter: ListFilter,
) -> AppResult<PrivateListResponse> {
    let pagination: PaginationOptions = PaginationOptions::builder()
        .enable_pages(false)
        .enable_seek(true)
        .gather(req)?;

    let user = auth.user();
    let conn = req.db_read_only()?;
    let config = &req.app().config;

    let mut crate_names = HashMap::new();
    let mut users = IndexMap::new();
    users.insert(user.id, user.clone());

    let sql_filter: Box<dyn BoxableExpression<crate_owner_invitations::table, Pg, SqlType = Bool>> =
        match filter {
            ListFilter::CrateName(crate_name) => {
                // Only allow crate owners to query pending invitations for their crate.
                let krate: Crate = Crate::by_name(&crate_name).first(&*conn)?;
                let owners = krate.owners(&*conn)?;
                if user.rights(req.app(), &owners)? != Rights::Full {
                    return Err(forbidden());
                }

                // Cache the crate name to avoid querying it from the database again
                crate_names.insert(krate.id, krate.name.clone());

                Box::new(crate_owner_invitations::crate_id.eq(krate.id))
            }
            ListFilter::InviteeId(invitee_id) => {
                if invitee_id != user.id {
                    return Err(forbidden());
                }
                Box::new(crate_owner_invitations::invited_user_id.eq(invitee_id))
            }
        };

    // Load all the non-expired invitations matching the filter.
    let expire_cutoff = Duration::days(config.ownership_invitations_expiration_days as i64);
    let query = crate_owner_invitations::table
        .filter(sql_filter)
        .filter(crate_owner_invitations::created_at.gt((Utc::now() - expire_cutoff).naive_utc()))
        .order_by((
            crate_owner_invitations::crate_id,
            crate_owner_invitations::invited_user_id,
        ))
        // We fetch one element over the page limit to then detect whether there is a next page.
        .limit(pagination.per_page as i64 + 1);

    // Load and paginate the results.
    let mut raw_invitations: Vec<CrateOwnerInvitation> = match pagination.page {
        Page::Unspecified => query.load(&*conn)?,
        Page::Seek(s) => {
            let seek_key: (i32, i32) = s.decode()?;
            query
                .filter(
                    crate_owner_invitations::crate_id.gt(seek_key.0).or(
                        crate_owner_invitations::crate_id
                            .eq(seek_key.0)
                            .and(crate_owner_invitations::invited_user_id.gt(seek_key.1)),
                    ),
                )
                .load(&*conn)?
        }
        Page::Numeric(_) => unreachable!("page-based pagination is disabled"),
    };
    let next_page = if raw_invitations.len() > pagination.per_page as usize {
        // We fetch `per_page + 1` to check if there are records for the next page. Since the last
        // element is not what the user wanted it's discarded.
        raw_invitations.pop();

        if let Some(last) = raw_invitations.last() {
            let mut params = IndexMap::new();
            params.insert(
                "seek".into(),
                crate::controllers::helpers::pagination::encode_seek((
                    last.crate_id,
                    last.invited_user_id,
                ))?,
            );
            Some(req.query_with_params(params))
        } else {
            None
        }
    } else {
        None
    };

    // Load all the related crates.
    let missing_crate_names = raw_invitations
        .iter()
        .map(|i| i.crate_id)
        .filter(|id| !crate_names.contains_key(id))
        .collect::<Vec<_>>();
    if !missing_crate_names.is_empty() {
        let new_names: Vec<(i32, String)> = crates::table
            .select((crates::id, crates::name))
            .filter(crates::id.eq_any(missing_crate_names))
            .load(&*conn)?;
        for (id, name) in new_names.into_iter() {
            crate_names.insert(id, name);
        }
    }

    // Load all the related users.
    let missing_users = raw_invitations
        .iter()
        .flat_map(|invite| {
            std::iter::once(invite.invited_user_id)
                .chain(std::iter::once(invite.invited_by_user_id))
        })
        .filter(|id| !users.contains_key(id))
        .collect::<Vec<_>>();
    if !missing_users.is_empty() {
        let new_users: Vec<User> = users::table
            .filter(users::id.eq_any(missing_users))
            .load(&*conn)?;
        for user in new_users.into_iter() {
            users.insert(user.id, user);
        }
    }

    // Turn `CrateOwnerInvitation`s into `EncodablePrivateCrateOwnerInvitation`.
    let config = &req.app().config;
    let mut invitations = Vec::new();
    let mut users_in_response = HashSet::new();
    for invitation in raw_invitations.into_iter() {
        invitations.push(EncodableCrateOwnerInvitation {
            invitee_id: invitation.invited_user_id,
            inviter_id: invitation.invited_by_user_id,
            crate_id: invitation.crate_id,
            crate_name: crate_names
                .get(&invitation.crate_id)
                .ok_or_else(|| internal(&format!("missing crate with id {}", invitation.crate_id)))?
                .clone(),
            created_at: invitation.created_at,
            expires_at: invitation.expires_at(config),
        });
        users_in_response.insert(invitation.invited_user_id);
        users_in_response.insert(invitation.invited_by_user_id);
    }

    // Provide a stable response for the users list, only including the referenced users with
    // stable sorting.
    users.retain(|k, _| users_in_response.contains(k));
    users.sort_keys();

    Ok(PrivateListResponse {
        invitations,
        users: users.into_iter().map(|(_, user)| user.into()).collect(),
        meta: ResponseMeta { next_page },
    })
}

#[derive(Serialize)]
struct PrivateListResponse {
    invitations: Vec<EncodableCrateOwnerInvitation>,
    users: Vec<EncodablePublicUser>,
    meta: ResponseMeta,
}

#[derive(Serialize)]
struct ResponseMeta {
    next_page: Option<String>,
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /api/v1/me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;
    let config = &req.app().config;

    let invitation = CrateOwnerInvitation::find_by_id(user_id, crate_invite.crate_id, conn)?;
    if crate_invite.accepted {
        invitation.accept(conn, config)?;
    } else {
        invitation.decline(conn)?;
    }

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }
    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}

/// Handles the `PUT /api/v1/me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let config = &req.app().config;
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let invitation = CrateOwnerInvitation::find_by_token(req_token, &conn)?;
    let crate_id = invitation.crate_id;
    invitation.accept(&conn, config)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }
    Ok(req.json(&R {
        crate_owner_invitation: InvitationResponse {
            crate_id,
            accepted: true,
        },
    }))
}
<|endoftext|>


<commit_before>//! A module to manage protobuf deserialization

use errors::{Result, ErrorKind};

use byteorder::LittleEndian as LE;
use byteorder::ByteOrder;

const WIRE_TYPE_VARINT: u8 = 0;
const WIRE_TYPE_FIXED64: u8 = 1;
const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2;
const WIRE_TYPE_START_GROUP: u8 = 3;
const WIRE_TYPE_END_GROUP: u8 = 4;
const WIRE_TYPE_FIXED32: u8 = 5;

/// A struct to read protocol binary files
#[derive(Debug, Clone, PartialEq)]
pub struct Reader {
    start: usize,
    end: usize,
}

impl Reader {

    /// Creates a new reader from chunks of data
    pub fn from_bytes(bytes: &[u8]) -> Reader {
        Reader {
            start: 0,
            end: bytes.len()
        }
    }

    /// Reads next tag, `None` if all bytes have been read
    pub fn next_tag(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_varint(bytes).map(|i| (i as u32))
    }

    /// Reads the next varint encoded u64
    pub fn read_varint(&mut self, bytes: &[u8]) -> Result<u64> {
        let mut r: u64 = 0;
        let mut i = 0;
        for b in bytes.iter().skip(self.start).take(9).cloned() {
            self.start += 1;
            r |= ((b & 0x7f) as u64) << i;
            if b < 0x80 {
                return Ok(r);
            }
            i += 7;
        }
        let b = bytes[self.start];
        self.start += 1;
        let res = match b {
            0 => Ok(r),
            1 => {
                r |= 1 << 63;
                Ok(r)
            }
            _ => Err(ErrorKind::Varint.into()), // we have only one spare bit to fit into
        };
        res
    }

    /// Reads int32 (varint)
    pub fn read_int32(&mut self, bytes: &[u8]) -> Result<i32> {
        self.read_varint(bytes).map(|i| i as i32)
    }

    /// Reads int64 (varint)
    pub fn read_int64(&mut self, bytes: &[u8]) -> Result<i64> {
        self.read_varint(bytes).map(|i| i as i64)
    }

    /// Reads uint32 (varint)
    pub fn read_uint32(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_varint(bytes).map(|i| i as u32)
    }

    /// Reads uint64 (varint)
    pub fn read_uint64(&mut self, bytes: &[u8]) -> Result<u64> {
        self.read_varint(bytes)
    }

    /// Reads sint32 (varint)
    pub fn read_sint32(&mut self, bytes: &[u8]) -> Result<i32> {
        // zigzag
        let n = self.read_varint(bytes)? as u32;
        Ok(((n >> 1) as i32) ^ (-((n & 1) as i32)))
    }

    /// Reads sint64 (varint)
    pub fn read_sint64(&mut self, bytes: &[u8]) -> Result<i64> {
        // zigzag
        let n = self.read_varint(bytes)?;
        Ok(((n >> 1) as i64) ^ (-((n & 1) as i64)))
    }

    /// Reads fixed64 (little endian u64)
    fn read_fixed<M, F: Fn(&[u8]) -> M>(&mut self, bytes: &[u8], len: usize, read: F) -> Result<M> {
        let v = read(&bytes[self.start .. self.start + len]);
        self.start += len;
        Ok(v)
    }

    /// Reads fixed64 (little endian u64)
    pub fn read_fixed64(&mut self, bytes: &[u8]) -> Result<u64> {
        self.read_fixed(bytes, 8, LE::read_u64)
    }

    /// Reads fixed32 (little endian u32)
    pub fn read_fixed32(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_fixed(bytes, 4, LE::read_u32)
    }

    /// Reads sfixed64 (little endian i64)
    pub fn read_sfixed64(&mut self, bytes: &[u8]) -> Result<i64> {
        self.read_fixed(bytes, 8, LE::read_i64)
    }

    /// Reads sfixed32 (little endian i32)
    pub fn read_sfixed32(&mut self, bytes: &[u8]) -> Result<i32> {
        self.read_fixed(bytes, 4, LE::read_i32)
    }

    /// Reads float (little endian f32)
    pub fn read_float(&mut self, bytes: &[u8]) -> Result<f32> {
        self.read_fixed(bytes, 4, LE::read_f32)
    }

    /// Reads double (little endian f64)
    pub fn read_double(&mut self, bytes: &[u8]) -> Result<f64> {
        self.read_fixed(bytes, 8, LE::read_f64)
    }

    /// Reads bool (varint, check if == 0)
    pub fn read_bool(&mut self, bytes: &[u8]) -> Result<bool> {
        self.read_varint(bytes).map(|i| i != 0)
    }

    /// Reads enum, encoded as i32
    pub fn read_enum<E: From<i32>>(&mut self, bytes: &[u8]) -> Result<E> {
        self.read_int32(bytes).map(|e| e.into())
    }

    fn read_len<'a, M, F>(&mut self, bytes: &'a [u8], mut read: F) -> Result<M>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>,
    {
        let len = self.read_varint(bytes)? as usize;
        let cur_end = self.end;
        self.end = self.start + len;
        let v = read(self, bytes)?;
        self.start = self.end;
        self.end = cur_end;
        Ok(v)
    }

    /// Reads bytes (Vec<u8>)
    pub fn read_bytes<'a>(&mut self, bytes: &'a[u8]) -> Result<&'a[u8]> {
        self.read_len(bytes, |r, b| Ok(&b[r.start..r.end]))
    }

    /// Reads string (String)
    pub fn read_string<'a>(&mut self, bytes: &'a[u8]) -> Result<&'a str> {
        self.read_len(bytes, |r, b| ::std::str::from_utf8(&b[r.start..r.end]).map_err(|e| e.into()))
    }

    /// Reads packed repeated field (Vec<M>)
    ///
    /// Note: packed field are stored as a variable length chunk of data, while regular repeated
    /// fields behaves like an iterator, yielding their tag everytime
    pub fn read_packed<'a, M, F>(&mut self, bytes: &'a[u8], mut read: F) -> Result<Vec<M>>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>,
    {
        self.read_len(bytes, |r, b| {
            let mut v = Vec::new();
            while !r.is_eof() {
                v.push(read(r, b)?);
            }
            Ok(v)
        })
    }

    /// Reads a nested message
    pub fn read_message<'a, M, F>(&mut self, bytes: &'a[u8], read: F) -> Result<M>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>
    {
        self.read_len(bytes, read)
    }

    /// Reads unknown data, based on its tag value (which itself gives us the wire_type value)
    pub fn read_unknown(&mut self, bytes: &[u8], tag_value: u32) -> Result<()> {
        match (tag_value & 0x7) as u8 {
            WIRE_TYPE_VARINT => { self.read_varint(bytes)?; },
            WIRE_TYPE_FIXED64 => self.start += 8,
            WIRE_TYPE_FIXED32 => self.start += 4,
            WIRE_TYPE_LENGTH_DELIMITED => {
                let len = self.read_varint(bytes)? as usize;
                self.start += len;
            },
            WIRE_TYPE_START_GROUP |
                WIRE_TYPE_END_GROUP => { return Err(ErrorKind::Deprecated("group").into()); },
            t => { return Err(ErrorKind::UnknownWireType(t).into()); },
        }
        Ok(())
    }

    /// Gets the remaining length of bytes not read yet
    pub fn len(&self) -> usize {
        self.end - self.start
    }

    /// Checks if `self.len == 0`
    pub fn is_eof(&self) -> bool {
        self.start == self.end
    }
}

#[test]
fn test_varint() {
    let data = [0x96, 0x01];
    let mut r = Reader::from_bytes(&data[..]);
    assert_eq!(150, r.read_varint(&data[..]).unwrap());
    assert!(r.is_eof());
}
<commit_msg>improve varint<commit_after>//! A module to manage protobuf deserialization

use errors::{Result, ErrorKind};

use byteorder::LittleEndian as LE;
use byteorder::ByteOrder;

const WIRE_TYPE_VARINT: u8 = 0;
const WIRE_TYPE_FIXED64: u8 = 1;
const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2;
const WIRE_TYPE_START_GROUP: u8 = 3;
const WIRE_TYPE_END_GROUP: u8 = 4;
const WIRE_TYPE_FIXED32: u8 = 5;

/// A struct to read protocol binary files
#[derive(Debug, Clone, PartialEq)]
pub struct Reader {
    start: usize,
    end: usize,
}

impl Reader {

    /// Creates a new reader from chunks of data
    pub fn from_bytes(bytes: &[u8]) -> Reader {
        Reader {
            start: 0,
            end: bytes.len()
        }
    }

    /// Reads next tag, `None` if all bytes have been read
    pub fn next_tag(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_varint(bytes).map(|i| (i as u32))
    }

    /// Reads the next varint encoded u64
    #[inline]
    pub fn read_varint(&mut self, bytes: &[u8]) -> Result<u64> {
        let mut r: u64 = 0;
        let mut i = 0;
        for _ in 0..9 {
            let b = bytes[self.start];
            self.start += 1;
            r |= ((b & 0x7f) as u64) << i;
            if b < 0x80 {
                return Ok(r);
            }
            i += 7;
        }
        let b = bytes[self.start];
        self.start += 1;
        let res = match b {
            0 => Ok(r),
            1 => {
                r |= 1 << 63;
                Ok(r)
            }
            _ => Err(ErrorKind::Varint.into()), // we have only one spare bit to fit into
        };
        res
    }

    /// Reads int32 (varint)
    pub fn read_int32(&mut self, bytes: &[u8]) -> Result<i32> {
        self.read_varint(bytes).map(|i| i as i32)
    }

    /// Reads int64 (varint)
    pub fn read_int64(&mut self, bytes: &[u8]) -> Result<i64> {
        self.read_varint(bytes).map(|i| i as i64)
    }

    /// Reads uint32 (varint)
    pub fn read_uint32(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_varint(bytes).map(|i| i as u32)
    }

    /// Reads uint64 (varint)
    pub fn read_uint64(&mut self, bytes: &[u8]) -> Result<u64> {
        self.read_varint(bytes)
    }

    /// Reads sint32 (varint)
    pub fn read_sint32(&mut self, bytes: &[u8]) -> Result<i32> {
        // zigzag
        let n = self.read_varint(bytes)? as u32;
        Ok(((n >> 1) as i32) ^ (-((n & 1) as i32)))
    }

    /// Reads sint64 (varint)
    pub fn read_sint64(&mut self, bytes: &[u8]) -> Result<i64> {
        // zigzag
        let n = self.read_varint(bytes)?;
        Ok(((n >> 1) as i64) ^ (-((n & 1) as i64)))
    }

    /// Reads fixed64 (little endian u64)
    fn read_fixed<M, F: Fn(&[u8]) -> M>(&mut self, bytes: &[u8], len: usize, read: F) -> Result<M> {
        let v = read(&bytes[self.start .. self.start + len]);
        self.start += len;
        Ok(v)
    }

    /// Reads fixed64 (little endian u64)
    pub fn read_fixed64(&mut self, bytes: &[u8]) -> Result<u64> {
        self.read_fixed(bytes, 8, LE::read_u64)
    }

    /// Reads fixed32 (little endian u32)
    pub fn read_fixed32(&mut self, bytes: &[u8]) -> Result<u32> {
        self.read_fixed(bytes, 4, LE::read_u32)
    }

    /// Reads sfixed64 (little endian i64)
    pub fn read_sfixed64(&mut self, bytes: &[u8]) -> Result<i64> {
        self.read_fixed(bytes, 8, LE::read_i64)
    }

    /// Reads sfixed32 (little endian i32)
    pub fn read_sfixed32(&mut self, bytes: &[u8]) -> Result<i32> {
        self.read_fixed(bytes, 4, LE::read_i32)
    }

    /// Reads float (little endian f32)
    pub fn read_float(&mut self, bytes: &[u8]) -> Result<f32> {
        self.read_fixed(bytes, 4, LE::read_f32)
    }

    /// Reads double (little endian f64)
    pub fn read_double(&mut self, bytes: &[u8]) -> Result<f64> {
        self.read_fixed(bytes, 8, LE::read_f64)
    }

    /// Reads bool (varint, check if == 0)
    pub fn read_bool(&mut self, bytes: &[u8]) -> Result<bool> {
        self.read_varint(bytes).map(|i| i != 0)
    }

    /// Reads enum, encoded as i32
    pub fn read_enum<E: From<i32>>(&mut self, bytes: &[u8]) -> Result<E> {
        self.read_int32(bytes).map(|e| e.into())
    }

    fn read_len<'a, M, F>(&mut self, bytes: &'a [u8], mut read: F) -> Result<M>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>,
    {
        let len = self.read_varint(bytes)? as usize;
        let cur_end = self.end;
        self.end = self.start + len;
        let v = read(self, bytes)?;
        self.start = self.end;
        self.end = cur_end;
        Ok(v)
    }

    /// Reads bytes (Vec<u8>)
    pub fn read_bytes<'a>(&mut self, bytes: &'a[u8]) -> Result<&'a[u8]> {
        self.read_len(bytes, |r, b| Ok(&b[r.start..r.end]))
    }

    /// Reads string (String)
    pub fn read_string<'a>(&mut self, bytes: &'a[u8]) -> Result<&'a str> {
        self.read_len(bytes, |r, b| ::std::str::from_utf8(&b[r.start..r.end]).map_err(|e| e.into()))
    }

    /// Reads packed repeated field (Vec<M>)
    ///
    /// Note: packed field are stored as a variable length chunk of data, while regular repeated
    /// fields behaves like an iterator, yielding their tag everytime
    pub fn read_packed<'a, M, F>(&mut self, bytes: &'a[u8], mut read: F) -> Result<Vec<M>>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>,
    {
        self.read_len(bytes, |r, b| {
            let mut v = Vec::new();
            while !r.is_eof() {
                v.push(read(r, b)?);
            }
            Ok(v)
        })
    }

    /// Reads a nested message
    pub fn read_message<'a, M, F>(&mut self, bytes: &'a[u8], read: F) -> Result<M>
        where F: FnMut(&mut Reader, &'a[u8]) -> Result<M>
    {
        self.read_len(bytes, read)
    }

    /// Reads unknown data, based on its tag value (which itself gives us the wire_type value)
    pub fn read_unknown(&mut self, bytes: &[u8], tag_value: u32) -> Result<()> {
        match (tag_value & 0x7) as u8 {
            WIRE_TYPE_VARINT => { self.read_varint(bytes)?; },
            WIRE_TYPE_FIXED64 => self.start += 8,
            WIRE_TYPE_FIXED32 => self.start += 4,
            WIRE_TYPE_LENGTH_DELIMITED => {
                let len = self.read_varint(bytes)? as usize;
                self.start += len;
            },
            WIRE_TYPE_START_GROUP |
                WIRE_TYPE_END_GROUP => { return Err(ErrorKind::Deprecated("group").into()); },
            t => { return Err(ErrorKind::UnknownWireType(t).into()); },
        }
        Ok(())
    }

    /// Gets the remaining length of bytes not read yet
    pub fn len(&self) -> usize {
        self.end - self.start
    }

    /// Checks if `self.len == 0`
    pub fn is_eof(&self) -> bool {
        self.start == self.end
    }
}

#[test]
fn test_varint() {
    let data = [0x96, 0x01];
    let mut r = Reader::from_bytes(&data[..]);
    assert_eq!(150, r.read_varint(&data[..]).unwrap());
    assert!(r.is_eof());
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Rouille developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Equivalent to a `match` expression but for routes.
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate rouille; fn main() {
/// # let request: rouille::Request = unsafe { std::mem::uninitialized() };
/// let _result = router!(request,
///     // first route
///     (GET) (/) => {
///         12
///     },
///
///     // second route
///     (GET) (/hello) => {
///         43 * 7
///     },
///
///     // ... other routes here ...
///
///     // default route
///     _ => 5
/// );
/// # }
/// ```
///
/// # Details
///
/// The macro will take each route one by one and execute the first one that matches, similar to a
/// `match` language construct. The whole `router!` expression then returns what the body
/// returns, therefore all the bodies must return the same type of data.
///
/// You can use parameters by putting them inside `{}`:
///
/// ```ignore
/// (GET) (/{id}/foo) => {
///     ...
/// },
/// ```
///
/// If you use parameters inside `{}`, then a variable with the same name will be available in the
/// code in the body.
///
/// Each parameter gets parsed through the `FromStr` trait. If the parsing fails, the route is
/// ignored. If you get an error because the type of the parameter couldn't be inferred, you can
/// also specify the type inside the brackets:
///
/// ```ignore
/// (GET) (/{id: u32}/foo) => {
///     ...
/// },
/// ```
///
/// Some other things to note:
///
/// - The right of the `=>` must be a block (must be surrounded by `{` and `}`).
/// - The pattern of the URL and the closure must be inside parentheses. This is to bypass
///   limitations of Rust's macros system.
/// - The default handler (with `_`) must be present or will get a compilation error.
///
// FIXME: turn `: $pt:ident` into `ty`
// TODO: don't panic if parsing fails
#[macro_export]
macro_rules! router {
    ($request:expr, $(($method:ident) ($($pat:tt)+) => $value:block,)* _ => $def:expr) => {
        {
            let ref request = $request;

            // ignoring the GET parameters (everything after `?`)
            let request_url = request.url();
            let request_url = {
                let pos = request_url.find('?').unwrap_or(request_url.len());
                &request_url[..pos]
            };

            let mut ret = None;

            $({
                if ret.is_none() && request.method() == stringify!($method) {
                    ret = router!(__check_pattern request_url $value $($pat)+);
                }
            })+

            if let Some(ret) = ret {
                ret
            } else {
                $def
            }
        }
    };

    (__check_pattern $url:ident $value:block /{$p:ident} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            None
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];

            if let Some($p) = url[0 .. pat_end].parse().ok() {
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block /{$p:ident: $t:ty} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            None
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];

            if let Some($p) = url[0 .. pat_end].parse().ok() {
                let $p: $t = $p;
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block /$p:ident $($rest:tt)*) => (
        {
            let required = concat!("/", stringify!($p));
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block - $($rest:tt)*) => (
        {
            if $url.starts_with('-') {
                let rest_url = &$url[1..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block) => (
        if $url.len() == 0 { Some($value) } else { None }
    );

    (__check_pattern $url:ident $value:block /) => (
        if $url == "/" { Some($value) } else { None }
    );

    (__check_pattern $url:ident $value:block $p:ident $($rest:tt)*) => (
        {
            let required = stringify!($p);
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );
}

#[cfg(test)]
mod tests {
    use Request;

    #[test]
    fn basic() {
        let request = Request::fake_http("GET", "/", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/hello) => { 0 },
            (GET) (/{_val:u32}) => { 0 },
            (GET) (/) => { 1 },
            _ => 0
        ));
    }

    #[test]
    fn dash() {
        let request = Request::fake_http("GET", "/a-b", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/a/b) => { 0 },
            (GET) (/a_b) => { 0 },
            (GET) (/a-b) => { 1 },
            _ => 0
        ));
    }

    #[test]
    fn params() {
        let request = Request::fake_http("GET", "/hello/5", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/hello/) => { 0 },
            (GET) (/hello/{id:u32}) => { if id == 5 { 1 } else { 0 } },
            (GET) (/hello/{_id:String}) => { 0 },
            _ => 0
        ));
    }

    #[test]
    #[ignore]       // TODO: not implemented
    fn param_slash() {
        let request = Request::fake_http("GET", "/hello%2F5", vec![], vec![]);

        router!(request,
            (GET) (/{a:String}) => { assert_eq!(a, "hello/5") },
            _ => panic!()
        );
    }
}
<commit_msg>fixing clippy warnings for router macro<commit_after>// Copyright (c) 2016 The Rouille developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Equivalent to a `match` expression but for routes.
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate rouille; fn main() {
/// # let request: rouille::Request = unsafe { std::mem::uninitialized() };
/// let _result = router!(request,
///     // first route
///     (GET) (/) => {
///         12
///     },
///
///     // second route
///     (GET) (/hello) => {
///         43 * 7
///     },
///
///     // ... other routes here ...
///
///     // default route
///     _ => 5
/// );
/// # }
/// ```
///
/// # Details
///
/// The macro will take each route one by one and execute the first one that matches, similar to a
/// `match` language construct. The whole `router!` expression then returns what the body
/// returns, therefore all the bodies must return the same type of data.
///
/// You can use parameters by putting them inside `{}`:
///
/// ```ignore
/// (GET) (/{id}/foo) => {
///     ...
/// },
/// ```
///
/// If you use parameters inside `{}`, then a variable with the same name will be available in the
/// code in the body.
///
/// Each parameter gets parsed through the `FromStr` trait. If the parsing fails, the route is
/// ignored. If you get an error because the type of the parameter couldn't be inferred, you can
/// also specify the type inside the brackets:
///
/// ```ignore
/// (GET) (/{id: u32}/foo) => {
///     ...
/// },
/// ```
///
/// Some other things to note:
///
/// - The right of the `=>` must be a block (must be surrounded by `{` and `}`).
/// - The pattern of the URL and the closure must be inside parentheses. This is to bypass
///   limitations of Rust's macros system.
/// - The default handler (with `_`) must be present or will get a compilation error.
///
// FIXME: turn `: $pt:ident` into `ty`
// TODO: don't panic if parsing fails
#[macro_export]
macro_rules! router {
    ($request:expr, $(($method:ident) ($($pat:tt)+) => $value:block,)* _ => $def:expr) => {
        {
            let request = &$request;

            // ignoring the GET parameters (everything after `?`)
            let request_url = request.url();
            let request_url = {
                let pos = request_url.find('?').unwrap_or(request_url.len());
                &request_url[..pos]
            };

            let mut ret = None;

            $({
                if ret.is_none() && request.method() == stringify!($method) {
                    ret = router!(__check_pattern request_url $value $($pat)+);
                }
            })+

            if let Some(ret) = ret {
                ret
            } else {
                $def
            }
        }
    };

    (__check_pattern $url:ident $value:block /{$p:ident} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            None
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];

            if let Ok($p) = url[0 .. pat_end].parse() {
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block /{$p:ident: $t:ty} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            None
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];

            if let Ok($p) = url[0 .. pat_end].parse() {
                let $p: $t = $p;
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block /$p:ident $($rest:tt)*) => (
        {
            let required = concat!("/", stringify!($p));
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block - $($rest:tt)*) => (
        {
            if $url.starts_with('-') {
                let rest_url = &$url[1..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );

    (__check_pattern $url:ident $value:block) => (
        if $url.len() == 0 { Some($value) } else { None }
    );

    (__check_pattern $url:ident $value:block /) => (
        if $url == "/" { Some($value) } else { None }
    );

    (__check_pattern $url:ident $value:block $p:ident $($rest:tt)*) => (
        {
            let required = stringify!($p);
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern rest_url $value $($rest)*)
            } else {
                None
            }
        }
    );
}

#[cfg(test)]
mod tests {
    use Request;

    #[test]
    fn basic() {
        let request = Request::fake_http("GET", "/", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/hello) => { 0 },
            (GET) (/{_val:u32}) => { 0 },
            (GET) (/) => { 1 },
            _ => 0
        ));
    }

    #[test]
    fn dash() {
        let request = Request::fake_http("GET", "/a-b", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/a/b) => { 0 },
            (GET) (/a_b) => { 0 },
            (GET) (/a-b) => { 1 },
            _ => 0
        ));
    }

    #[test]
    fn params() {
        let request = Request::fake_http("GET", "/hello/5", vec![], vec![]);

        assert_eq!(1, router!(request,
            (GET) (/hello/) => { 0 },
            (GET) (/hello/{id:u32}) => { if id == 5 { 1 } else { 0 } },
            (GET) (/hello/{_id:String}) => { 0 },
            _ => 0
        ));
    }

    #[test]
    #[ignore]       // TODO: not implemented
    fn param_slash() {
        let request = Request::fake_http("GET", "/hello%2F5", vec![], vec![]);

        router!(request,
            (GET) (/{a:String}) => { assert_eq!(a, "hello/5") },
            _ => panic!()
        );
    }
}
<|endoftext|>


<commit_before>// check-pass

use std::io::Write;

fn main() -> Result<(), std::io::Error> {
    vec! { 1, 2, 3 }.len();
    write! { vec![], "" }?;
    Ok(())
}
<commit_msg>Add negative test in macro-braces-dot-question.rs.<commit_after>// check-pass

use std::io::Write;

fn main() -> Result<(), std::io::Error> {
    vec! { 1, 2, 3 }.len();
    write! { vec![], "" }?;
    println!{""}
    [0]; // separate statement, not indexing into the result of println.
    Ok(())
}
<|endoftext|>


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

use std::io::Error;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use std::collections::LinkedList;

use libc;
use libc::{c_int, c_void};
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use errno::errno;
use threadpool::ThreadPool;
use openssl::ssl::{SslStream, SslContext};
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

use stats;
use types::*;
use config::Config;

// We need to be able to access our resource pool from several methods
static mut thread_pool: *mut ThreadPool = 0 as *mut ThreadPool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Stream>::new()));

    // Resource pool
    let mut tp = ThreadPool::new(config.workers);
    unsafe {
        thread_pool = &mut tp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create and configure a new socket
    let mut socket = Socket::new(tcp_stream.into_raw_fd());
    let result = setup_new_socket(&mut socket);
    if result.is_err() {
        close_fd(socket.as_raw_fd());
        return;
    }

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let sock_fd = socket.as_raw_fd();
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    close_fd(sock_fd);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_fd_to_epoll(epfd, fd, streams.clone());
}

fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    let fd = event.data as RawFd;
    let find_result = try_find_stream_from_fd(streams.clone(), fd);
    if find_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);
    }

    let stream = find_result.unwrap();
    let read_event = if (event.events & READ_EVENT) > 0 {
        true
    } else {
        false
    };

    if read_event {
        handle_read_event(epfd, stream, streams, handler);
    } else {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
    }
}

fn try_find_stream_from_fd(streams: StreamList, fd: RawFd) -> Result<Stream, ()> {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for stream in list.iter() {
        if stream.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    let result = if found {
        if index == 1 {
            Ok(list.pop_front().unwrap())
        } else {
            let mut split = list.split_off(index - 1);
            let stream = split.pop_front().unwrap();
            list.append(&mut split);
            Ok(stream)
        }
    } else {
        Err(())
    };

    result
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: Stream, streams: StreamList, handler: Handler) {
    let fd = stream.as_raw_fd();

    let mut stream = stream;
    let recv_result = stream.recv();
    if recv_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
        return;
    }

    let mut msg_queue = stream.drain_rx_queue();
    for msg in msg_queue.drain(..) {
        let s = stream.clone();
        let sl = streams.clone();
        let h = handler.clone();

        if msg_is_stats_request(&msg) {
            handle_stats_request(&msg, epfd, s, sl);
        } else {
            unsafe {
                (*thread_pool).execute(move || {
                    let Handler(ptr) = h;
                    (*ptr).on_data_received(s, msg);
                });
            }
        }
    }

    add_stream_to_master_list(stream, streams);
}

#[inline]
fn msg_is_stats_request(msg: &[u8]) -> bool {
    if msg.len() == 6 && msg[0] == 0x04 && msg[1] == 0x04 {
        true
    } else {
        false
    }
}

fn handle_stats_request(buf: &[u8], epfd: RawFd, stream: Stream, streams: StreamList) {
    trace!("handle_stats_request");
    let stream_clone = stream.clone();
    let u8ptr: *const u8 = &buf[2] as *const _;
    let f32ptr: *const f32 = u8ptr as *const _;
    unsafe {
        let sec = *f32ptr;
        (*thread_pool).execute(move || {
            let stats_result = stats::as_serialized_buffer(sec);
            if stats_result.is_err() {
                error!("Retrieving stats");
                return;
            }

            let stats_buffer = stats_result.unwrap();

            let mut stream = stream;
            let send_result = stream.send(&stats_buffer[..]);
            if send_result.is_err() {
                error!("Writing to stream: {}", send_result.unwrap_err());
                let fd = stream.as_raw_fd();
                remove_fd_from_epoll(epfd, fd);
                close_fd(fd);
            }
        });
    }

    add_stream_to_master_list(stream_clone, streams);
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };

    let stream_list = guard.deref_mut();
    stream_list.push_back(stream);

    stats::conn_recv();
}

/// Adds a new fd to the epoll instance
fn add_fd_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_err() {
        let e = result.unwrap_err();
        error!("epoll::CtrlError during add: {}", e);
        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with fd from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for stream in list.iter() {
        if stream.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    if !found {
        return;
    }

    if index == 1 {
        list.pop_front();
    } else {
        let mut split = list.split_off(index - 1);
        split.pop_front();
        list.append(&mut split);
    }

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }
    stats::fd_closed();
}
<commit_msg>Fixed socketoptions<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::Error;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use std::collections::LinkedList;

use libc;
use libc::{c_int, c_void};
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use errno::errno;
use threadpool::ThreadPool;
use openssl::ssl::{SslStream, SslContext};
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

use stats;
use types::*;
use config::Config;

// We need to be able to access our resource pool from several methods
static mut thread_pool: *mut ThreadPool = 0 as *mut ThreadPool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Stream>::new()));

    // Resource pool
    let mut tp = ThreadPool::new(config.workers);
    unsafe {
        thread_pool = &mut tp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create and configure a new socket
    let mut socket = Socket::new(tcp_stream.into_raw_fd());
    let result = setup_new_socket(&mut socket);
    if result.is_err() {
        close_fd(socket.as_raw_fd());
        return;
    }

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let sock_fd = socket.as_raw_fd();
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    close_fd(sock_fd);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_fd_to_epoll(epfd, fd, streams.clone());
}

fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    let fd = event.data as RawFd;
    let find_result = try_find_stream_from_fd(streams.clone(), fd);
    if find_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);
    }

    let stream = find_result.unwrap();
    let read_event = if (event.events & READ_EVENT) > 0 {
        true
    } else {
        false
    };

    if read_event {
        handle_read_event(epfd, stream, streams, handler);
    } else {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
    }
}

fn try_find_stream_from_fd(streams: StreamList, fd: RawFd) -> Result<Stream, ()> {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for stream in list.iter() {
        if stream.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    let result = if found {
        if index == 1 {
            Ok(list.pop_front().unwrap())
        } else {
            let mut split = list.split_off(index - 1);
            let stream = split.pop_front().unwrap();
            list.append(&mut split);
            Ok(stream)
        }
    } else {
        Err(())
    };

    result
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: Stream, streams: StreamList, handler: Handler) {
    let fd = stream.as_raw_fd();

    let mut stream = stream;
    let recv_result = stream.recv();
    if recv_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
        return;
    }

    let mut msg_queue = stream.drain_rx_queue();
    for msg in msg_queue.drain(..) {
        let s = stream.clone();
        let sl = streams.clone();
        let h = handler.clone();

        if msg_is_stats_request(&msg) {
            handle_stats_request(&msg, epfd, s, sl);
        } else {
            unsafe {
                (*thread_pool).execute(move || {
                    let Handler(ptr) = h;
                    (*ptr).on_data_received(s, msg);
                });
            }
        }
    }

    add_stream_to_master_list(stream, streams);
}

#[inline]
fn msg_is_stats_request(msg: &[u8]) -> bool {
    if msg.len() == 6 && msg[0] == 0x04 && msg[1] == 0x04 {
        true
    } else {
        false
    }
}

fn handle_stats_request(buf: &[u8], epfd: RawFd, stream: Stream, streams: StreamList) {
    trace!("handle_stats_request");
    let stream_clone = stream.clone();
    let u8ptr: *const u8 = &buf[2] as *const _;
    let f32ptr: *const f32 = u8ptr as *const _;
    unsafe {
        let sec = *f32ptr;
        (*thread_pool).execute(move || {
            let stats_result = stats::as_serialized_buffer(sec);
            if stats_result.is_err() {
                error!("Retrieving stats");
                return;
            }

            let stats_buffer = stats_result.unwrap();

            let mut stream = stream;
            let send_result = stream.send(&stats_buffer[..]);
            if send_result.is_err() {
                error!("Writing to stream: {}", send_result.unwrap_err());
                let fd = stream.as_raw_fd();
                remove_fd_from_epoll(epfd, fd);
                close_fd(fd);
            }
        });
    }

    add_stream_to_master_list(stream_clone, streams);
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };

    let stream_list = guard.deref_mut();
    stream_list.push_back(stream);

    stats::conn_recv();
}

/// Adds a new fd to the epoll instance
fn add_fd_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_err() {
        let e = result.unwrap_err();
        error!("epoll::CtrlError during add: {}", e);
        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with fd from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for stream in list.iter() {
        if stream.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    if !found {
        return;
    }

    if index == 1 {
        list.pop_front();
    } else {
        let mut split = list.split_off(index - 1);
        split.pop_front();
        list.append(&mut split);
    }

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }
    stats::fd_closed();
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Cache, Load, LoadError};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given type. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  pub fn new(mut cps: Vec<Key<T>>) -> Self {
    cps.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: cps
    }
  }
}

impl<'a, T> Load<'a> for Spline<T> where T: Deserialize {
  type Args = ();

  fn load<P>(path: P, _: &mut Cache<'a>, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::new(keys))
  }
}

pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Implement this trait if your type is a key you want to sample with.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.

fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

/// Samplers can sample `Spline` by providing a `Time`. They should be mutable so that they can
/// maintain an internal state for optimization purposes.
#[derive(Copy, Clone, Default)]
pub struct Sampler {
  /// Playback cursor – gives the lower control point index of the current portion of the curve
  /// we’re sampling at.
  cursor: usize
}

impl Sampler {
  pub fn new() -> Self {
    Sampler {
      cursor: 0
    }
  }

  /// Sample a spline. If `random_sampling` is set, random sampling is generally faster than
  /// continuous sampling. Though, if you use continuous sampling, set `random_sampling` to `false`
	/// for max speed performance.
  pub fn sample<T>(&mut self, t: Time, param: &Spline<T>, random_sampling: bool) -> Option<T>
      where T: Interpolate {
    let i = if random_sampling {
      binary_search_lower_cp(&param.keys, t)
    } else {
      let i = around_search_lower_cp(&param.keys, self.cursor, t);

      // if we’ve found the index, replace the cursor to speed up next searches
      if let Some(cursor) = i {
        self.cursor = cursor;
      }

      i
    };

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &param.keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &param.keys[i+1];
        Some(if t < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &param.keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &param.keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= param.keys.len() - 2 {
          None
        } else {
          let cp1 = &param.keys[i+1];
          let cpm0 = &param.keys[i-1];
          let cpm1 = &param.keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }
}

// Normalize a time ([0;1]) given two control points.
fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time. Random version.
fn binary_search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let len = cps.len() as i32;
  if len < 2 {
    return None;
  }

  let mut down = 0;
  let mut up = len - 1;

  while down <= up {
    let m = (up + down) / 2;
    if m < 0 || m >= len - 1 {
      return None;
    }

    let cp0 = &cps[m as usize];

    if cp0.t > t {
      up = m-1;
    } else {
      let cp1 = &cps[(m+1) as usize];

      if t >= cp1.t {
        down = m+1;
      } else {
        return Some(m as usize)
      }
    }
  }

  None
}

// Find the lower control point corresponding to a given time. Continuous version. `i` is the last
// known found index.
fn around_search_lower_cp<T>(cps: &[Key<T>], mut i: usize, t: Time) -> Option<usize> {
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<commit_msg>Default interpolation.<commit_after>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Cache, Load, LoadError};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given type. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  pub fn new(mut cps: Vec<Key<T>>) -> Self {
    cps.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: cps
    }
  }
}

impl<'a, T> Load<'a> for Spline<T> where T: Deserialize {
  type Args = ();

  fn load<P>(path: P, _: &mut Cache<'a>, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::new(keys))
  }
}

pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Implement this trait if your type is a key you want to sample with.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.

fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

/// Samplers can sample `Spline` by providing a `Time`. They should be mutable so that they can
/// maintain an internal state for optimization purposes.
#[derive(Copy, Clone, Default)]
pub struct Sampler {
  /// Playback cursor – gives the lower control point index of the current portion of the curve
  /// we’re sampling at.
  cursor: usize
}

impl Sampler {
  pub fn new() -> Self {
    Sampler {
      cursor: 0
    }
  }

  /// Sample a spline. If `random_sampling` is set, random sampling is generally faster than
  /// continuous sampling. Though, if you use continuous sampling, set `random_sampling` to `false`
	/// for max speed performance.
  pub fn sample<T>(&mut self, t: Time, param: &Spline<T>, random_sampling: bool) -> Option<T>
      where T: Interpolate {
    let i = if random_sampling {
      binary_search_lower_cp(&param.keys, t)
    } else {
      let i = around_search_lower_cp(&param.keys, self.cursor, t);

      // if we’ve found the index, replace the cursor to speed up next searches
      if let Some(cursor) = i {
        self.cursor = cursor;
      }

      i
    };

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &param.keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &param.keys[i+1];
        Some(if t < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &param.keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &param.keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= param.keys.len() - 2 {
          None
        } else {
          let cp1 = &param.keys[i+1];
          let cpm0 = &param.keys[i-1];
          let cpm1 = &param.keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }
}

// Normalize a time ([0;1]) given two control points.
fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time. Random version.
fn binary_search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let len = cps.len() as i32;
  if len < 2 {
    return None;
  }

  let mut down = 0;
  let mut up = len - 1;

  while down <= up {
    let m = (up + down) / 2;
    if m < 0 || m >= len - 1 {
      return None;
    }

    let cp0 = &cps[m as usize];

    if cp0.t > t {
      up = m-1;
    } else {
      let cp1 = &cps[(m+1) as usize];

      if t >= cp1.t {
        down = m+1;
      } else {
        return Some(m as usize)
      }
    }
  }

  None
}

// Find the lower control point corresponding to a given time. Continuous version. `i` is the last
// known found index.
fn around_search_lower_cp<T>(cps: &[Key<T>], mut i: usize, t: Time) -> Option<usize> {
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<|endoftext|>


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

use address::Address;

/// A symbol within an executable or library. This is a named [address].
///
/// [address]: struct.Address.html
#[derive(Debug)]
pub struct Symbol {
    /// The [address] of this symbol.
    ///
    /// [address]: struct.Address.html
    pub address: Address,
    /// The name of this symbol.
    pub name: String,
}

impl Symbol {
    /// Construct a `Symbol`.
    pub fn new(address: Address, name: &str) -> Self {
        Symbol {
            address: address,
            name: name.to_owned(),
        }
    }
}
<commit_msg>Symbol's name is optional.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use address::Address;

/// A symbol within an executable or library. This is a named [address].
///
/// [address]: struct.Address.html
#[derive(Debug)]
pub struct Symbol {
    /// The [address] of this symbol.
    ///
    /// [address]: struct.Address.html
    pub address: Address,
    /// The name of this symbol.
    pub name: Option<String>,
}

impl Symbol {
    /// Construct a `Symbol`.
    pub fn new(address: Address, name: Option<&str>) -> Self {
        Symbol {
            address: address,
            name: name.map(|n| n.to_owned()),
        }
    }
}
<|endoftext|>


<commit_before>pub trait ToRef<'a> {
    type Ref: 'a;

    fn to_ref(&'a self) -> Self::Ref;
}

pub trait ToMut<'a>: ToRef<'a> {
    type Mut: 'a;

    fn to_mut(&'a mut self) -> Self::Mut;
}

impl<'a, T: 'a> ToRef<'a> for &'a T {
    type Ref = &'a T;

    fn to_ref(&'a self) -> Self::Ref {
        &*self
    }
}

impl<'a, T: 'a> ToRef<'a> for &'a mut T {
    type Ref = &'a T;

    fn to_ref(&'a self) -> Self::Ref {
        &*self
    }
}

impl<'a, T: 'a> ToMut<'a> for &'a mut T {
    type Mut = &'a mut T;

    fn to_mut(&'a mut self) -> Self::Mut {
        &mut *self
    }
}
<commit_msg>Add `ToRef` and `ToMut` impls for `()`<commit_after>pub trait ToRef<'a> {
    type Ref: 'a;

    fn to_ref(&'a self) -> Self::Ref;
}

pub trait ToMut<'a>: ToRef<'a> {
    type Mut: 'a;

    fn to_mut(&'a mut self) -> Self::Mut;
}

impl<'a, T: 'a> ToRef<'a> for &'a T {
    type Ref = &'a T;

    fn to_ref(&'a self) -> Self::Ref {
        &*self
    }
}

impl<'a, T: 'a> ToRef<'a> for &'a mut T {
    type Ref = &'a T;

    fn to_ref(&'a self) -> Self::Ref {
        &*self
    }
}

impl<'a, T: 'a> ToMut<'a> for &'a mut T {
    type Mut = &'a mut T;

    fn to_mut(&'a mut self) -> Self::Mut {
        &mut *self
    }
}

impl<'a> ToRef<'a> for () {
    type Ref = ();

    fn to_ref(&'a self) -> Self::Ref {
        ()
    }
}

impl<'a> ToMut<'a> for () {
    type Mut = ();

    fn to_mut(&'a mut self) -> Self::Mut {
        ()
    }
}
<|endoftext|>