<commit_before>//! Endpoint for searching and discovery functionality

use diesel::dsl::*;
use diesel_full_text_search::*;

use crate::controllers::cargo_prelude::*;
use crate::controllers::helpers::Paginate;
use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version};
use crate::schema::*;
use crate::util::errors::{bad_request, ChainError};
use crate::views::EncodableCrate;

use crate::models::krate::{canon_crate_name, ALL_COLUMNS};

/// Handles the `GET /crates` route.
/// Returns a list of crates. Called in a variety of scenarios in the
/// front end, including:
/// - Alphabetical listing of crates
/// - List of crates under a specific owner
/// - Listing a user's followed crates
///
/// Notes:
/// The different use cases this function covers is handled through passing
/// in parameters in the GET request.
///
/// We would like to stop adding functionality in here. It was built like
/// this to keep the number of database queries low, though given Rust's
/// low performance overhead, this is a soft goal to have, and can afford
/// more database transactions if it aids understandability.
///
/// All of the edge cases for this function are not currently covered
/// in testing, and if they fail, it is difficult to determine what
/// caused the break. In the future, we should look at splitting this
/// function out to cover the different use cases, and create unit tests
/// for them.
pub fn search(req: &mut dyn Request) -> AppResult<Response> {
    use diesel::sql_types::{Bool, Text};

    let conn = req.db_conn()?;
    let params = req.query();
    let sort = params.get("sort").map(|s| &**s);
    let include_yanked = params
        .get("include_yanked")
        .map(|s| s == "yes")
        .unwrap_or(true);

    let selection = (
        ALL_COLUMNS,
        false.into_sql::<Bool>(),
        recent_crate_downloads::downloads.nullable(),
    );
    let mut query = crates::table
        .left_join(recent_crate_downloads::table)
        .select(selection)
        .into_boxed();

    if let Some(q_string) = params.get("q") {
        if !q_string.is_empty() {
            let sort = params.get("sort").map(|s| &**s).unwrap_or("relevance");

            let q = sql::<TsQuery>("plainto_tsquery('english', ")
                .bind::<Text, _>(q_string)
                .sql(")");
            query = query.filter(
                q.clone()
                    .matches(crates::textsearchable_index_col)
                    .or(Crate::loosly_matches_name(&q_string)),
            );

            query = query.select((
                ALL_COLUMNS,
                Crate::with_name(q_string),
                recent_crate_downloads::downloads.nullable(),
            ));
            query = query.order(Crate::with_name(q_string).desc());

            if sort == "relevance" {
                let rank = ts_rank_cd(crates::textsearchable_index_col, q);
                query = query.then_order_by(rank.desc())
            }
        }
    }

    if let Some(cat) = params.get("category") {
        query = query.filter(
            crates::id.eq_any(
                crates_categories::table
                    .select(crates_categories::crate_id)
                    .inner_join(categories::table)
                    .filter(
                        categories::slug
                            .eq(cat)
                            .or(categories::slug.like(format!("{}::%", cat))),
                    ),
            ),
        );
    }

    if let Some(kws) = params.get("all_keywords") {
        use diesel::sql_types::Array;
        sql_function!(#[aggregate] fn array_agg<T>(x: T) -> Array<T>);

        let names: Vec<_> = kws
            .split_whitespace()
            .map(|name| name.to_lowercase())
            .collect();

        query = query.filter(
            // FIXME: Just use `.contains` in Diesel 2.0
            // https://github.com/diesel-rs/diesel/issues/2066
            Contains::new(
                crates_keywords::table
                    .inner_join(keywords::table)
                    .filter(crates_keywords::crate_id.eq(crates::id))
                    .select(array_agg(keywords::keyword))
                    .single_value(),
                names.into_sql::<Array<Text>>(),
            ),
        );
    } else if let Some(kw) = params.get("keyword") {
        query = query.filter(
            crates::id.eq_any(
                crates_keywords::table
                    .select(crates_keywords::crate_id)
                    .inner_join(keywords::table)
                    .filter(crate::lower(keywords::keyword).eq(crate::lower(kw))),
            ),
        );
    } else if let Some(letter) = params.get("letter") {
        let pattern = format!(
            "{}%",
            letter
                .chars()
                .next()
                .chain_error(|| bad_request("letter value must contain 1 character"))?
                .to_lowercase()
                .collect::<String>()
        );
        query = query.filter(canon_crate_name(crates::name).like(pattern));
    } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::<i32>().ok()) {
        query = query.filter(
            crates::id.eq_any(
                CrateOwner::by_owner_kind(OwnerKind::User)
                    .select(crate_owners::crate_id)
                    .filter(crate_owners::owner_id.eq(user_id)),
            ),
        );
    } else if let Some(team_id) = params.get("team_id").and_then(|s| s.parse::<i32>().ok()) {
        query = query.filter(
            crates::id.eq_any(
                CrateOwner::by_owner_kind(OwnerKind::Team)
                    .select(crate_owners::crate_id)
                    .filter(crate_owners::owner_id.eq(team_id)),
            ),
        );
    } else if params.get("following").is_some() {
        let user_id = req.authenticate(&conn)?.user_id();
        query = query.filter(
            crates::id.eq_any(
                follows::table
                    .select(follows::crate_id)
                    .filter(follows::user_id.eq(user_id)),
            ),
        );
    }

    if !include_yanked {
        query = query.filter(exists(
            versions::table
                .filter(versions::crate_id.eq(crates::id))
                .filter(versions::yanked.eq(false)),
        ));
    }

    if sort == Some("downloads") {
        query = query.then_order_by(crates::downloads.desc())
    } else if sort == Some("recent-downloads") {
        query = query.then_order_by(recent_crate_downloads::downloads.desc().nulls_last())
    } else if sort == Some("recent-updates") {
        query = query.order(crates::updated_at.desc());
    } else {
        query = query.then_order_by(crates::name.asc())
    }

    let data = query
        .paginate(&req.query())?
        .load::<(Crate, bool, Option<i64>)>(&*conn)?;
    let total = data.total();

    let next_page = data.next_page_params().map(|p| req.query_with_params(p));
    let prev_page = data.prev_page_params().map(|p| req.query_with_params(p));

    let perfect_matches = data.iter().map(|&(_, b, _)| b).collect::<Vec<_>>();
    let recent_downloads = data
        .iter()
        .map(|&(_, _, s)| s.unwrap_or(0))
        .collect::<Vec<_>>();
    let crates = data.into_iter().map(|(c, _, _)| c).collect::<Vec<_>>();

    let versions = crates
        .versions()
        .load::<Version>(&*conn)?
        .grouped_by(&crates)
        .into_iter()
        .map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))));

    let badges = CrateBadge::belonging_to(&crates)
        .select((badges::crate_id, badges::all_columns))
        .load::<CrateBadge>(&*conn)?
        .grouped_by(&crates)
        .into_iter()
        .map(|badges| badges.into_iter().map(|cb| cb.badge).collect());

    let crates = versions
        .zip(crates)
        .zip(perfect_matches)
        .zip(recent_downloads)
        .zip(badges)
        .map(
            |((((max_version, krate), perfect_match), recent_downloads), badges)| {
                krate.minimal_encodable(
                    &max_version,
                    Some(badges),
                    perfect_match,
                    Some(recent_downloads),
                )
            },
        )
        .collect();

    #[derive(Serialize)]
    struct R {
        crates: Vec<EncodableCrate>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        total: Option<i64>,
        next_page: Option<String>,
        prev_page: Option<String>,
    }

    Ok(req.json(&R {
        crates,
        meta: Meta {
            total,
            next_page,
            prev_page,
        },
    }))
}

diesel_infix_operator!(Contains, "@>");
<commit_msg>Use read-only replica pool for search endpoint<commit_after>//! Endpoint for searching and discovery functionality

use diesel::dsl::*;
use diesel_full_text_search::*;

use crate::controllers::cargo_prelude::*;
use crate::controllers::helpers::Paginate;
use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version};
use crate::schema::*;
use crate::util::errors::{bad_request, ChainError};
use crate::views::EncodableCrate;

use crate::models::krate::{canon_crate_name, ALL_COLUMNS};

/// Handles the `GET /crates` route.
/// Returns a list of crates. Called in a variety of scenarios in the
/// front end, including:
/// - Alphabetical listing of crates
/// - List of crates under a specific owner
/// - Listing a user's followed crates
///
/// Notes:
/// The different use cases this function covers is handled through passing
/// in parameters in the GET request.
///
/// We would like to stop adding functionality in here. It was built like
/// this to keep the number of database queries low, though given Rust's
/// low performance overhead, this is a soft goal to have, and can afford
/// more database transactions if it aids understandability.
///
/// All of the edge cases for this function are not currently covered
/// in testing, and if they fail, it is difficult to determine what
/// caused the break. In the future, we should look at splitting this
/// function out to cover the different use cases, and create unit tests
/// for them.
pub fn search(req: &mut dyn Request) -> AppResult<Response> {
    use diesel::sql_types::{Bool, Text};

    let conn = req.db_read_only()?;
    let params = req.query();
    let sort = params.get("sort").map(|s| &**s);
    let include_yanked = params
        .get("include_yanked")
        .map(|s| s == "yes")
        .unwrap_or(true);

    let selection = (
        ALL_COLUMNS,
        false.into_sql::<Bool>(),
        recent_crate_downloads::downloads.nullable(),
    );
    let mut query = crates::table
        .left_join(recent_crate_downloads::table)
        .select(selection)
        .into_boxed();

    if let Some(q_string) = params.get("q") {
        if !q_string.is_empty() {
            let sort = params.get("sort").map(|s| &**s).unwrap_or("relevance");

            let q = sql::<TsQuery>("plainto_tsquery('english', ")
                .bind::<Text, _>(q_string)
                .sql(")");
            query = query.filter(
                q.clone()
                    .matches(crates::textsearchable_index_col)
                    .or(Crate::loosly_matches_name(&q_string)),
            );

            query = query.select((
                ALL_COLUMNS,
                Crate::with_name(q_string),
                recent_crate_downloads::downloads.nullable(),
            ));
            query = query.order(Crate::with_name(q_string).desc());

            if sort == "relevance" {
                let rank = ts_rank_cd(crates::textsearchable_index_col, q);
                query = query.then_order_by(rank.desc())
            }
        }
    }

    if let Some(cat) = params.get("category") {
        query = query.filter(
            crates::id.eq_any(
                crates_categories::table
                    .select(crates_categories::crate_id)
                    .inner_join(categories::table)
                    .filter(
                        categories::slug
                            .eq(cat)
                            .or(categories::slug.like(format!("{}::%", cat))),
                    ),
            ),
        );
    }

    if let Some(kws) = params.get("all_keywords") {
        use diesel::sql_types::Array;
        sql_function!(#[aggregate] fn array_agg<T>(x: T) -> Array<T>);

        let names: Vec<_> = kws
            .split_whitespace()
            .map(|name| name.to_lowercase())
            .collect();

        query = query.filter(
            // FIXME: Just use `.contains` in Diesel 2.0
            // https://github.com/diesel-rs/diesel/issues/2066
            Contains::new(
                crates_keywords::table
                    .inner_join(keywords::table)
                    .filter(crates_keywords::crate_id.eq(crates::id))
                    .select(array_agg(keywords::keyword))
                    .single_value(),
                names.into_sql::<Array<Text>>(),
            ),
        );
    } else if let Some(kw) = params.get("keyword") {
        query = query.filter(
            crates::id.eq_any(
                crates_keywords::table
                    .select(crates_keywords::crate_id)
                    .inner_join(keywords::table)
                    .filter(crate::lower(keywords::keyword).eq(crate::lower(kw))),
            ),
        );
    } else if let Some(letter) = params.get("letter") {
        let pattern = format!(
            "{}%",
            letter
                .chars()
                .next()
                .chain_error(|| bad_request("letter value must contain 1 character"))?
                .to_lowercase()
                .collect::<String>()
        );
        query = query.filter(canon_crate_name(crates::name).like(pattern));
    } else if let Some(user_id) = params.get("user_id").and_then(|s| s.parse::<i32>().ok()) {
        query = query.filter(
            crates::id.eq_any(
                CrateOwner::by_owner_kind(OwnerKind::User)
                    .select(crate_owners::crate_id)
                    .filter(crate_owners::owner_id.eq(user_id)),
            ),
        );
    } else if let Some(team_id) = params.get("team_id").and_then(|s| s.parse::<i32>().ok()) {
        query = query.filter(
            crates::id.eq_any(
                CrateOwner::by_owner_kind(OwnerKind::Team)
                    .select(crate_owners::crate_id)
                    .filter(crate_owners::owner_id.eq(team_id)),
            ),
        );
    } else if params.get("following").is_some() {
        let user_id = req.authenticate(&conn)?.user_id();
        query = query.filter(
            crates::id.eq_any(
                follows::table
                    .select(follows::crate_id)
                    .filter(follows::user_id.eq(user_id)),
            ),
        );
    }

    if !include_yanked {
        query = query.filter(exists(
            versions::table
                .filter(versions::crate_id.eq(crates::id))
                .filter(versions::yanked.eq(false)),
        ));
    }

    if sort == Some("downloads") {
        query = query.then_order_by(crates::downloads.desc())
    } else if sort == Some("recent-downloads") {
        query = query.then_order_by(recent_crate_downloads::downloads.desc().nulls_last())
    } else if sort == Some("recent-updates") {
        query = query.order(crates::updated_at.desc());
    } else {
        query = query.then_order_by(crates::name.asc())
    }

    let data = query
        .paginate(&req.query())?
        .load::<(Crate, bool, Option<i64>)>(&*conn)?;
    let total = data.total();

    let next_page = data.next_page_params().map(|p| req.query_with_params(p));
    let prev_page = data.prev_page_params().map(|p| req.query_with_params(p));

    let perfect_matches = data.iter().map(|&(_, b, _)| b).collect::<Vec<_>>();
    let recent_downloads = data
        .iter()
        .map(|&(_, _, s)| s.unwrap_or(0))
        .collect::<Vec<_>>();
    let crates = data.into_iter().map(|(c, _, _)| c).collect::<Vec<_>>();

    let versions = crates
        .versions()
        .load::<Version>(&*conn)?
        .grouped_by(&crates)
        .into_iter()
        .map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num))));

    let badges = CrateBadge::belonging_to(&crates)
        .select((badges::crate_id, badges::all_columns))
        .load::<CrateBadge>(&*conn)?
        .grouped_by(&crates)
        .into_iter()
        .map(|badges| badges.into_iter().map(|cb| cb.badge).collect());

    let crates = versions
        .zip(crates)
        .zip(perfect_matches)
        .zip(recent_downloads)
        .zip(badges)
        .map(
            |((((max_version, krate), perfect_match), recent_downloads), badges)| {
                krate.minimal_encodable(
                    &max_version,
                    Some(badges),
                    perfect_match,
                    Some(recent_downloads),
                )
            },
        )
        .collect();

    #[derive(Serialize)]
    struct R {
        crates: Vec<EncodableCrate>,
        meta: Meta,
    }
    #[derive(Serialize)]
    struct Meta {
        total: Option<i64>,
        next_page: Option<String>,
        prev_page: Option<String>,
    }

    Ok(req.json(&R {
        crates,
        meta: Meta {
            total,
            next_page,
            prev_page,
        },
    }))
}

diesel_infix_operator!(Contains, "@>");
<|endoftext|>


<commit_before>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    0b000001 => verbatim(input, bits_per_sample, block_size),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<commit_msg>Add `coding_method` parser<commit_after>use nom::{
  IResult,
  ErrorCode, Err,
  Needed,
};

use frame;
use frame::subframe;
use frame::SubFrame;
use frame::subframe::{CodingMethod, PartitionedRiceContents};

fn leading_zeros(input: (&[u8], usize)) -> IResult<(&[u8], usize), u32> {
  let (bytes, mut offset) = input;

  let mut index     = 0;
  let mut count     = 0;
  let mut is_parsed = false;
  let bytes_len     = bytes.len();

  for i in 0..bytes_len {
    // Clear the number of offset bits
    let byte  = bytes[i] << offset;
    let zeros = byte.leading_zeros() as usize;

    if byte > 0 {
      index     = i;
      is_parsed = true;
      count    += zeros;
      offset   += zeros + 1;

      if offset >= 8 {
        index  += 1;
        offset -= 8;
      }

      break;
    } else {
      count += zeros - offset;
      offset = 0;
    }
  }

  if is_parsed {
    IResult::Done((&bytes[index..], offset), count as u32)
  } else if index + 1 > bytes_len {
    IResult::Incomplete(Needed::Size(index + 1))
  } else {
    IResult::Error(Err::Position(ErrorCode::TakeUntil as u32, bytes))
  }
}

pub fn subframe_parser<'a>(input: (&'a [u8], usize),
                           frame_header: &frame::Header)
                           -> IResult<'a, (&'a [u8], usize), SubFrame> {
  chain!(input,
    subframe_header: header ~
    wasted_bits: map!(
      cond!(subframe_header.1, leading_zeros),
      |option: Option<u32>| option.map_or(0, |zeros| zeros + 1)
    ) ~
    subframe_data: apply!(data, frame_header, subframe_header.0 as usize,
                          wasted_bits as usize),
    || {
      SubFrame {
        data: subframe_data,
        wasted_bits: wasted_bits,
      }
    }
  )
}

fn header(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, bool)> {
  match take_bits!(input, u8, 8) {
    IResult::Done(i, byte)    => {
      let is_valid        = (byte >> 7) == 0;
      let subframe_type   = (byte >> 1) & 0b111111;
      let has_wasted_bits = (byte & 0b01) == 1;

      if is_valid {
        IResult::Done(i, (subframe_type, has_wasted_bits))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input.0))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn data<'a>(input: (&'a [u8], usize),
            frame_header: &frame::Header,
            subframe_type: usize,
            wasted_bits: usize)
            -> IResult<'a, (&'a [u8], usize), subframe::Data> {
  let bits_per_sample = frame_header.bits_per_sample - wasted_bits;
  let block_size      = frame_header.block_size as usize;

  match subframe_type {
    0b000000 => constant(input, bits_per_sample),
    0b000001 => verbatim(input, bits_per_sample, block_size),
    _        => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0))
  }
}

fn constant(input: (&[u8], usize), bits_per_sample: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  map!(input, take_bits!(i32, bits_per_sample), subframe::Data::Constant)
}

fn verbatim(input: (&[u8], usize), bits_per_sample: usize, block_size: usize)
            -> IResult<(&[u8], usize), subframe::Data> {
  // TODO: Use nom's `count!` macro as soon as it is fixed for bit parsers.
  map!(input, count_bits!(take_bits!(i32, bits_per_sample), block_size),
       subframe::Data::Verbatim)
}

fn coding_method(input: (&[u8], usize))
                 -> IResult<(&[u8], usize), CodingMethod> {
  match take_bits!(input, u8, 2) {
    IResult::Done(i, method)  => {
      match method {
        0 => IResult::Done(i, CodingMethod::PartitionedRice),
        1 => IResult::Done(i, CodingMethod::PartitionedRice2),
        _ => IResult::Error(Err::Position(ErrorCode::Alt as u32, input.0)),
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn rice_partition(input: (&[u8], usize),
                  partition_order: u32,
                  predictor_order: usize,
                  block_size: usize,
                  method: CodingMethod)
                  -> IResult<(&[u8], usize),
                             (subframe::EntropyCodingMethod, Vec<i32>)> {
  let (param_size, escape_code) = match method {
    CodingMethod::PartitionedRice  => (4, 0b1111),
    CodingMethod::PartitionedRice2 => (5, 0b11111),
  };

  // Adjust block size to not include allocation for warm up samples
  let residual_size = block_size - predictor_order;

  let mut mut_input = input;
  let mut residual  = Vec::with_capacity(residual_size);
  let mut sample    = 0;
  let mut contents  = PartitionedRiceContents::new(partition_order);

  unsafe { residual.set_len(residual_size) }

  let partitions = 2_usize.pow(partition_order);

  for partition in 0..partitions {
    let offset = if partition_order == 0 {
      block_size - predictor_order
    } else if partition > 0 {
      block_size / partitions
    } else {
      (block_size / partitions) - predictor_order
    };
    let start = sample;
    let end   = sample + offset;

    let result = chain!(mut_input,
      rice_parameter: take_bits!(u32, param_size) ~
      size: cond!(rice_parameter == escape_code, take_bits!(usize, 5)) ~
      data: apply!(residual_data,
        size, rice_parameter,
        &mut contents.raw_bits[partition],
        &mut residual[start..end]
      ),
      || { rice_parameter }
    );

    match result {
      IResult::Done(i, parameter) => {
        mut_input = i;
        sample    = end;

        contents.parameters[partition] = parameter;
      }
      IResult::Error(error)       => return IResult::Error(error),
      IResult::Incomplete(need)   => return IResult::Incomplete(need),
    }
  }

  let entropy_coding_method = subframe::EntropyCodingMethod {
    method_type: method,
    data: subframe::PartitionedRice {
      order: partition_order,
      contents: contents,
    },
  };

  IResult::Done(mut_input, (entropy_coding_method, residual))
}

fn residual_data<'a>(input: (&'a [u8], usize),
                     option: Option<usize>,
                     rice_parameter: u32,
                     raw_bit: &mut u32,
                     samples: &mut [i32])
                     -> IResult<'a, (&'a [u8], usize), ()> {
  if let Some(size) = option {
    unencoded_residuals(input, size, raw_bit, samples)
  } else {
    encoded_residuals(input, rice_parameter, raw_bit, samples)
  }
}

fn unencoded_residuals<'a>(input: (&'a [u8], usize),
                           bits_per_sample: usize,
                           raw_bit: &mut u32,
                           samples: &mut [i32])
                           -> IResult<'a, (&'a[u8], usize), ()> {
  *raw_bit = bits_per_sample as u32;

  count_slice!(input, take_bits!(i32, bits_per_sample), &mut samples[..])
}

fn encoded_residuals<'a>(input: (&'a [u8], usize),
                         parameter: u32,
                         raw_bit: &mut u32,
                         samples: &mut [i32])
                         -> IResult<'a, (&'a[u8], usize), ()> {
  let length = samples.len();

  let mut count     = 0;
  let mut is_error  = false;
  let mut mut_input = input;

  *raw_bit = 0;

  for sample in samples {
    let result = chain!(mut_input,
      quotient: leading_zeros ~
      remainder: take_bits!(u32, parameter as usize),
      || {
        let value = quotient * parameter + remainder;

        ((value as i32) >> 1) ^ -((value as i32) & 1)
      });

    match result {
      IResult::Done(i, value) => {
        mut_input = i;
        count    += 1;

        *sample = value
      }
      IResult::Error(_)       => {
        is_error = true;

        break;
      }
      IResult::Incomplete(_)  => break,
    }
  }

  if is_error {
    IResult::Error(Err::Position(ErrorCode::Count as u32, input.0))
  } else if count == length {
    IResult::Done(mut_input, ())
  } else {
    IResult::Incomplete(Needed::Unknown)
  }
}
<|endoftext|>


<commit_before>use chrono::Utc;
use crate::constants::{self, OpCode};
use crate::gateway::{CurrentPresence, WsClient};
use crate::internal::prelude::*;
use crate::internal::ws_impl::SenderExt;
use crate::model::id::GuildId;
use serde_json::json;
use std::env::consts;
use log::{debug, trace};

pub trait WebSocketGatewayClientExt {
    fn send_chunk_guilds<It>(
        &mut self,
        guild_ids: It,
        shard_info: &[u64; 2],
        limit: Option<u16>,
        query: Option<&str>,
    ) -> Result<()> where It: IntoIterator<Item=GuildId>;

    fn send_heartbeat(&mut self, shard_info: &[u64; 2], seq: Option<u64>)
        -> Result<()>;

    fn send_identify(&mut self, shard_info: &[u64; 2], token: &str, guild_subscriptions: bool)
        -> Result<()>;

    fn send_presence_update(
        &mut self,
        shard_info: &[u64; 2],
        current_presence: &CurrentPresence,
    ) -> Result<()>;

    fn send_resume(
        &mut self,
        shard_info: &[u64; 2],
        session_id: &str,
        seq: u64,
        token: &str,
    ) -> Result<()>;
}

impl WebSocketGatewayClientExt for WsClient {
    fn send_chunk_guilds<It>(
        &mut self,
        guild_ids: It,
        shard_info: &[u64; 2],
        limit: Option<u16>,
        query: Option<&str>,
    ) -> Result<()> where It: IntoIterator<Item=GuildId> {
        debug!("[Shard {:?}] Requesting member chunks", shard_info);

        self.send_json(&json!({
            "op": OpCode::GetGuildMembers.num(),
            "d": {
                "guild_id": guild_ids.into_iter().map(|x| x.as_ref().0).collect::<Vec<u64>>(),
                "limit": limit.unwrap_or(0),
                "query": query.unwrap_or(""),
            },
        })).map_err(From::from)
    }

    fn send_heartbeat(&mut self, shard_info: &[u64; 2], seq: Option<u64>)
        -> Result<()> {
        trace!("[Shard {:?}] Sending heartbeat d: {:?}", shard_info, seq);

        self.send_json(&json!({
            "d": seq,
            "op": OpCode::Heartbeat.num(),
        })).map_err(From::from)
    }

    fn send_identify(&mut self, shard_info: &[u64; 2], token: &str, guild_subscriptions: bool)
        -> Result<()> {
        debug!("[Shard {:?}] Identifying", shard_info);

        self.send_json(&json!({
            "op": OpCode::Identify.num(),
            "d": {
                "compression": true,
                "large_threshold": constants::LARGE_THRESHOLD,
                "guild_subscriptions": guild_subscriptions,
                "shard": shard_info,
                "token": token,
                "v": constants::GATEWAY_VERSION,
                "properties": {
                    "$browser": "serenity",
                    "$device": "serenity",
                    "$os": consts::OS,
                },
            },
        }))
    }

    fn send_presence_update(
        &mut self,
        shard_info: &[u64; 2],
        current_presence: &CurrentPresence,
    ) -> Result<()> {
        let &(ref activity, ref status) = current_presence;
        let now = Utc::now().timestamp() as u64;

        debug!("[Shard {:?}] Sending presence update", shard_info);

        self.send_json(&json!({
            "op": OpCode::StatusUpdate.num(),
            "d": {
                "afk": false,
                "since": now,
                "status": status.name(),
                "game": activity.as_ref().map(|x| json!({
                    "name": x.name,
                    "type": x.kind,
                    "url": x.url,
                })),
            },
        }))
    }

    fn send_resume(
        &mut self,
        shard_info: &[u64; 2],
        session_id: &str,
        seq: u64,
        token: &str,
    ) -> Result<()> {
        debug!("[Shard {:?}] Sending resume; seq: {}", shard_info, seq);

        self.send_json(&json!({
            "op": OpCode::Resume.num(),
            "d": {
                "session_id": session_id,
                "seq": seq,
                "token": token,
            },
        })).map_err(From::from)
    }
}
<commit_msg>Remedy a typo<commit_after>use chrono::Utc;
use crate::constants::{self, OpCode};
use crate::gateway::{CurrentPresence, WsClient};
use crate::internal::prelude::*;
use crate::internal::ws_impl::SenderExt;
use crate::model::id::GuildId;
use serde_json::json;
use std::env::consts;
use log::{debug, trace};

pub trait WebSocketGatewayClientExt {
    fn send_chunk_guilds<It>(
        &mut self,
        guild_ids: It,
        shard_info: &[u64; 2],
        limit: Option<u16>,
        query: Option<&str>,
    ) -> Result<()> where It: IntoIterator<Item=GuildId>;

    fn send_heartbeat(&mut self, shard_info: &[u64; 2], seq: Option<u64>)
        -> Result<()>;

    fn send_identify(&mut self, shard_info: &[u64; 2], token: &str, guild_subscriptions: bool)
        -> Result<()>;

    fn send_presence_update(
        &mut self,
        shard_info: &[u64; 2],
        current_presence: &CurrentPresence,
    ) -> Result<()>;

    fn send_resume(
        &mut self,
        shard_info: &[u64; 2],
        session_id: &str,
        seq: u64,
        token: &str,
    ) -> Result<()>;
}

impl WebSocketGatewayClientExt for WsClient {
    fn send_chunk_guilds<It>(
        &mut self,
        guild_ids: It,
        shard_info: &[u64; 2],
        limit: Option<u16>,
        query: Option<&str>,
    ) -> Result<()> where It: IntoIterator<Item=GuildId> {
        debug!("[Shard {:?}] Requesting member chunks", shard_info);

        self.send_json(&json!({
            "op": OpCode::GetGuildMembers.num(),
            "d": {
                "guild_id": guild_ids.into_iter().map(|x| x.as_ref().0).collect::<Vec<u64>>(),
                "limit": limit.unwrap_or(0),
                "query": query.unwrap_or(""),
            },
        })).map_err(From::from)
    }

    fn send_heartbeat(&mut self, shard_info: &[u64; 2], seq: Option<u64>)
        -> Result<()> {
        trace!("[Shard {:?}] Sending heartbeat d: {:?}", shard_info, seq);

        self.send_json(&json!({
            "d": seq,
            "op": OpCode::Heartbeat.num(),
        })).map_err(From::from)
    }

    fn send_identify(&mut self, shard_info: &[u64; 2], token: &str, guild_subscriptions: bool)
        -> Result<()> {
        debug!("[Shard {:?}] Identifying", shard_info);

        self.send_json(&json!({
            "op": OpCode::Identify.num(),
            "d": {
                "compress": true,
                "large_threshold": constants::LARGE_THRESHOLD,
                "guild_subscriptions": guild_subscriptions,
                "shard": shard_info,
                "token": token,
                "v": constants::GATEWAY_VERSION,
                "properties": {
                    "$browser": "serenity",
                    "$device": "serenity",
                    "$os": consts::OS,
                },
            },
        }))
    }

    fn send_presence_update(
        &mut self,
        shard_info: &[u64; 2],
        current_presence: &CurrentPresence,
    ) -> Result<()> {
        let &(ref activity, ref status) = current_presence;
        let now = Utc::now().timestamp() as u64;

        debug!("[Shard {:?}] Sending presence update", shard_info);

        self.send_json(&json!({
            "op": OpCode::StatusUpdate.num(),
            "d": {
                "afk": false,
                "since": now,
                "status": status.name(),
                "game": activity.as_ref().map(|x| json!({
                    "name": x.name,
                    "type": x.kind,
                    "url": x.url,
                })),
            },
        }))
    }

    fn send_resume(
        &mut self,
        shard_info: &[u64; 2],
        session_id: &str,
        seq: u64,
        token: &str,
    ) -> Result<()> {
        debug!("[Shard {:?}] Sending resume; seq: {}", shard_info, seq);

        self.send_json(&json!({
            "op": OpCode::Resume.num(),
            "d": {
                "session_id": session_id,
                "seq": seq,
                "token": token,
            },
        })).map_err(From::from)
    }
}
<|endoftext|>


<commit_before>use common::*;

use holmes::client::*;
use holmes::native_types::*;
use holmes::native_types::HType::*;
use holmes::native_types::HValue::*;
use holmes::native_types::MatchExpr::*;

#[test]
pub fn one_step() {
  server_single(&|&: client : &mut Client| {
    let test_pred = "test_pred".to_string();
    assert!(&client.new_predicate(&Predicate {
      name  : test_pred.clone(),
      types : vec![HString, Blob, UInt64]
    }));
    println!("Created predicate");
    &client.new_fact(&Fact {
      pred_name : test_pred.clone(),
      args : vec![HStringV("foo".to_string()),
                  BlobV(vec![3;3]),
                  UInt64V(7)
                 ]
    }).unwrap();
    println!("Created fact");
    let rule = Rule {
      head : Clause {
        pred_name : test_pred.clone(),
        args : vec![HConst(HStringV("bar".to_string())),
                    HConst(BlobV(vec![2;2])),
                    Var(0)]
      },
      body : vec![Clause {
        pred_name : test_pred.clone(),
        args : vec![HConst(HStringV("foo".to_string())),
                    Unbound,
                    Var(0)]
        }]
      };
    &client.new_rule(&rule).unwrap();
    println!("Added rule");
    assert_eq!(&client.derive(vec![&Clause {
      pred_name : test_pred,
      args : vec![HConst(HStringV("bar".to_string())),
                  Unbound,
                  Var(0)]
    }]).unwrap(), &vec![vec![UInt64V(7)]]);
    println!("Entering cleanup");
  })
}

<commit_msg>Remove debugging prints<commit_after>use common::*;

use holmes::client::*;
use holmes::native_types::*;
use holmes::native_types::HType::*;
use holmes::native_types::HValue::*;
use holmes::native_types::MatchExpr::*;

#[test]
pub fn one_step() {
  server_single(&|&: client : &mut Client| {
    let test_pred = "test_pred".to_string();
    assert!(&client.new_predicate(&Predicate {
      name  : test_pred.clone(),
      types : vec![HString, Blob, UInt64]
    }));
    &client.new_fact(&Fact {
      pred_name : test_pred.clone(),
      args : vec![HStringV("foo".to_string()),
                  BlobV(vec![3;3]),
                  UInt64V(7)
                 ]
    }).unwrap();
    let rule = Rule {
      head : Clause {
        pred_name : test_pred.clone(),
        args : vec![HConst(HStringV("bar".to_string())),
                    HConst(BlobV(vec![2;2])),
                    Var(0)]
      },
      body : vec![Clause {
        pred_name : test_pred.clone(),
        args : vec![HConst(HStringV("foo".to_string())),
                    Unbound,
                    Var(0)]
        }]
      };
    &client.new_rule(&rule).unwrap();
    assert_eq!(&client.derive(vec![&Clause {
      pred_name : test_pred,
      args : vec![HConst(HStringV("bar".to_string())),
                  Unbound,
                  Var(0)]
    }]).unwrap(), &vec![vec![UInt64V(7)]]);
  })
}

<|endoftext|>


<commit_before><commit_msg>Use set_one in div_rem<commit_after><|endoftext|>


<commit_before>//! Determining which types for which we can emit `#[derive(Debug)]`.
use super::MonotoneFramework;
use ir::context::{BindgenContext, ItemId};
use ir::item::ItemSet;
use std::collections::HashSet;
use std::collections::HashMap;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
use ir::traversal::Trace;
use ir::comp::FieldMethods;
use ir::layout::Layout;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;

/// An analysis that finds for each IR item whether debug cannot be derived.
///
/// We use the monotone constraint function `cannot_derive_debug`, defined as
/// follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
///   type and check whether it can be derived using trivial checks.
/// * If T is Array type, debug cannot be derived if the length of the array is
///   larger than the limit or the type of data the array contains cannot derive
///   debug.
/// * If T is a type alias, a templated alias or an indirection to another type,
///   debug cannot be derived if the type T refers to cannot be derived debug.
/// * If T is a compound type, debug cannot be derived if any of its base member
///   or field cannot be derived debug.
/// * If T is a pointer, T cannot be derived debug if T is a function pointer
///   and the function signature cannot be derived debug.
/// * If T is an instantiation of an abstract template definition, T cannot be
///   derived debug if any of the template arguments or template definition
///   cannot derive debug.
#[derive(Debug, Clone)]
pub struct CannotDeriveDebug<'ctx, 'gen>
    where 'gen: 'ctx
{
    ctx: &'ctx BindgenContext<'gen>,

    // The incremental result of this analysis's computation. Everything in this
    // set cannot derive debug.
    cannot_derive_debug: HashSet<ItemId>,

    // Dependencies saying that if a key ItemId has been inserted into the
    // `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
    // considered again.
    //
    // This is a subset of the natural IR graph with reversed edges, where we
    // only include the edges from the IR graph that can affect whether a type
    // can derive debug or not.
    dependencies: HashMap<ItemId, Vec<ItemId>>,
}

impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
    fn consider_edge(kind: EdgeKind) -> bool {
        match kind {
            // These are the only edges that can affect whether a type can derive
            // debug or not.
            EdgeKind::BaseMember |
            EdgeKind::Field |
            EdgeKind::TypeReference |
            EdgeKind::VarType |
            EdgeKind::TemplateArgument |
            EdgeKind::TemplateDeclaration |
            EdgeKind::TemplateParameterDefinition => true,

            EdgeKind::Constructor |
            EdgeKind::Destructor |
            EdgeKind::FunctionReturn |
            EdgeKind::FunctionParameter |
            EdgeKind::InnerType |
            EdgeKind::InnerVar |
            EdgeKind::Method => false,
            EdgeKind::Generic => false,
        }
    }

    fn insert(&mut self, id: ItemId) -> bool {
        let was_already_in = self.cannot_derive_debug.insert(id);
        assert!(
            was_already_in,
            format!("We shouldn't try and insert twice because if it was already in the set, \
             `constrain` would have exited early.: {:?}", id)
        );
        true
    }
}

impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
    type Node = ItemId;
    type Extra = &'ctx BindgenContext<'gen>;
    type Output = HashSet<ItemId>;

    fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
        let cannot_derive_debug = HashSet::new();
        let mut dependencies = HashMap::new();
        let whitelisted_items: HashSet<_> = ctx.whitelisted_items().collect();

        let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter()
            .cloned()
            .flat_map(|i| {
                let mut reachable = vec![i];
                i.trace(ctx, &mut |s, _| {
                    reachable.push(s);
                }, &());
                reachable
            })
            .collect();

        for item in whitelisted_and_blacklisted_items {
            dependencies.entry(item).or_insert(vec![]);

            {
                // We reverse our natural IR graph edges to find dependencies
                // between nodes.
                item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
                    if Self::consider_edge(edge_kind) {
                        dependencies.entry(sub_item)
                            .or_insert(vec![])
                            .push(item);
                    }
                }, &());
            }
        }

        CannotDeriveDebug {
            ctx: ctx,
            cannot_derive_debug: cannot_derive_debug,
            dependencies: dependencies,
        }
    }

    fn initial_worklist(&self) -> Vec<ItemId> {
        self.ctx.whitelisted_items().collect()
    }

    fn constrain(&mut self, id: ItemId) -> bool {
        if self.cannot_derive_debug.contains(&id) {
            return false;
        }

        let item = self.ctx.resolve_item(id);
        let ty = match item.as_type() {
            None => return false,
            Some(ty) => ty
        };

        match *ty.kind() {
            // handle the simple case
            // These can derive debug without further information
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::Named |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::ObjCSel => {
                return false;
            },
            TypeKind::Opaque => {
                if ty.layout(self.ctx)
                    .map_or(true, |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
            },
            TypeKind::Array(t, len) => {
                if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
                    if self.cannot_derive_debug.contains(&t) {
                        return self.insert(id);
                    }
                    return false;
                } else {
                    return self.insert(id);
                }
            },
            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                if self.cannot_derive_debug.contains(&t) {
                    return self.insert(id);
                }
                return false;
            },
            TypeKind::Comp(ref info) => {
                if info.has_non_type_template_params() {
                    if ty.layout(self.ctx).map_or(true,
                                                  |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
                }
                if info.kind() == CompKind::Union {
                    if self.ctx.options().unstable_rust {
                        return self.insert(id);
                    }

                    if ty.layout(self.ctx).map_or(true,
                                                  |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
                }
                let bases_cannot_derive = info.base_members()
                    .iter()
                    .any(|base| self.cannot_derive_debug.contains(&base.ty));
                if bases_cannot_derive {
                    return self.insert(id);
                }
                let fields_cannot_derive = info.fields()
                    .iter()
                    .any(|f| {
                        match f {
                            &Field::DataMember(ref data) => self.cannot_derive_debug.contains(&data.ty()),
                            &Field::Bitfields(ref bfu) => bfu.bitfields()
                                .iter().any(|b| {
                                    self.cannot_derive_debug.contains(&b.ty())
                                })
                        }
                    });
                if fields_cannot_derive {
                    return self.insert(id);
                }
                false
            },
            TypeKind::Pointer(inner) => {
                let inner_type = self.ctx.resolve_type(inner);
                if let TypeKind::Function(ref sig) =
                    *inner_type.canonical_type(self.ctx).kind() {
                        if sig.can_trivially_derive_debug(&self.ctx, ()) {
                            return false;
                        } else {
                            return self.insert(id);
                        }
                    }
                false
            },
            TypeKind::TemplateInstantiation(ref template) => {
                let args_cannot_derive = template.template_arguments()
                    .iter()
                    .any(|arg| self.cannot_derive_debug.contains(&arg));
                if args_cannot_derive {
                    return self.insert(id);
                }
                let ty_cannot_derive = template.template_definition()
                    .into_resolver()
                    .through_type_refs()
                    .through_type_aliases()
                    .resolve(self.ctx)
                    .as_type()
                    .expect("Instantiations of a non-type?")
                    .as_comp()
                    .and_then(|c| {
                        // For non-type template parameters, we generate an opaque
                        // blob, and in this case the instantiation has a better
                        // idea of the layout than the definition does.
                        if c.has_non_type_template_params() {
                            let opaque = ty.layout(self.ctx)
                                .or_else(|| self.ctx.resolve_type(template.template_definition()).layout(self.ctx))
                                .unwrap_or(Layout::zero())
                                .opaque();
                            Some(!opaque.can_trivially_derive_debug(&self.ctx, ()))
                        } else {
                            None
                        }
                    })
                    .unwrap_or_else(|| self.cannot_derive_debug.contains(&template.template_definition()));
                if ty_cannot_derive {
                    return self.insert(id);
                }
                false
            },
        }
    }

    fn each_depending_on<F>(&self, id: ItemId, mut f: F)
        where F: FnMut(ItemId),
    {
        if let Some(edges) = self.dependencies.get(&id) {
            for item in edges {
                trace!("enqueue {:?} into worklist", item);
                f(*item);
            }
        }
    }
}

impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
    fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
        analysis.cannot_derive_debug
    }
}
<commit_msg>Fix variable name to reflect its semantics<commit_after>//! Determining which types for which we can emit `#[derive(Debug)]`.
use super::MonotoneFramework;
use ir::context::{BindgenContext, ItemId};
use ir::item::ItemSet;
use std::collections::HashSet;
use std::collections::HashMap;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
use ir::traversal::Trace;
use ir::comp::FieldMethods;
use ir::layout::Layout;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;

/// An analysis that finds for each IR item whether debug cannot be derived.
///
/// We use the monotone constraint function `cannot_derive_debug`, defined as
/// follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
///   type and check whether it can be derived using trivial checks.
/// * If T is Array type, debug cannot be derived if the length of the array is
///   larger than the limit or the type of data the array contains cannot derive
///   debug.
/// * If T is a type alias, a templated alias or an indirection to another type,
///   debug cannot be derived if the type T refers to cannot be derived debug.
/// * If T is a compound type, debug cannot be derived if any of its base member
///   or field cannot be derived debug.
/// * If T is a pointer, T cannot be derived debug if T is a function pointer
///   and the function signature cannot be derived debug.
/// * If T is an instantiation of an abstract template definition, T cannot be
///   derived debug if any of the template arguments or template definition
///   cannot derive debug.
#[derive(Debug, Clone)]
pub struct CannotDeriveDebug<'ctx, 'gen>
    where 'gen: 'ctx
{
    ctx: &'ctx BindgenContext<'gen>,

    // The incremental result of this analysis's computation. Everything in this
    // set cannot derive debug.
    cannot_derive_debug: HashSet<ItemId>,

    // Dependencies saying that if a key ItemId has been inserted into the
    // `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
    // considered again.
    //
    // This is a subset of the natural IR graph with reversed edges, where we
    // only include the edges from the IR graph that can affect whether a type
    // can derive debug or not.
    dependencies: HashMap<ItemId, Vec<ItemId>>,
}

impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
    fn consider_edge(kind: EdgeKind) -> bool {
        match kind {
            // These are the only edges that can affect whether a type can derive
            // debug or not.
            EdgeKind::BaseMember |
            EdgeKind::Field |
            EdgeKind::TypeReference |
            EdgeKind::VarType |
            EdgeKind::TemplateArgument |
            EdgeKind::TemplateDeclaration |
            EdgeKind::TemplateParameterDefinition => true,

            EdgeKind::Constructor |
            EdgeKind::Destructor |
            EdgeKind::FunctionReturn |
            EdgeKind::FunctionParameter |
            EdgeKind::InnerType |
            EdgeKind::InnerVar |
            EdgeKind::Method => false,
            EdgeKind::Generic => false,
        }
    }

    fn insert(&mut self, id: ItemId) -> bool {
        let was_not_already_in_set = self.cannot_derive_debug.insert(id);
        assert!(
            was_not_already_in_set,
            "We shouldn't try and insert {:?} twice because if it was \
             already in the set, `constrain` should have exited early.",
            id
        );
        true
    }
}

impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
    type Node = ItemId;
    type Extra = &'ctx BindgenContext<'gen>;
    type Output = HashSet<ItemId>;

    fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
        let cannot_derive_debug = HashSet::new();
        let mut dependencies = HashMap::new();
        let whitelisted_items: HashSet<_> = ctx.whitelisted_items().collect();

        let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter()
            .cloned()
            .flat_map(|i| {
                let mut reachable = vec![i];
                i.trace(ctx, &mut |s, _| {
                    reachable.push(s);
                }, &());
                reachable
            })
            .collect();

        for item in whitelisted_and_blacklisted_items {
            dependencies.entry(item).or_insert(vec![]);

            {
                // We reverse our natural IR graph edges to find dependencies
                // between nodes.
                item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
                    if Self::consider_edge(edge_kind) {
                        dependencies.entry(sub_item)
                            .or_insert(vec![])
                            .push(item);
                    }
                }, &());
            }
        }

        CannotDeriveDebug {
            ctx: ctx,
            cannot_derive_debug: cannot_derive_debug,
            dependencies: dependencies,
        }
    }

    fn initial_worklist(&self) -> Vec<ItemId> {
        self.ctx.whitelisted_items().collect()
    }

    fn constrain(&mut self, id: ItemId) -> bool {
        if self.cannot_derive_debug.contains(&id) {
            return false;
        }

        let item = self.ctx.resolve_item(id);
        let ty = match item.as_type() {
            None => return false,
            Some(ty) => ty
        };

        match *ty.kind() {
            // handle the simple case
            // These can derive debug without further information
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::BlockPointer |
            TypeKind::Named |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::ObjCSel => {
                return false;
            },
            TypeKind::Opaque => {
                if ty.layout(self.ctx)
                    .map_or(true, |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
            },
            TypeKind::Array(t, len) => {
                if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
                    if self.cannot_derive_debug.contains(&t) {
                        return self.insert(id);
                    }
                    return false;
                } else {
                    return self.insert(id);
                }
            },
            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) => {
                if self.cannot_derive_debug.contains(&t) {
                    return self.insert(id);
                }
                return false;
            },
            TypeKind::Comp(ref info) => {
                if info.has_non_type_template_params() {
                    if ty.layout(self.ctx).map_or(true,
                                                  |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
                }
                if info.kind() == CompKind::Union {
                    if self.ctx.options().unstable_rust {
                        return self.insert(id);
                    }

                    if ty.layout(self.ctx).map_or(true,
                                                  |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
                        return false;
                    } else {
                        return self.insert(id);
                    }
                }
                let bases_cannot_derive = info.base_members()
                    .iter()
                    .any(|base| self.cannot_derive_debug.contains(&base.ty));
                if bases_cannot_derive {
                    return self.insert(id);
                }
                let fields_cannot_derive = info.fields()
                    .iter()
                    .any(|f| {
                        match f {
                            &Field::DataMember(ref data) => self.cannot_derive_debug.contains(&data.ty()),
                            &Field::Bitfields(ref bfu) => bfu.bitfields()
                                .iter().any(|b| {
                                    self.cannot_derive_debug.contains(&b.ty())
                                })
                        }
                    });
                if fields_cannot_derive {
                    return self.insert(id);
                }
                false
            },
            TypeKind::Pointer(inner) => {
                let inner_type = self.ctx.resolve_type(inner);
                if let TypeKind::Function(ref sig) =
                    *inner_type.canonical_type(self.ctx).kind() {
                        if sig.can_trivially_derive_debug(&self.ctx, ()) {
                            return false;
                        } else {
                            return self.insert(id);
                        }
                    }
                false
            },
            TypeKind::TemplateInstantiation(ref template) => {
                let args_cannot_derive = template.template_arguments()
                    .iter()
                    .any(|arg| self.cannot_derive_debug.contains(&arg));
                if args_cannot_derive {
                    return self.insert(id);
                }
                let ty_cannot_derive = template.template_definition()
                    .into_resolver()
                    .through_type_refs()
                    .through_type_aliases()
                    .resolve(self.ctx)
                    .as_type()
                    .expect("Instantiations of a non-type?")
                    .as_comp()
                    .and_then(|c| {
                        // For non-type template parameters, we generate an opaque
                        // blob, and in this case the instantiation has a better
                        // idea of the layout than the definition does.
                        if c.has_non_type_template_params() {
                            let opaque = ty.layout(self.ctx)
                                .or_else(|| self.ctx.resolve_type(template.template_definition()).layout(self.ctx))
                                .unwrap_or(Layout::zero())
                                .opaque();
                            Some(!opaque.can_trivially_derive_debug(&self.ctx, ()))
                        } else {
                            None
                        }
                    })
                    .unwrap_or_else(|| self.cannot_derive_debug.contains(&template.template_definition()));
                if ty_cannot_derive {
                    return self.insert(id);
                }
                false
            },
        }
    }

    fn each_depending_on<F>(&self, id: ItemId, mut f: F)
        where F: FnMut(ItemId),
    {
        if let Some(edges) = self.dependencies.get(&id) {
            for item in edges {
                trace!("enqueue {:?} into worklist", item);
                f(*item);
            }
        }
    }
}

impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
    fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
        analysis.cannot_derive_debug
    }
}
<|endoftext|>


<commit_before><commit_msg>Dispatcher: exit the thread when two Exit command is received<commit_after><|endoftext|>


<commit_before><commit_msg>Use Rc<RefCell<_>> in NodePool<commit_after><|endoftext|>


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

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{boxed, rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for boxed::Box<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> BorrowMut<T> for boxed::Box<T> {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`.
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<commit_msg>Rollup merge of #27533 - steveklabnik:gh27109, r=Gankro<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{boxed, rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement
/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for boxed::Box<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> BorrowMut<T> for boxed::Box<T> {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`.
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<|endoftext|>