<commit_before>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};
use utility::Sample;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal<S: Sample>(order: usize,
                                       block_size: usize,
                                       output: &mut [S]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];
  let length       = block_size - order;

  for i in 0..length {
    let zero       = S::from_i8(0);
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(zero, |result, (coefficient, signal)|
                         result + S::from_i32_lossy(*coefficient) * *signal);

    output[offset] += prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal<S: Sample>(quantization_level: i8,
                                     block_size: usize,
                                     coefficients: &[i32],
                                     output: &mut [S]) {
  let order  = coefficients.len();
  let length = block_size - order;

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..length {
    let zero       = S::from_i8(0);
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(zero, |result, (coefficient, signal)|
                         result + S::from_i32_lossy(*coefficient) * *signal);

    output[offset] += prediction >> quantization_level;
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode<S>(subframe: &Subframe, block_size: usize, output: &mut [S])
 where S: Sample {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      let _constant = S::from_i32_lossy(constant);

      for i in 0..output.len() {
        output[i] = _constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      for i in 0..verbatim.len() {
        output[i] = S::from_i32_lossy(verbatim[i]);
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        let warmup = S::from_i32_lossy(fixed.warmup[i]);

        output[i] = warmup;
      }

      fixed_restore_signal(order, block_size, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        let warmup = S::from_i32_lossy(lpc.warmup[i]);

        output[i] = warmup;
      }

      lpc_restore_signal(lpc.quantization_level, block_size, coefficients,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let mut outputs = [ &mut [-729, -722, -667, -19, -16, 17, -23, -7, 16
                             , -16, -5, 3, -8, -13, -15, -1][..]
                      , &mut [21877, 27482, -6513][..]
                      ];

    fixed_restore_signal(3, 16, &mut outputs[0]);
    fixed_restore_signal(2, 3, &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , -2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 3157][..]
                      ];

    lpc_restore_signal(9, 16, &coefficients[0], &mut outputs[0]);
    lpc_restore_signal(10, 8, &coefficients[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, 16, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, 16, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    {
      let residual = [-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                     ,-1];

      for i in 0..residual.len() {
        output[i + 3] = residual[i];
      }

      decode(&fixed, 16, &mut output);
      assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                           ,209, 354, 497, 630, 740, 812, 845]);
    }

    {
      let residual = [-2, -23, 14, 6, 3, -4, 12, -2, 10];

      for i in 0..residual.len() {
        output[i + 7] = residual[i];
      }

      decode(&lpc, 16, &mut output);
      assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                           ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
    }
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, 4, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<commit_msg>Add unchecked array for `fixed_restore_signal`<commit_after>use subframe::{self, Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};
use utility::Sample;

// Restore the original signal from a fixed linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. With the linear prediction being "fixed", the polynomials will
// remain the same depending on the order value. And the max order is
// `MAX_FIXED_ORDER`, which is 4.
//
// This function also assumes that `output` already has the warm up values
// from the `Fixed` subframe in it.
pub fn fixed_restore_signal<S: Sample>(order: usize,
                                       block_size: usize,
                                       output: &mut [S]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = unsafe { *polynomial.get_unchecked(order) };
  let length       = block_size - order;

  for i in 0..length {
    let zero       = S::from_i8(0);
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(zero, |result, (coefficient, signal)|
                         result + S::from_i32_lossy(*coefficient) * *signal);

    output[offset] += prediction;
  }
}

// Restore the original signal from a FIR linear prediction.
//
// Signal restoration is accomplished by summing up the residual and the
// predictor. Figuring out the linear prediction for finite impulse response
// is a bit more involved because you have more to deal with, but the
// concept is very similar to the fixed version. Coefficients are passed in
// and reversed within function and the result of these reverse order
// coefficients and warm up values are summed and the quantization level
// will determine how much the bits gets shifted in order to figure the
// current predictor for it's corresponding residual value.
//
// The order doesn't get passed in explicitly because the coefficients
// length is assumed to be the value of order. And the max order is
// `MAX_LPC_ORDER`, which is 32. This function also assumes that `output`
// already has the warm up values from the `LPC` subframe in it.
pub fn lpc_restore_signal<S: Sample>(quantization_level: i8,
                                     block_size: usize,
                                     coefficients: &[i32],
                                     output: &mut [S]) {
  let order  = coefficients.len();
  let length = block_size - order;

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..length {
    let zero       = S::from_i8(0);
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(zero, |result, (coefficient, signal)|
                         result + S::from_i32_lossy(*coefficient) * *signal);

    output[offset] += prediction >> quantization_level;
  }
}

/// Decodes the current subframe.
///
/// * `Constant` - fills the length of `output` with the constant value
///   within the subframe.
/// * `Verbatim` - copies the data within the verbatim subframe over to
///   `output`.
/// * `Fixed` - restore the signal of the fixed linear prediction and put
///   the result into `output`.
/// * `LPC` - restore the signal of the finite impulse response linear
///   prediction and put the result into `output`.
pub fn decode<S>(subframe: &Subframe, block_size: usize, output: &mut [S])
 where S: Sample {
  match subframe.data {
    subframe::Data::Constant(constant)     => {
      let _constant = S::from_i32_lossy(constant);

      for i in 0..output.len() {
        output[i] = _constant
      }
    }
    subframe::Data::Verbatim(ref verbatim) => {
      for i in 0..verbatim.len() {
        output[i] = S::from_i32_lossy(verbatim[i]);
      }
    }
    subframe::Data::Fixed(ref fixed)       => {
      let order = fixed.order as usize;

      for i in 0..order {
        let warmup = S::from_i32_lossy(fixed.warmup[i]);

        output[i] = warmup;
      }

      fixed_restore_signal(order, block_size, output);
    }
    subframe::Data::LPC(ref lpc)           => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        let warmup = S::from_i32_lossy(lpc.warmup[i]);

        output[i] = warmup;
      }

      lpc_restore_signal(lpc.quantization_level, block_size, coefficients,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}

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

  use subframe;
  use subframe::{
    Subframe, Fixed, LPC,
    EntropyCodingMethod, CodingMethod, PartitionedRice,
    PartitionedRiceContents,
  };

  #[test]
  fn test_fixed_restore_signal() {
    let mut outputs = [ &mut [-729, -722, -667, -19, -16, 17, -23, -7, 16
                             , -16, -5, 3, -8, -13, -15, -1][..]
                      , &mut [21877, 27482, -6513][..]
                      ];

    fixed_restore_signal(3, 16, &mut outputs[0]);
    fixed_restore_signal(2, 3, &mut outputs[1]);

    assert_eq!(&outputs[0], &[-729, -722, -667, -583, -486, -359, -225, -91
                             , 59, 209, 354, 497, 630, 740, 812, 845]);
    assert_eq!(&outputs[1], &[21877, 27482, 26574]);
  }

  #[test]
  fn test_lpc_restore_signal() {
    let coefficients = [ &[1042, -399, -75, -269, 121, 166, -75][..]
                       , &[1757, -1199, 879, -836, 555, -255, 119][..]
                       ];
    let mut outputs = [ &mut [-796, -547, -285, -32, 199, 443, 670
                             , -2, -23, 14, 6, 3, -4, 12, -2, 10][..]
                      , &mut [-21363, -21951, -22649, -24364, -27297, -26870
                             ,-30017, 3157][..]
                      ];

    lpc_restore_signal(9, 16, &coefficients[0], &mut outputs[0]);
    lpc_restore_signal(10, 8, &coefficients[1], &mut outputs[1]);

    assert_eq!(&outputs[0], &[-796, -547, -285, -32, 199, 443, 670, 875
                             , 1046, 1208, 1343, 1454, 1541, 1616, 1663
                             , 1701]);
    assert_eq!(&outputs[1], &[-21363, -21951, -22649, -24364, -27297, -26870
                             , -30017, -29718]);
  }

  #[test]
  fn test_decode() {
    let mut output = [0; 16];

    let constant = Subframe {
      data: subframe::Data::Constant(4),
      wasted_bits: 0,
    };

    let verbatim = Subframe {
      data: subframe::Data::Verbatim(vec![16, -3, 55, 49, -32, 6, 40, -90, 1
                                         ,0, 77, -12, 84, 10, -112, 136]),
      wasted_bits: 0,
    };

    let fixed = Subframe {
      data: subframe::Data::Fixed(Fixed {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 3,
        warmup: [-729, -722, -667, 0],
        residual: vec![-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                      ,-1],
      }),
      wasted_bits: 0,
    };

    let lpc = Subframe {
      data: subframe::Data::LPC(LPC {
        entropy_coding_method: EntropyCodingMethod {
          method_type: CodingMethod::PartitionedRice,
          data: PartitionedRice {
            order: 0,
            contents: PartitionedRiceContents {
              capacity: 0,
              data: Vec::new(),
            },
          },
        },
        order: 7,
        qlp_coeff_precision: 0,
        quantization_level: 9,
        qlp_coefficients: [1042, -399, -75, -269, 121, 166, -75, 0, 0, 0, 0
                          ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                          ,0, 0, 0, 0],
        warmup: [-796, -547, -285, -32, 199, 443, 670, 0, 0, 0, 0, 0, 0, 0, 0
                ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        residual: vec![-2, -23, 14, 6, 3, -4, 12, -2, 10],
      }),
      wasted_bits: 0,
    };

    decode(&constant, 16, &mut output);
    assert_eq!(&output, &[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]);

    decode(&verbatim, 16, &mut output);
    assert_eq!(&output, &[16, -3, 55, 49, -32, 6, 40 , -90, 1, 0, 77, -12, 84
                         ,10 , -112, 136]);

    {
      let residual = [-19, -16, 17, -23, -7, 16, -16, -5, 3 , -8, -13, -15
                     ,-1];

      for i in 0..residual.len() {
        output[i + 3] = residual[i];
      }

      decode(&fixed, 16, &mut output);
      assert_eq!(&output, &[-729, -722, -667, -583, -486, -359, -225, -91, 59
                           ,209, 354, 497, 630, 740, 812, 845]);
    }

    {
      let residual = [-2, -23, 14, 6, 3, -4, 12, -2, 10];

      for i in 0..residual.len() {
        output[i + 7] = residual[i];
      }

      decode(&lpc, 16, &mut output);
      assert_eq!(&output, &[-796, -547, -285, -32, 199, 443, 670, 875, 1046
                           ,1208, 1343, 1454, 1541, 1616, 1663, 1701]);
    }
  }

  #[test]
  fn test_wasted_bit_decode() {
    let mut output = [0; 4];

    let constant = Subframe {
      data: subframe::Data::Constant(1),
      wasted_bits: 10,
    };

    decode(&constant, 4, &mut output);
    assert_eq!(&output, &[1024, 1024, 1024, 1024]);
  }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use objective::functions::Function;
use objective::constraints::Constraint;
use objective::constraints::SystemOfConstraints;
use tableau::tables::Table;

pub fn get_initial_table_from(fun: &Function, constraints: &SystemOfConstraints) -> Table {
    let mut column_names: HashMap<String, usize> = HashMap::new();
    // We have number of rows equal to the number of regular constraints plus a
    // row for the function we are maxising or minimising.
    let mut num_rows: usize = 1;
    // We need the length of rows and we should be able to index into the table
    // with respect to a variable name.
    for constraint in constraints.system() {
        match constraint {
            &Constraint::Regular(ref ref_cell) => {
                num_rows += 1;
                let exp = ref_cell.borrow();
                for var in exp.lhs() {
                    let map_len = column_names.len();
                    column_names.entry(var.name().to_string()).or_insert(map_len);
                }
            }
            &Constraint::NonNegative(_) => continue,
        }
    }
    for var in fun.exp().borrow().lhs() {
        let map_len = column_names.len();
        column_names.entry(var.name().to_string()).or_insert(map_len);
    }
    // ... and don't forget about the constant on the right.
    let map_len = column_names.len();
    column_names.insert("RHS".to_string(), map_len);
    let mut rows: Vec<Vec<f64>> = vec![vec![0.0; column_names.len()]; num_rows];
    // Populate the table
    let mut row_index = 0;
    for constraint in constraints.system() {
        match constraint {
            &Constraint::Regular(ref ref_cell) => {
                let exp = ref_cell.borrow();
                for var in exp.lhs() {
                    rows[row_index][*column_names.get(var.name()).unwrap()] = var.get_data();
                }
                // ... and don't forget about the constant on the right.
                let last_column = rows[row_index].len() - 1;
                rows[row_index][last_column] = exp.rhs()[0].get_data();
                row_index += 1;
            }
            &Constraint::NonNegative(_) => continue,
        }
    }
    let fun_vars = fun.exp_max().borrow();
    for var in fun_vars.lhs() {
        rows[row_index][*column_names.get(var.name()).unwrap()] = var.get_data();
    }
    // Set the value of Z to be initially 0 in the table.
    rows[row_index][map_len] = fun_vars.rhs()[0].get_data();
    Table::new(column_names, rows)
}
<commit_msg>Bug fix for table header containing original function name.<commit_after>use std::collections::HashMap;
use objective::functions::Function;
use objective::constraints::Constraint;
use objective::constraints::SystemOfConstraints;
use tableau::tables::Table;

pub fn get_initial_table_from(fun: &Function, constraints: &SystemOfConstraints) -> Table {
    let mut column_names: HashMap<String, usize> = HashMap::new();
    // We have number of rows equal to the number of regular constraints plus a
    // row for the function we are maxising or minimising.
    let mut num_rows: usize = 1;
    // We need the length of rows and we should be able to index into the table
    // with respect to a variable name.
    for constraint in constraints.system() {
        match constraint {
            &Constraint::Regular(ref ref_cell) => {
                num_rows += 1;
                let exp = ref_cell.borrow();
                for var in exp.lhs() {
                    let map_len = column_names.len();
                    column_names.entry(var.name().to_string()).or_insert(map_len);
                }
            }
            &Constraint::NonNegative(_) => continue,
        }
    }
    for var in fun.exp_max().borrow().lhs() {
        let map_len = column_names.len();
        column_names.entry(var.name().to_string()).or_insert(map_len);
    }
    // ... and don't forget about the constant on the right.
    let map_len = column_names.len();
    column_names.insert("RHS".to_string(), map_len);
    let mut rows: Vec<Vec<f64>> = vec![vec![0.0; column_names.len()]; num_rows];
    // Populate the table
    let mut row_index = 0;
    for constraint in constraints.system() {
        match constraint {
            &Constraint::Regular(ref ref_cell) => {
                let exp = ref_cell.borrow();
                for var in exp.lhs() {
                    rows[row_index][*column_names.get(var.name()).unwrap()] = var.get_data();
                }
                // ... and don't forget about the constant on the right.
                let last_column = rows[row_index].len() - 1;
                rows[row_index][last_column] = exp.rhs()[0].get_data();
                row_index += 1;
            }
            &Constraint::NonNegative(_) => continue,
        }
    }
    let fun_vars = fun.exp_max().borrow();
    for var in fun_vars.lhs() {
        rows[row_index][*column_names.get(var.name()).unwrap()] = var.get_data();
    }
    // Set the value of Z to be initially 0 in the table.
    rows[row_index][map_len] = fun_vars.rhs()[0].get_data();
    Table::new(column_names, rows)
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::{Cursor, Read};

use gfx;
use gfx::format::*;
use gfx_core;
use image::{self, GenericImage};
use zip::ZipArchive;

use cache::{WebAsset, GeneratedAsset};

#[derive(Clone, Copy)]
enum MaterialType {
    Rock = 0,
    Grass = 1,
}

struct MaterialTypeRaw(MaterialType);
impl WebAsset for MaterialTypeRaw {
    type Type = MaterialRaw;

    fn url(&self) -> String {
        match self.0 {
            MaterialType::Rock => "https://opengameart.org/sites/default/files/terrain_0.zip",
            MaterialType::Grass => "https://opengameart.org/sites/default/files/terrain_0.zip",
        }.to_owned()
    }

    fn filename(&self) -> String {
        let name = match self.0 {
            MaterialType::Rock => "terrain2.zip",
            MaterialType::Grass => "terrain2.zip",
        };
        format!("materials/raw/{}", name)
    }

    fn parse(&self, data: Vec<u8>) -> Result<Self::Type, Box<Error>> {
        let name = match self.0 {
            MaterialType::Rock => "ground_mud2_d.jpg",
            MaterialType::Grass => "grass_ground_d.jpg",
        };

        let mut raw = MaterialRaw::default();
        let mut zip = ZipArchive::new(Cursor::new(data))?;
        for i in 0..zip.len() {
            let mut file = zip.by_index(i)?;
            if file.name().contains(name) {
                raw.albedo.clear();
                file.read_to_end(&mut raw.albedo)?;
            }
        }
        Ok(raw)
    }
}

impl GeneratedAsset for MaterialType {
    type Type = Material;

    fn filename(&self) -> String {
        let name = match *self {
            MaterialType::Rock => "rock.bin",
            MaterialType::Grass => "grass.bin",
        };
        format!("materials/filtered/{}", name)
    }

    fn generate(&self) -> Result<Self::Type, Box<Error>> {
        fn convert_image(img: &image::DynamicImage) -> Vec<[u8; 4]> {
            img.to_rgba().to_vec()[..]
                .chunks(4)
                .map(|c| [c[0], c[1], c[2], c[3]])
                .collect()
        }

        let resolution: u16 = 1024;
        let mipmaps = 11;

        let raw = MaterialTypeRaw(*self).load()?;
        let mut albedo_image =
            image::DynamicImage::ImageRgba8(image::load_from_memory(&raw.albedo[..])?.to_rgba());

        let mut albedo_sum = [0u64; 4];
        for (_, _, color) in albedo_image.pixels() {
            for i in 0..4 {
                albedo_sum[i] += color[i] as u64;
            }
        }
        let num_pixels = (albedo_image.width() * albedo_image.height()) as u64;
        let average_albedo: [u8; 4] = [
            (albedo_sum[0] / num_pixels) as u8,
            (albedo_sum[1] / num_pixels) as u8,
            (albedo_sum[2] / num_pixels) as u8,
            (albedo_sum[3] / num_pixels) as u8,
        ];

        let mut albedo = Vec::new();
        for level in 0..mipmaps {
            let level_resolution = (resolution >> level) as u32;
            if albedo_image.width() != level_resolution ||
                albedo_image.height() != level_resolution
            {
                albedo_image = albedo_image.resize_exact(
                    level_resolution,
                    level_resolution,
                    image::FilterType::Triangle,
                );
            }

            let mut albedo_data = convert_image(&albedo_image);
            if level >= 20 {
                let (cw, aw) = match level {
                    5 => (50, 50),
                    6 => (25, 75),
                    _ => (0, 100),
                };

                for color in albedo_data.iter_mut() {
                    for i in 0..4 {
                        let c = color[i] as u16 * cw;
                        let a = average_albedo[i] as u16 * aw;
                        color[i] = ((c + a) / 100) as u8;
                    }
                }
            }

            albedo.push(albedo_data);
        }

        Ok(Material {
            resolution,
            mipmaps,
            albedo,
        })
    }
}

/// Holds the raw bytes of the image files for each map of a material.
#[derive(Serialize, Deserialize, Default)]
struct MaterialRaw {
    albedo: Vec<u8>,
}

#[derive(Serialize, Deserialize)]
struct Material {
    resolution: u16,
    mipmaps: u8,

    albedo: Vec<Vec<[u8; 4]>>,
}

pub struct MaterialSet<R: gfx::Resources> {
    pub(crate) texture_view: gfx_core::handle::ShaderResourceView<R, [f32; 4]>,
    pub(crate) _texture: gfx_core::handle::Texture<R, gfx_core::format::R8_G8_B8_A8>,
}

impl<R: gfx::Resources> MaterialSet<R> {
    pub fn load<F: gfx::Factory<R>, C: gfx_core::command::Buffer<R>>(
        factory: &mut F,
        encoder: &mut gfx::Encoder<R, C>,
    ) -> Result<Self, Box<Error>> {
        let resolution = 1024;
        let mipmaps = 11;

        let materials = vec![MaterialType::Rock.load()?, MaterialType::Grass.load()?];

        let texture = factory
            .create_texture::<R8_G8_B8_A8>(
                gfx::texture::Kind::D2Array(
                    resolution,
                    resolution,
                    materials.len() as u16,
                    gfx::texture::AaMode::Single,
                ),
                mipmaps,
                gfx::SHADER_RESOURCE,
                gfx::memory::Usage::Dynamic,
                Some(ChannelType::Srgb),
            )
            .unwrap();

        for (layer, material) in materials.iter().enumerate() {
            assert_eq!(mipmaps, material.mipmaps);
            assert_eq!(mipmaps as usize, material.albedo.len());

            for (level, albedo) in material.albedo.iter().enumerate() {
                encoder
                    .update_texture::<R8_G8_B8_A8, gfx::format::Srgba8>(
                        &texture,
                        None,
                        gfx_core::texture::NewImageInfo {
                            xoffset: 0,
                            yoffset: 0,
                            zoffset: layer as u16,
                            width: resolution >> level,
                            height: resolution >> level,
                            depth: 1,
                            format: (),
                            mipmap: level as u8,
                        },
                        &albedo[..],
                    )
                    .unwrap();
            }
        }

        let texture_view = factory
            .view_texture_as_shader_resource::<gfx::format::Srgba8>(
                &texture,
                (0, mipmaps),
                Swizzle::new(),
            )
            .unwrap();

        Ok(Self {
            texture_view,
            _texture: texture,
        })
    }
}
<commit_msg>Perform high pass filter on materials during preprocessing<commit_after>use std::error::Error;
use std::io::{Cursor, Read};

use gfx;
use gfx::format::*;
use gfx_core;
use image::{self, GenericImage};
use zip::ZipArchive;

use cache::{WebAsset, GeneratedAsset};

#[derive(Clone, Copy)]
enum MaterialType {
    Rock = 0,
    Grass = 1,
}

struct MaterialTypeRaw(MaterialType);
impl WebAsset for MaterialTypeRaw {
    type Type = MaterialRaw;

    fn url(&self) -> String {
        match self.0 {
            MaterialType::Rock => "https://opengameart.org/sites/default/files/terrain_0.zip",
            MaterialType::Grass => "https://opengameart.org/sites/default/files/terrain_0.zip",
        }.to_owned()
    }

    fn filename(&self) -> String {
        let name = match self.0 {
            MaterialType::Rock => "terrain.zip",
            MaterialType::Grass => "terrain.zip",
        };
        format!("materials/raw/{}", name)
    }

    fn parse(&self, data: Vec<u8>) -> Result<Self::Type, Box<Error>> {
        let name = match self.0 {
            MaterialType::Rock => "ground_mud2_d.jpg",
            MaterialType::Grass => "grass_ground_d.jpg",
        };

        let mut raw = MaterialRaw::default();
        let mut zip = ZipArchive::new(Cursor::new(data))?;
        for i in 0..zip.len() {
            let mut file = zip.by_index(i)?;
            if file.name().contains(name) {
                raw.albedo.clear();
                file.read_to_end(&mut raw.albedo)?;
            }
        }
        Ok(raw)
    }
}

impl GeneratedAsset for MaterialType {
    type Type = Material;

    fn filename(&self) -> String {
        let name = match *self {
            MaterialType::Rock => "rock.bin",
            MaterialType::Grass => "grass.bin",
        };
        format!("materials/filtered/{}", name)
    }

    fn generate(&self) -> Result<Self::Type, Box<Error>> {
        let resolution = 1024;
        let mipmaps = 11;

        let raw = MaterialTypeRaw(*self).load()?;
        let mut albedo_image =
            image::DynamicImage::ImageRgba8(image::load_from_memory(&raw.albedo[..])?.to_rgba());
        if albedo_image.width() != resolution || albedo_image.height() != resolution {
            albedo_image =
                albedo_image.resize_exact(resolution, resolution, image::FilterType::Triangle);
        }

        let albedo_image_blurred = {
            let sigma = 32;
            println!("tiling...");
            let tiled =
                image::RgbaImage::from_fn(resolution + 4 * sigma, resolution + 4 * sigma, |x, y| {
                    albedo_image.get_pixel(
                        (x + resolution - 2 * sigma) % resolution,
                        (y + resolution - 2 * sigma) % resolution,
                    )
                });
            println!("blurring...");
            let mut tiled = image::DynamicImage::ImageRgba8(tiled).blur(sigma as f32);
            println!("cropping...");
            tiled.crop(2 * sigma, 2 * sigma, resolution, resolution)
        };

        println!("computing average albedo...");
        let mut albedo_sum = [0u64; 4];
        for (_, _, color) in albedo_image.pixels() {
            for i in 0..4 {
                albedo_sum[i] += color[i] as u64;
            }
        }
        let num_pixels = (albedo_image.width() * albedo_image.height()) as u64;
        let average_albedo: [u8; 4] = [
            (albedo_sum[0] / num_pixels) as u8,
            (albedo_sum[1] / num_pixels) as u8,
            (albedo_sum[2] / num_pixels) as u8,
            (albedo_sum[3] / num_pixels) as u8,
        ];

        println!("high pass filter...");
        for (x, y, blurred_color) in albedo_image_blurred.pixels() {
            let mut color = albedo_image.get_pixel(x, y);
            for i in 0..4 {
                use image::math::utils::clamp;
                color[i] = clamp(
                    (color[i] as i16) - (blurred_color[i] as i16) +
                        (average_albedo[i] as i16),
                    0,
                    255,
                ) as u8;
            }
            albedo_image.put_pixel(x, y, color);
        }

        println!("generating mipmaps...");
        let mut albedo = Vec::new();
        for level in 0..mipmaps {
            let level_resolution = (resolution >> level) as u32;
            if albedo_image.width() != level_resolution ||
                albedo_image.height() != level_resolution
            {
                albedo_image = albedo_image.resize_exact(
                    level_resolution,
                    level_resolution,
                    image::FilterType::Triangle,
                );
            }

            albedo.push(
                albedo_image.to_rgba().to_vec()[..]
                    .chunks(4)
                    .map(|c| [c[0], c[1], c[2], c[3]])
                    .collect(),
            );
        }
        println!("done.");
        Ok(Material {
            resolution: resolution as u16,
            mipmaps,
            albedo,
        })
    }
}

/// Holds the raw bytes of the image files for each map of a material.
#[derive(Serialize, Deserialize, Default)]
struct MaterialRaw {
    albedo: Vec<u8>,
}

#[derive(Serialize, Deserialize)]
struct Material {
    resolution: u16,
    mipmaps: u8,

    albedo: Vec<Vec<[u8; 4]>>,
}

pub struct MaterialSet<R: gfx::Resources> {
    pub(crate) texture_view: gfx_core::handle::ShaderResourceView<R, [f32; 4]>,
    pub(crate) _texture: gfx_core::handle::Texture<R, gfx_core::format::R8_G8_B8_A8>,
}

impl<R: gfx::Resources> MaterialSet<R> {
    pub fn load<F: gfx::Factory<R>, C: gfx_core::command::Buffer<R>>(
        factory: &mut F,
        encoder: &mut gfx::Encoder<R, C>,
    ) -> Result<Self, Box<Error>> {
        let resolution = 1024;
        let mipmaps = 11;

        let materials = vec![MaterialType::Rock.load()?, MaterialType::Grass.load()?];

        let texture = factory
            .create_texture::<R8_G8_B8_A8>(
                gfx::texture::Kind::D2Array(
                    resolution,
                    resolution,
                    materials.len() as u16,
                    gfx::texture::AaMode::Single,
                ),
                mipmaps,
                gfx::SHADER_RESOURCE,
                gfx::memory::Usage::Dynamic,
                Some(ChannelType::Srgb),
            )
            .unwrap();

        for (layer, material) in materials.iter().enumerate() {
            assert_eq!(mipmaps, material.mipmaps);
            assert_eq!(mipmaps as usize, material.albedo.len());

            for (level, albedo) in material.albedo.iter().enumerate() {
                encoder
                    .update_texture::<R8_G8_B8_A8, gfx::format::Srgba8>(
                        &texture,
                        None,
                        gfx_core::texture::NewImageInfo {
                            xoffset: 0,
                            yoffset: 0,
                            zoffset: layer as u16,
                            width: resolution >> level,
                            height: resolution >> level,
                            depth: 1,
                            format: (),
                            mipmap: level as u8,
                        },
                        &albedo[..],
                    )
                    .unwrap();
            }
        }

        let texture_view = factory
            .view_texture_as_shader_resource::<gfx::format::Srgba8>(
                &texture,
                (0, mipmaps),
                Swizzle::new(),
            )
            .unwrap();

        Ok(Self {
            texture_view,
            _texture: texture,
        })
    }
}
<|endoftext|>


<commit_before>use super::Color;

/// Combines a front and back color.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ColorPair {
    /// Color used for the foreground.
    pub front: Color,

    /// Color used for the background.
    pub back: Color,
}

impl ColorPair {
    /// Return an inverted color pair.
    ///
    /// With swapped front abd back color.
    pub fn invert(self) -> Self {
        ColorPair {
            front: self.back,
            back: self.front,
        }
    }

    /// Creates a new color pair from color IDs.
    pub fn from_256colors(front: u8, back: u8) -> Self {
        Self {
            front: Color::from_256colors(front),
            back: Color::from_256colors(back),
        }
    }
}
<commit_msg>Fix doc typo (abd -> and) (#350)<commit_after>use super::Color;

/// Combines a front and back color.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ColorPair {
    /// Color used for the foreground.
    pub front: Color,

    /// Color used for the background.
    pub back: Color,
}

impl ColorPair {
    /// Return an inverted color pair.
    ///
    /// With swapped front and back color.
    pub fn invert(self) -> Self {
        ColorPair {
            front: self.back,
            back: self.front,
        }
    }

    /// Creates a new color pair from color IDs.
    pub fn from_256colors(front: u8, back: u8) -> Self {
        Self {
            front: Color::from_256colors(front),
            back: Color::from_256colors(back),
        }
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;
use std::collections::HashMap;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Relation {
    Equal,
    Before,
    After,
    Concurrent
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct VectorClock<S: Hash + Eq + Copy> {
    map: HashMap<S, u64>
}

impl <S: Hash + Eq + Copy>VectorClock<S> {
    pub fn new() -> VectorClock<S> {
        VectorClock {
            map: HashMap::new()
        }
    }

    pub fn inc(&mut self, server: S) {
        *self.map.entry(server).or_insert(0) += 1;
    }

    pub fn happened_after(&self, clock_b: &VectorClock<S>) -> bool {
        for (server, ac) in self.map.iter() {
            if let Some(bc) = clock_b.map.get(server) {
                // We only check servers that existed in the clock
                // Because we can't tell sequences from missing servers
                if ac > bc {return true;}
            }
        }
        return false;
    }
    pub fn equals(&self, clock_b: &VectorClock<S>) -> bool {
        for (server, ac) in self.map.iter() {
            if let Some(bc) = clock_b.map.get(server) {
                if ac != bc {return false;}
            }
        }
        return true;
    }
    pub fn relation(&self, clock_b: &VectorClock<S>) -> Relation {
        if self.equals(clock_b) {
            return Relation::Equal;
        }
        if self.happened_after(clock_b) {
            return Relation::After;
        }
        if clock_b.happened_after(self) {
            return Relation::Before;
        }
        return Relation::Concurrent;
    }
    pub fn merge_with(&mut self, clock_b: &VectorClock<S>) {
        for (server, bc) in clock_b.map.iter() {
            let mut ba = self.map.entry(*server).or_insert(0);
            if *ba < *bc {*ba = *bc}
        }
    }
}
<commit_msg>server vector clock<commit_after>use std::hash::Hash;
use std::collections::HashMap;
use parking_lot::RwLock;
use bifrost_hasher::hash_str;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Relation {
    Equal,
    Before,
    After,
    Concurrent
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct VectorClock<S: Hash + Eq + Copy> {
    map: HashMap<S, u64>
}

impl <S: Hash + Eq + Copy>VectorClock<S> {
    pub fn new() -> VectorClock<S> {
        VectorClock {
            map: HashMap::new()
        }
    }

    pub fn inc(&mut self, server: S) {
        *self.map.entry(server).or_insert(0) += 1;
    }

    pub fn happened_after(&self, clock_b: &VectorClock<S>) -> bool {
        for (server, ac) in self.map.iter() {
            if let Some(bc) = clock_b.map.get(server) {
                // We only check servers that existed in the clock
                // Because we can't tell sequences from missing servers
                if ac > bc {return true;}
            }
        }
        return false;
    }
    pub fn equals(&self, clock_b: &VectorClock<S>) -> bool {
        for (server, ac) in self.map.iter() {
            if let Some(bc) = clock_b.map.get(server) {
                if ac != bc {return false;}
            }
        }
        return true;
    }
    pub fn relation(&self, clock_b: &VectorClock<S>) -> Relation {
        if self.equals(clock_b) {
            return Relation::Equal;
        }
        if self.happened_after(clock_b) {
            return Relation::After;
        }
        if clock_b.happened_after(self) {
            return Relation::Before;
        }
        return Relation::Concurrent;
    }
    pub fn merge_with(&mut self, clock_b: &VectorClock<S>) {
        for (server, bc) in clock_b.map.iter() {
            let mut ba = self.map.entry(*server).or_insert(0);
            if *ba < *bc {*ba = *bc}
        }
    }
}

pub struct ServerVectorClock {
    server: u64,
    clock: RwLock<VectorClock<u64>>
}

impl ServerVectorClock {
    pub fn new(server_address: &String) -> ServerVectorClock {
        ServerVectorClock {
            server: hash_str(server_address),
            clock: RwLock::new(VectorClock::new())
        }
    }
    pub fn inc(&mut self) {
        let mut clock = self.clock.write();
        clock.inc(self.server)
    }

    pub fn happened_after(&self, clock_b: &VectorClock<u64>) -> bool {
        let clock = self.clock.read();
        clock.happened_after(clock_b)
    }
    pub fn equals(&self, clock_b: &VectorClock<u64>) -> bool {
        let clock = self.clock.read();
        clock.equals(clock_b)
    }
    pub fn relation(&self, clock_b: &VectorClock<u64>) -> Relation {
        let clock = self.clock.read();
        clock.relation(clock_b)
    }
    pub fn merge_with(&mut self, clock_b: &VectorClock<u64>) {
        let mut clock = self.clock.write();
        clock.merge_with(clock_b)
    }
}
<|endoftext|>


<commit_before>use Printer;
use backend::Backend;

use direction::Direction;
use event::{Event, EventResult};
use std::any::Any;
use theme::ColorStyle;
use vec::Vec2;
use view::{Offset, Position, Selector, View};
use views::ShadowView;

/// Simple stack of views.
/// Only the top-most view is active and can receive input.
pub struct StackView {
    layers: Vec<Layer>,
    last_size: Vec2,
}

struct Layer {
    view: Box<View>,
    size: Vec2,
    position: Position,
    // Has it received the gift yet?
    virgin: bool,
}

new_default!(StackView);

impl StackView {
    /// Creates a new empty StackView
    pub fn new() -> Self {
        StackView {
            layers: Vec::new(),
            last_size: Vec2::zero(),
        }
    }

    /// Adds new view on top of the stack in the center of the screen.
    pub fn add_layer<T: 'static + View>(&mut self, view: T) {
        self.add_layer_at(Position::center(), view);
    }

    /// Adds a view on top of the stack.
    pub fn add_layer_at<T: 'static + View>(&mut self, position: Position,
                                           view: T) {
        self.layers.push(Layer {
            // Skip padding for absolute/parent-placed views
            view: Box::new(ShadowView::new(view)
                .top_padding(position.y == Offset::Center)
                .left_padding(position.x == Offset::Center)),
            size: Vec2::new(0, 0),
            position: position,
            virgin: true,
        });
    }

    /// Remove the top-most layer.
    pub fn pop_layer(&mut self) {
        self.layers.pop();
        ::B::clear();
    }

    /// Computes the offset of the current top view.
    pub fn offset(&self) -> Vec2 {
        let mut previous = Vec2::zero();
        for layer in &self.layers {
            let offset = layer.position
                .compute_offset(layer.size, self.last_size, previous);
            previous = offset;
        }
        previous
    }
}

impl View for StackView {
    fn draw(&self, printer: &Printer) {
        let last = self.layers.len();
        let mut previous = Vec2::zero();
        printer.with_color(ColorStyle::Primary, |printer| {
            for (i, v) in self.layers.iter().enumerate() {
                // Place the view
                // Center the view
                let offset = v.position
                    .compute_offset(v.size, printer.size, previous);

                previous = offset;
                v.view
                    .draw(&printer.sub_printer(offset, v.size, i + 1 == last));
            }
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        match self.layers.last_mut() {
            None => EventResult::Ignored,
            Some(v) => v.view.on_event(event),
        }
    }

    fn layout(&mut self, size: Vec2) {
        self.last_size = size;

        // The call has been made, we can't ask for more space anymore.
        // Let's make do with what we have.

        for layer in &mut self.layers {
            // Give each guy what he asks for, within the budget constraints.
            layer.size = Vec2::min(size, layer.view.get_min_size(size));
            layer.view.layout(layer.size);

            // We do it here instead of when adding a new layer because...?
            // (TODO: try to make it during layer addition)
            if layer.virgin {
                layer.view.take_focus(Direction::none());
                layer.virgin = false;
            }
        }
    }

    fn get_min_size(&mut self, size: Vec2) -> Vec2 {
        // The min size is the max of all children's

        self.layers
            .iter_mut()
            .map(|layer| layer.view.get_min_size(size))
            .fold(Vec2::new(1, 1), Vec2::max)
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        match self.layers.last_mut() {
            None => false,
            Some(mut v) => v.view.take_focus(source),
        }
    }

    fn find_any(&mut self, selector: &Selector) -> Option<&mut Any> {
        self.layers
            .iter_mut()
            .filter_map(|l| l.view.find_any(selector))
            .next()
    }
}
<commit_msg>Clear screen if a layer is shrinked<commit_after>use Printer;
use backend::Backend;

use direction::Direction;
use event::{Event, EventResult};
use std::any::Any;
use theme::ColorStyle;
use vec::Vec2;
use view::{Offset, Position, Selector, View};
use views::ShadowView;

/// Simple stack of views.
/// Only the top-most view is active and can receive input.
pub struct StackView {
    layers: Vec<Layer>,
    last_size: Vec2,
}

struct Layer {
    view: Box<View>,
    size: Vec2,
    position: Position,
    // Has it received the gift yet?
    virgin: bool,
}

new_default!(StackView);

impl StackView {
    /// Creates a new empty StackView
    pub fn new() -> Self {
        StackView {
            layers: Vec::new(),
            last_size: Vec2::zero(),
        }
    }

    /// Adds new view on top of the stack in the center of the screen.
    pub fn add_layer<T: 'static + View>(&mut self, view: T) {
        self.add_layer_at(Position::center(), view);
    }

    /// Adds a view on top of the stack.
    pub fn add_layer_at<T: 'static + View>(&mut self, position: Position,
                                           view: T) {
        self.layers.push(Layer {
            // Skip padding for absolute/parent-placed views
            view: Box::new(ShadowView::new(view)
                .top_padding(position.y == Offset::Center)
                .left_padding(position.x == Offset::Center)),
            size: Vec2::new(0, 0),
            position: position,
            virgin: true,
        });
    }

    /// Remove the top-most layer.
    pub fn pop_layer(&mut self) {
        self.layers.pop();
        ::B::clear();
    }

    /// Computes the offset of the current top view.
    pub fn offset(&self) -> Vec2 {
        let mut previous = Vec2::zero();
        for layer in &self.layers {
            let offset = layer.position
                .compute_offset(layer.size, self.last_size, previous);
            previous = offset;
        }
        previous
    }
}

impl View for StackView {
    fn draw(&self, printer: &Printer) {
        let last = self.layers.len();
        let mut previous = Vec2::zero();
        printer.with_color(ColorStyle::Primary, |printer| {
            for (i, v) in self.layers.iter().enumerate() {
                // Place the view
                // Center the view
                let offset = v.position
                    .compute_offset(v.size, printer.size, previous);

                previous = offset;
                v.view
                    .draw(&printer.sub_printer(offset, v.size, i + 1 == last));
            }
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        match self.layers.last_mut() {
            None => EventResult::Ignored,
            Some(v) => v.view.on_event(event),
        }
    }

    fn layout(&mut self, size: Vec2) {
        self.last_size = size;

        // The call has been made, we can't ask for more space anymore.
        // Let's make do with what we have.

        for layer in &mut self.layers {
            // Give each guy what he asks for, within the budget constraints.
            let size = Vec2::min(size, layer.view.get_min_size(size));
            if !layer.size.fits_in(size) {
                ::B::clear();
            }
            layer.size = size;
            layer.view.layout(layer.size);

            // We do it here instead of when adding a new layer because...?
            // (TODO: try to make it during layer addition)
            if layer.virgin {
                layer.view.take_focus(Direction::none());
                layer.virgin = false;
            }
        }
    }

    fn get_min_size(&mut self, size: Vec2) -> Vec2 {
        // The min size is the max of all children's

        self.layers
            .iter_mut()
            .map(|layer| layer.view.get_min_size(size))
            .fold(Vec2::new(1, 1), Vec2::max)
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        match self.layers.last_mut() {
            None => false,
            Some(mut v) => v.view.take_focus(source),
        }
    }

    fn find_any(&mut self, selector: &Selector) -> Option<&mut Any> {
        self.layers
            .iter_mut()
            .filter_map(|l| l.view.find_any(selector))
            .next()
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::io::BufWriter;
use std::io::{self, Write};

fn main() {
    let os_args = env::args();
    let args: Vec<_> = os_args.collect();

    if args.len() != 4 {
        println!("usage : {} start numline width", args[0]);
        return;
    }

    let start_num = args[1].trim_right().parse::<u64>().unwrap_or(0);
    let stop_num = args[2].trim_right().parse::<u64>().unwrap_or(0);
    let width_num = args[3].trim_right().parse::<u64>().unwrap_or(0);

    gen_lines(start_num, stop_num, width_num);
}

fn gen_lines(start: u64, stop: u64, linewidth: u64) -> () {
    let string = gen_line(linewidth);

    let stdout = io::stdout();
    let mut buff = BufWriter::new(stdout);
    for x in start..start + stop + 1 {
        buff.write_fmt(format_args!("{:012} {}", x, string)).unwrap();
    }
}

fn gen_line(linewidth: u64) -> String {
    let mut string = String::new();

    let table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                 'w', 'x', 'y', 'z'];

    for x in 0..linewidth {
        string.push(table[x as usize % table.len()]);
    }
    string.push('\n');

    return string;
}
<commit_msg>simplification<commit_after>use std::env;
use std::io::BufWriter;
use std::io::{self, Write};

fn main() {
    let os_args = env::args();
    let args: Vec<_> = os_args.collect();

    if args.len() != 4 {
        println!("usage : {} start numline width", args[0]);
        return;
    }

    let start_num = args[1].trim_right().parse::<u64>().unwrap_or(0);
    let stop_num = args[2].trim_right().parse::<u64>().unwrap_or(0);
    let width_num = args[3].trim_right().parse::<u64>().unwrap_or(0);

    gen_lines(start_num, stop_num, width_num);
}

fn gen_lines(start: u64, stop: u64, linewidth: u64) -> () {
    let string = gen_line(linewidth);

    let stdout = io::stdout();
    let mut buff = BufWriter::new(stdout);
    for x in start..start + stop + 1 {
        buff.write_fmt(format_args!("{:012} {}", x, string)).unwrap();
    }
}

fn gen_line(linewidth: u64) -> String {
    let mut string = String::new();

    let table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                 'w', 'x', 'y', 'z'];

    for x in 0..linewidth {
        string.push(table[x as usize % table.len()]);
    }
    string.push('\n');

    string
}
<|endoftext|>


<commit_before>//! Types for working with [`File`].
//!
//! [`File`]: struct.File.html

mod create;
mod open;

pub use self::create::CreateFuture;
pub use self::open::OpenFuture;

use tokio_io::{AsyncRead, AsyncWrite};

use futures::Poll;

use std::fs::{File as StdFile, Metadata, Permissions};
use std::io::{self, Read, Write, Seek};
use std::path::Path;

/// A reference to an open file on the filesystem.
///
/// This is a specialized version of [`std::fs::File`][std] for usage from the
/// Tokio runtime.
///
/// An instance of a `File` can be read and/or written depending on what options
/// it was opened with. Files also implement Seek to alter the logical cursor
/// that the file contains internally.
///
/// Files are automatically closed when they go out of scope.
///
/// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
#[derive(Debug)]
pub struct File {
    std: Option<StdFile>,
}

impl File {
    /// Attempts to open a file in read-only mode.
    ///
    /// # Errors
    ///
    /// `OpenFuture` results in an error if called from outside of the Tokio
    /// runtime or if the underlying [`open`] call results in an error.
    ///
    /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
    pub fn open
(path: P) -> OpenFuture

    where P: AsRef<Path> + Send + 'static,
    {
        OpenFuture::new(path)
    }

    /// Opens a file in write-only mode.
    ///
    /// This function will create a file if it does not exist, and will truncate
    /// it if it does.
    ///
    /// `CreateFuture` results in an error if called from outside of the Tokio
    /// runtime or if the underlying [`create`] call results in an error.
    ///
    /// [`open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create
    pub fn create
(path: P) -> CreateFuture

    where P: AsRef<Path> + Send + 'static,
    {
        CreateFuture::new(path)
    }

    /// Convert a [`std::fs::File`][std] to a `tokio_fs::File`.
    ///
    /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
    pub(crate) fn from_std(std: StdFile) -> File {
        File { std: Some(std) }
    }

    /// Seek to an offset, in bytes, in a stream.
    ///
    /// A seek beyond the end of a stream is allowed, but implementation
    /// defined.
    ///
    /// If the seek operation completed successfully, this method returns the
    /// new position from the start of the stream. That position can be used
    /// later with `SeekFrom::Start`.
    ///
    /// # Errors
    ///
    /// Seeking to a negative offset is considered an error.
    pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll<u64, io::Error> {
        ::blocking_io(|| self.std().seek(pos))
    }

    /// Attempts to sync all OS-internal metadata to disk.
    ///
    /// This function will attempt to ensure that all in-core data reaches the
    /// filesystem before returning.
    pub fn poll_sync_all(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().sync_all())
    }

    /// This function is similar to `poll_sync_all`, except that it may not
    /// synchronize file metadata to the filesystem.
    ///
    /// This is intended for use cases that must synchronize content, but don't
    /// need the metadata on disk. The goal of this method is to reduce disk
    /// operations.
    ///
    /// Note that some platforms may simply implement this in terms of `poll_sync_all`.
    pub fn poll_sync_data(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().sync_data())
    }

    /// Truncates or extends the underlying file, updating the size of this file to become size.
    ///
    /// If the size is less than the current file's size, then the file will be
    /// shrunk. If it is greater than the current file's size, then the file
    /// will be extended to size and have all of the intermediate data filled in
    /// with 0s.
    ///
    /// # Errors
    ///
    /// This function will return an error if the file is not opened for
    /// writing.
    pub fn poll_set_len(&mut self, size: u64) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().set_len(size))
    }

    /// Queries metadata about the underlying file.
    pub fn poll_metadata(&mut self) -> Poll<Metadata, io::Error> {
        ::blocking_io(|| self.std().metadata())
    }

    /// Create a new `File` instance that shares the same underlying file handle
    /// as the existing `File` instance. Reads, writes, and seeks will affect both
    /// File instances simultaneously.
    pub fn poll_try_clone(&mut self) -> Poll<File, io::Error> {
        ::blocking_io(|| {
            let std = self.std().try_clone()?;
            Ok(File::from_std(std))
        })
    }

    /// Changes the permissions on the underlying file.
    ///
    /// # Platform-specific behavior
    ///
    /// This function currently corresponds to the `fchmod` function on Unix and
    /// the `SetFileInformationByHandle` function on Windows. Note that, this
    /// [may change in the future][changes].
    ///
    /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
    ///
    /// # Errors
    ///
    /// This function will return an error if the user lacks permission change
    /// attributes on the underlying file. It may also return an error in other
    /// os-specific unspecified cases.
    pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().set_permissions(perm))
    }

    fn std(&mut self) -> &mut StdFile {
        self.std.as_mut().expect("`File` instance already shutdown")
    }
}

impl Read for File {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        ::would_block(|| self.std().read(buf))
    }
}

impl AsyncRead for File {
    unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
        false
    }
}

impl Write for File {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        ::would_block(|| self.std().write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        ::would_block(|| self.std().flush())
    }
}

impl AsyncWrite for File {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| {
            self.std = None;
            Ok(())
        })
    }
}

impl Drop for File {
    fn drop(&mut self) {
        if let Some(_std) = self.std.take() {
            // This is probably fine as closing a file *shouldn't* be a blocking
            // operation. That said, ideally `shutdown` is called first.
        }
    }
}
<commit_msg>Fix typo in documentation (#338)<commit_after>//! Types for working with [`File`].
//!
//! [`File`]: struct.File.html

mod create;
mod open;

pub use self::create::CreateFuture;
pub use self::open::OpenFuture;

use tokio_io::{AsyncRead, AsyncWrite};

use futures::Poll;

use std::fs::{File as StdFile, Metadata, Permissions};
use std::io::{self, Read, Write, Seek};
use std::path::Path;

/// A reference to an open file on the filesystem.
///
/// This is a specialized version of [`std::fs::File`][std] for usage from the
/// Tokio runtime.
///
/// An instance of a `File` can be read and/or written depending on what options
/// it was opened with. Files also implement Seek to alter the logical cursor
/// that the file contains internally.
///
/// Files are automatically closed when they go out of scope.
///
/// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
#[derive(Debug)]
pub struct File {
    std: Option<StdFile>,
}

impl File {
    /// Attempts to open a file in read-only mode.
    ///
    /// # Errors
    ///
    /// `OpenFuture` results in an error if called from outside of the Tokio
    /// runtime or if the underlying [`open`] call results in an error.
    ///
    /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
    pub fn open
(path: P) -> OpenFuture

    where P: AsRef<Path> + Send + 'static,
    {
        OpenFuture::new(path)
    }

    /// Opens a file in write-only mode.
    ///
    /// This function will create a file if it does not exist, and will truncate
    /// it if it does.
    ///
    /// `CreateFuture` results in an error if called from outside of the Tokio
    /// runtime or if the underlying [`create`] call results in an error.
    ///
    /// [`create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create
    pub fn create
(path: P) -> CreateFuture

    where P: AsRef<Path> + Send + 'static,
    {
        CreateFuture::new(path)
    }

    /// Convert a [`std::fs::File`][std] to a `tokio_fs::File`.
    ///
    /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
    pub(crate) fn from_std(std: StdFile) -> File {
        File { std: Some(std) }
    }

    /// Seek to an offset, in bytes, in a stream.
    ///
    /// A seek beyond the end of a stream is allowed, but implementation
    /// defined.
    ///
    /// If the seek operation completed successfully, this method returns the
    /// new position from the start of the stream. That position can be used
    /// later with `SeekFrom::Start`.
    ///
    /// # Errors
    ///
    /// Seeking to a negative offset is considered an error.
    pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll<u64, io::Error> {
        ::blocking_io(|| self.std().seek(pos))
    }

    /// Attempts to sync all OS-internal metadata to disk.
    ///
    /// This function will attempt to ensure that all in-core data reaches the
    /// filesystem before returning.
    pub fn poll_sync_all(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().sync_all())
    }

    /// This function is similar to `poll_sync_all`, except that it may not
    /// synchronize file metadata to the filesystem.
    ///
    /// This is intended for use cases that must synchronize content, but don't
    /// need the metadata on disk. The goal of this method is to reduce disk
    /// operations.
    ///
    /// Note that some platforms may simply implement this in terms of `poll_sync_all`.
    pub fn poll_sync_data(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().sync_data())
    }

    /// Truncates or extends the underlying file, updating the size of this file to become size.
    ///
    /// If the size is less than the current file's size, then the file will be
    /// shrunk. If it is greater than the current file's size, then the file
    /// will be extended to size and have all of the intermediate data filled in
    /// with 0s.
    ///
    /// # Errors
    ///
    /// This function will return an error if the file is not opened for
    /// writing.
    pub fn poll_set_len(&mut self, size: u64) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().set_len(size))
    }

    /// Queries metadata about the underlying file.
    pub fn poll_metadata(&mut self) -> Poll<Metadata, io::Error> {
        ::blocking_io(|| self.std().metadata())
    }

    /// Create a new `File` instance that shares the same underlying file handle
    /// as the existing `File` instance. Reads, writes, and seeks will affect both
    /// File instances simultaneously.
    pub fn poll_try_clone(&mut self) -> Poll<File, io::Error> {
        ::blocking_io(|| {
            let std = self.std().try_clone()?;
            Ok(File::from_std(std))
        })
    }

    /// Changes the permissions on the underlying file.
    ///
    /// # Platform-specific behavior
    ///
    /// This function currently corresponds to the `fchmod` function on Unix and
    /// the `SetFileInformationByHandle` function on Windows. Note that, this
    /// [may change in the future][changes].
    ///
    /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
    ///
    /// # Errors
    ///
    /// This function will return an error if the user lacks permission change
    /// attributes on the underlying file. It may also return an error in other
    /// os-specific unspecified cases.
    pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll<(), io::Error> {
        ::blocking_io(|| self.std().set_permissions(perm))
    }

    fn std(&mut self) -> &mut StdFile {
        self.std.as_mut().expect("`File` instance already shutdown")
    }
}

impl Read for File {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        ::would_block(|| self.std().read(buf))
    }
}

impl AsyncRead for File {
    unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
        false
    }
}

impl Write for File {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        ::would_block(|| self.std().write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        ::would_block(|| self.std().flush())
    }
}

impl AsyncWrite for File {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        ::blocking_io(|| {
            self.std = None;
            Ok(())
        })
    }
}

impl Drop for File {
    fn drop(&mut self) {
        if let Some(_std) = self.std.take() {
            // This is probably fine as closing a file *shouldn't* be a blocking
            // operation. That said, ideally `shutdown` is called first.
        }
    }
}
<|endoftext|>


<commit_before>use crate::sync::batch_semaphore::{AcquireError, Semaphore};
use std::cell::UnsafeCell;
use std::ops;

#[cfg(not(loom))]
const MAX_READS: usize = 32;

#[cfg(loom)]
const MAX_READS: usize = 10;

/// An asynchronous reader-writer lock
///
/// This type of lock allows a number of readers or at most one writer at any
/// point in time. The write portion of this lock typically allows modification
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that acquire the lock, therefore causing any tasks waiting for the lock to
/// become available to yield. An `RwLock` will allow any number of readers to
/// acquire the lock as long as a writer is not holding the lock.
///
/// The priority policy of Tokio's read-write lock is _fair_ (or
/// [_write-preferring_]), in order to ensure that readers cannot starve
/// writers. Fairness is ensured using a first-in, first-out queue for the tasks
/// awaiting the lock; if a task that wishes to acquire the write lock is at the
/// head of the queue, read locks will not be given out until the write lock has
/// been released. This is in contrast to the Rust standard library's
/// `std::sync::RwLock`, where the priority policy is dependent on the
/// operating system's implementation.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
/// returned from the locking methods implement [`Deref`](trait@std::ops::Deref)
/// (and [`DerefMut`](trait@std::ops::DerefMut)
/// for the `write` methods) to allow access to the content of the lock.
///
/// # Examples
///
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
///     let lock = RwLock::new(5);
///
///     // many reader locks can be held at once
///     {
///         let r1 = lock.read().await;
///         let r2 = lock.read().await;
///         assert_eq!(*r1, 5);
///         assert_eq!(*r2, 5);
///     } // read locks are dropped at this point
///
///     // only one write lock may be held, however
///     {
///         let mut w = lock.write().await;
///         *w += 1;
///         assert_eq!(*w, 6);
///     } // write lock is dropped here
/// }
/// ```
///
/// [`Mutex`]: struct@super::Mutex
/// [`RwLock`]: struct@RwLock
/// [`RwLockReadGuard`]: struct@RwLockReadGuard
/// [`RwLockWriteGuard`]: struct@RwLockWriteGuard
/// [`Send`]: trait@std::marker::Send
/// [_write-preferring_]: https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock#Priority_policies
#[derive(Debug)]
pub struct RwLock<T: ?Sized> {
    //semaphore to coordinate read and write access to T
    s: Semaphore,

    //inner data T
    c: UnsafeCell<T>,
}

/// RAII structure used to release the shared read access of a lock when
/// dropped.
///
/// This structure is created by the [`read`] method on
/// [`RwLock`].
///
/// [`read`]: method@RwLock::read
#[derive(Debug)]
pub struct RwLockReadGuard<'a, T: ?Sized> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

/// RAII structure used to release the exclusive write access of a lock when
/// dropped.
///
/// This structure is created by the [`write`] and method
/// on [`RwLock`].
///
/// [`write`]: method@RwLock::write
/// [`RwLock`]: struct@RwLock
#[derive(Debug)]
pub struct RwLockWriteGuard<'a, T: ?Sized> {
    permit: ReleasingPermit<'a, T>,
    lock: &'a RwLock<T>,
}

// Wrapper arround Permit that releases on Drop
#[derive(Debug)]
struct ReleasingPermit<'a, T: ?Sized> {
    num_permits: u16,
    lock: &'a RwLock<T>,
}

impl<'a, T: ?Sized> ReleasingPermit<'a, T> {
    async fn acquire(
        lock: &'a RwLock<T>,
        num_permits: u16,
    ) -> Result<ReleasingPermit<'a, T>, AcquireError> {
        lock.s.acquire(num_permits.into()).await?;
        Ok(Self { num_permits, lock })
    }
}

impl<T: ?Sized> Drop for ReleasingPermit<'_, T> {
    fn drop(&mut self) {
        self.lock.s.release(self.num_permits as usize);
    }
}

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check_send<T: Send>() {}
    fn check_sync<T: Sync>() {}
    fn check_unpin<T: Unpin>() {}
    // This has to take a value, since the async fn's return type is unnameable.
    fn check_send_sync_val<T: Send + Sync>(_t: T) {}

    check_send::<RwLock<u32>>();
    check_sync::<RwLock<u32>>();
    check_unpin::<RwLock<u32>>();

    check_sync::<RwLockReadGuard<'_, u32>>();
    check_unpin::<RwLockReadGuard<'_, u32>>();

    check_sync::<RwLockWriteGuard<'_, u32>>();
    check_unpin::<RwLockWriteGuard<'_, u32>>();

    let rwlock = RwLock::new(0);
    check_send_sync_val(rwlock.read());
    check_send_sync_val(rwlock.write());
}

// As long as T: Send + Sync, it's fine to send and share RwLock<T> between threads.
// If T were not Send, sending and sharing a RwLock<T> would be bad, since you can access T through
// RwLock<T>.
unsafe impl<T> Send for RwLock<T> where T: ?Sized + Send {}
unsafe impl<T> Sync for RwLock<T> where T: ?Sized + Send + Sync {}
unsafe impl<T> Sync for RwLockReadGuard<'_, T> where T: ?Sized + Send + Sync {}
unsafe impl<T> Sync for RwLockWriteGuard<'_, T> where T: ?Sized + Send + Sync {}

impl<T: ?Sized> RwLock<T> {
    /// Creates a new instance of an `RwLock<T>` which is unlocked.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// let lock = RwLock::new(5);
    /// ```
    pub fn new(value: T) -> RwLock<T>
    where
        T: Sized,
    {
        RwLock {
            c: UnsafeCell::new(value),
            s: Semaphore::new(MAX_READS),
        }
    }

    /// Locks this rwlock with shared read access, causing the current task
    /// to yield until the lock has been acquired.
    ///
    /// The calling task will yield until there are no more writers which
    /// hold the lock. There may be other readers currently inside the lock when
    /// this method returns.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Arc;
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let lock = Arc::new(RwLock::new(1));
    ///     let c_lock = lock.clone();
    ///
    ///     let n = lock.read().await;
    ///     assert_eq!(*n, 1);
    ///
    ///     tokio::spawn(async move {
    ///         // While main has an active read lock, we acquire one too.
    ///         let r = c_lock.read().await;
    ///         assert_eq!(*r, 1);
    ///     }).await.expect("The spawned task has paniced");
    ///
    ///     // Drop the guard after the spawned task finishes.
    ///     drop(n);
    ///}
    /// ```
    pub async fn read(&self) -> RwLockReadGuard<'_, T> {
        let permit = ReleasingPermit::acquire(self, 1).await.unwrap_or_else(|_| {
            // The semaphore was closed. but, we never explicitly close it, and we have a
            // handle to it through the Arc, which means that this can never happen.
            unreachable!()
        });
        RwLockReadGuard { lock: self, permit }
    }

    /// Locks this rwlock with exclusive write access, causing the current task
    /// to yield until the lock has been acquired.
    ///
    /// This function will not return while other writers or other readers
    /// currently have access to the lock.
    ///
    /// Returns an RAII guard which will drop the write access of this rwlock
    /// when dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///   let lock = RwLock::new(1);
    ///
    ///   let mut n = lock.write().await;
    ///   *n = 2;
    ///}
    /// ```
    pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
        let permit = ReleasingPermit::acquire(self, MAX_READS as u16)
            .await
            .unwrap_or_else(|_| {
                // The semaphore was closed. but, we never explicitly close it, and we have a
                // handle to it through the Arc, which means that this can never happen.
                unreachable!()
            });

        RwLockWriteGuard { lock: self, permit }
    }

    /// Consumes the lock, returning the underlying data.
    pub fn into_inner(self) -> T
    where
        T: Sized,
    {
        self.c.into_inner()
    }
}

impl<T: ?Sized> ops::Deref for RwLockReadGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T: ?Sized> ops::Deref for RwLockWriteGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.lock.c.get() }
    }
}

impl<T: ?Sized> ops::DerefMut for RwLockWriteGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.lock.c.get() }
    }
}

impl<T> From<T> for RwLock<T> {
    fn from(s: T) -> Self {
        Self::new(s)
    }
}

impl<T> Default for RwLock<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}
<commit_msg>sync: implement map methods of parking_lot fame (#2445)<commit_after>use crate::sync::batch_semaphore::Semaphore;
use std::cell::UnsafeCell;
use std::fmt;
use std::marker;
use std::mem;
use std::ops;

#[cfg(not(loom))]
const MAX_READS: usize = 32;

#[cfg(loom)]
const MAX_READS: usize = 10;

/// An asynchronous reader-writer lock
///
/// This type of lock allows a number of readers or at most one writer at any
/// point in time. The write portion of this lock typically allows modification
/// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access).
///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that acquire the lock, therefore causing any tasks waiting for the lock to
/// become available to yield. An `RwLock` will allow any number of readers to
/// acquire the lock as long as a writer is not holding the lock.
///
/// The priority policy of Tokio's read-write lock is _fair_ (or
/// [_write-preferring_]), in order to ensure that readers cannot starve
/// writers. Fairness is ensured using a first-in, first-out queue for the tasks
/// awaiting the lock; if a task that wishes to acquire the write lock is at the
/// head of the queue, read locks will not be given out until the write lock has
/// been released. This is in contrast to the Rust standard library's
/// `std::sync::RwLock`, where the priority policy is dependent on the
/// operating system's implementation.
///
/// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies [`Send`] to be shared across threads. The RAII guards
/// returned from the locking methods implement [`Deref`](trait@std::ops::Deref)
/// (and [`DerefMut`](trait@std::ops::DerefMut)
/// for the `write` methods) to allow access to the content of the lock.
///
/// # Examples
///
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
///     let lock = RwLock::new(5);
///
///     // many reader locks can be held at once
///     {
///         let r1 = lock.read().await;
///         let r2 = lock.read().await;
///         assert_eq!(*r1, 5);
///         assert_eq!(*r2, 5);
///     } // read locks are dropped at this point
///
///     // only one write lock may be held, however
///     {
///         let mut w = lock.write().await;
///         *w += 1;
///         assert_eq!(*w, 6);
///     } // write lock is dropped here
/// }
/// ```
///
/// [`Mutex`]: struct@super::Mutex
/// [`RwLock`]: struct@RwLock
/// [`RwLockReadGuard`]: struct@RwLockReadGuard
/// [`RwLockWriteGuard`]: struct@RwLockWriteGuard
/// [`Send`]: trait@std::marker::Send
/// [_write-preferring_]: https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock#Priority_policies
#[derive(Debug)]
pub struct RwLock<T: ?Sized> {
    //semaphore to coordinate read and write access to T
    s: Semaphore,

    //inner data T
    c: UnsafeCell<T>,
}

/// RAII structure used to release the shared read access of a lock when
/// dropped.
///
/// This structure is created by the [`read`] method on
/// [`RwLock`].
///
/// [`read`]: method@RwLock::read
/// [`RwLock`]: struct@RwLock
pub struct RwLockReadGuard<'a, T: ?Sized> {
    s: &'a Semaphore,
    data: *const T,
    marker: marker::PhantomData<&'a T>,
}

impl<'a, T> RwLockReadGuard<'a, T> {
    /// Make a new `RwLockReadGuard` for a component of the locked data.
    ///
    /// This operation cannot fail as the `RwLockReadGuard` passed in already
    /// locked the data.
    ///
    /// This is an associated function that needs to be
    /// used as `RwLockReadGuard::map(...)`. A method would interfere with
    /// methods of the same name on the contents of the locked data.
    ///
    /// This is an asynchronous version of [`RwLockReadGuard::map`] from the
    /// [`parking_lot` crate].
    ///
    /// [`RwLockReadGuard::map`]: https://docs.rs/lock_api/latest/lock_api/struct.RwLockReadGuard.html#method.map
    /// [`parking_lot` crate]: https://crates.io/crates/parking_lot
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::{RwLock, RwLockReadGuard};
    ///
    /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    /// struct Foo(u32);
    ///
    /// # #[tokio::main]
    /// # async fn main() {
    /// let lock = RwLock::new(Foo(1));
    ///
    /// let guard = lock.read().await;
    /// let guard = RwLockReadGuard::map(guard, |f| &f.0);
    ///
    /// assert_eq!(1, *guard);
    /// # }
    /// ```
    #[inline]
    pub fn map<F, U: ?Sized>(this: Self, f: F) -> RwLockReadGuard<'a, U>
    where
        F: FnOnce(&T) -> &U,
    {
        let data = f(&*this) as *const U;
        let s = this.s;
        // NB: Forget to avoid drop impl from being called.
        mem::forget(this);
        RwLockReadGuard {
            s,
            data,
            marker: marker::PhantomData,
        }
    }

    /// Attempts to make a new [`RwLockReadGuard`] for a component of the
    /// locked data. The original guard is returned if the closure returns
    /// `None`.
    ///
    /// This operation cannot fail as the `RwLockReadGuard` passed in already
    /// locked the data.
    ///
    /// This is an associated function that needs to be used as
    /// `RwLockReadGuard::try_map(..)`. A method would interfere with methods of the
    /// same name on the contents of the locked data.
    ///
    /// This is an asynchronous version of [`RwLockReadGuard::try_map`] from the
    /// [`parking_lot` crate].
    ///
    /// [`RwLockReadGuard::try_map`]: https://docs.rs/lock_api/latest/lock_api/struct.RwLockReadGuard.html#method.try_map
    /// [`parking_lot` crate]: https://crates.io/crates/parking_lot
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::{RwLock, RwLockReadGuard};
    ///
    /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    /// struct Foo(u32);
    ///
    /// # #[tokio::main]
    /// # async fn main() {
    /// let lock = RwLock::new(Foo(1));
    ///
    /// let guard = lock.read().await;
    /// let guard = RwLockReadGuard::try_map(guard, |f| Some(&f.0)).expect("should not fail");
    ///
    /// assert_eq!(1, *guard);
    /// # }
    /// ```
    #[inline]
    pub fn try_map<F, U: ?Sized>(this: Self, f: F) -> Result<RwLockReadGuard<'a, U>, Self>
    where
        F: FnOnce(&T) -> Option<&U>,
    {
        let data = match f(&*this) {
            Some(data) => data as *const U,
            None => return Err(this),
        };
        let s = this.s;
        // NB: Forget to avoid drop impl from being called.
        mem::forget(this);
        Ok(RwLockReadGuard {
            s,
            data,
            marker: marker::PhantomData,
        })
    }
}

impl<'a, T: ?Sized> fmt::Debug for RwLockReadGuard<'a, T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> fmt::Display for RwLockReadGuard<'a, T>
where
    T: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
    fn drop(&mut self) {
        self.s.release(1);
    }
}

/// RAII structure used to release the exclusive write access of a lock when
/// dropped.
///
/// This structure is created by the [`write`] and method
/// on [`RwLock`].
///
/// [`write`]: method@RwLock::write
/// [`RwLock`]: struct@RwLock
pub struct RwLockWriteGuard<'a, T: ?Sized> {
    s: &'a Semaphore,
    data: *mut T,
    marker: marker::PhantomData<&'a mut T>,
}

impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
    /// Make a new `RwLockWriteGuard` for a component of the locked data.
    ///
    /// This operation cannot fail as the `RwLockWriteGuard` passed in already
    /// locked the data.
    ///
    /// This is an associated function that needs to be used as
    /// `RwLockWriteGuard::map(..)`. A method would interfere with methods of
    /// the same name on the contents of the locked data.
    ///
    /// This is an asynchronous version of [`RwLockWriteGuard::map`] from the
    /// [`parking_lot` crate].
    ///
    /// [`RwLockWriteGuard::map`]: https://docs.rs/lock_api/latest/lock_api/struct.RwLockWriteGuard.html#method.map
    /// [`parking_lot` crate]: https://crates.io/crates/parking_lot
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::{RwLock, RwLockWriteGuard};
    ///
    /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    /// struct Foo(u32);
    ///
    /// # #[tokio::main]
    /// # async fn main() {
    /// let lock = RwLock::new(Foo(1));
    ///
    /// {
    ///     let mut mapped = RwLockWriteGuard::map(lock.write().await, |f| &mut f.0);
    ///     *mapped = 2;
    /// }
    ///
    /// assert_eq!(Foo(2), *lock.read().await);
    /// # }
    /// ```
    #[inline]
    pub fn map<F, U: ?Sized>(mut this: Self, f: F) -> RwLockWriteGuard<'a, U>
    where
        F: FnOnce(&mut T) -> &mut U,
    {
        let data = f(&mut *this) as *mut U;
        let s = this.s;
        // NB: Forget to avoid drop impl from being called.
        mem::forget(this);
        RwLockWriteGuard {
            s,
            data,
            marker: marker::PhantomData,
        }
    }

    /// Attempts to make  a new [`RwLockWriteGuard`] for a component of
    /// the locked data. The original guard is returned if the closure returns
    /// `None`.
    ///
    /// This operation cannot fail as the `RwLockWriteGuard` passed in already
    /// locked the data.
    ///
    /// This is an associated function that needs to be
    /// used as `RwLockWriteGuard::try_map(...)`. A method would interfere with
    /// methods of the same name on the contents of the locked data.
    ///
    /// This is an asynchronous version of [`RwLockWriteGuard::try_map`] from
    /// the [`parking_lot` crate].
    ///
    /// [`RwLockWriteGuard::try_map`]: https://docs.rs/lock_api/latest/lock_api/struct.RwLockWriteGuard.html#method.try_map
    /// [`parking_lot` crate]: https://crates.io/crates/parking_lot
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::{RwLock, RwLockWriteGuard};
    ///
    /// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    /// struct Foo(u32);
    ///
    /// # #[tokio::main]
    /// # async fn main() {
    /// let lock = RwLock::new(Foo(1));
    ///
    /// {
    ///     let guard = lock.write().await;
    ///     let mut guard = RwLockWriteGuard::try_map(guard, |f| Some(&mut f.0)).expect("should not fail");
    ///     *guard = 2;
    /// }
    ///
    /// assert_eq!(Foo(2), *lock.read().await);
    /// # }
    /// ```
    #[inline]
    pub fn try_map<F, U: ?Sized>(mut this: Self, f: F) -> Result<RwLockWriteGuard<'a, U>, Self>
    where
        F: FnOnce(&mut T) -> Option<&mut U>,
    {
        let data = match f(&mut *this) {
            Some(data) => data as *mut U,
            None => return Err(this),
        };
        let s = this.s;
        // NB: Forget to avoid drop impl from being called.
        mem::forget(this);
        Ok(RwLockWriteGuard {
            s,
            data,
            marker: marker::PhantomData,
        })
    }
}

impl<'a, T: ?Sized> fmt::Debug for RwLockWriteGuard<'a, T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> fmt::Display for RwLockWriteGuard<'a, T>
where
    T: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
    fn drop(&mut self) {
        self.s.release(MAX_READS);
    }
}

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check_send<T: Send>() {}
    fn check_sync<T: Sync>() {}
    fn check_unpin<T: Unpin>() {}
    // This has to take a value, since the async fn's return type is unnameable.
    fn check_send_sync_val<T: Send + Sync>(_t: T) {}

    check_send::<RwLock<u32>>();
    check_sync::<RwLock<u32>>();
    check_unpin::<RwLock<u32>>();

    check_send::<RwLockReadGuard<'_, u32>>();
    check_sync::<RwLockReadGuard<'_, u32>>();
    check_unpin::<RwLockReadGuard<'_, u32>>();

    check_send::<RwLockWriteGuard<'_, u32>>();
    check_sync::<RwLockWriteGuard<'_, u32>>();
    check_unpin::<RwLockWriteGuard<'_, u32>>();

    let rwlock = RwLock::new(0);
    check_send_sync_val(rwlock.read());
    check_send_sync_val(rwlock.write());
}

// As long as T: Send + Sync, it's fine to send and share RwLock<T> between threads.
// If T were not Send, sending and sharing a RwLock<T> would be bad, since you can access T through
// RwLock<T>.
unsafe impl<T> Send for RwLock<T> where T: ?Sized + Send {}
unsafe impl<T> Sync for RwLock<T> where T: ?Sized + Send + Sync {}
// NB: These impls need to be explicit since we're storing a raw pointer.
// Safety: Stores a raw pointer to `T`, so if `T` is `Sync`, the lock guard over
// `T` is `Send`.
unsafe impl<T> Send for RwLockReadGuard<'_, T> where T: ?Sized + Sync {}
unsafe impl<T> Sync for RwLockReadGuard<'_, T> where T: ?Sized + Send + Sync {}
unsafe impl<T> Sync for RwLockWriteGuard<'_, T> where T: ?Sized + Send + Sync {}
// Safety: Stores a raw pointer to `T`, so if `T` is `Sync`, the lock guard over
// `T` is `Send` - but since this is also provides mutable access, we need to
// make sure that `T` is `Send` since its value can be sent across thread
// boundaries.
unsafe impl<T> Send for RwLockWriteGuard<'_, T> where T: ?Sized + Send + Sync {}

impl<T: ?Sized> RwLock<T> {
    /// Creates a new instance of an `RwLock<T>` which is unlocked.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// let lock = RwLock::new(5);
    /// ```
    pub fn new(value: T) -> RwLock<T>
    where
        T: Sized,
    {
        RwLock {
            c: UnsafeCell::new(value),
            s: Semaphore::new(MAX_READS),
        }
    }

    /// Locks this rwlock with shared read access, causing the current task
    /// to yield until the lock has been acquired.
    ///
    /// The calling task will yield until there are no more writers which
    /// hold the lock. There may be other readers currently inside the lock when
    /// this method returns.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Arc;
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let lock = Arc::new(RwLock::new(1));
    ///     let c_lock = lock.clone();
    ///
    ///     let n = lock.read().await;
    ///     assert_eq!(*n, 1);
    ///
    ///     tokio::spawn(async move {
    ///         // While main has an active read lock, we acquire one too.
    ///         let r = c_lock.read().await;
    ///         assert_eq!(*r, 1);
    ///     }).await.expect("The spawned task has paniced");
    ///
    ///     // Drop the guard after the spawned task finishes.
    ///     drop(n);
    ///}
    /// ```
    pub async fn read(&self) -> RwLockReadGuard<'_, T> {
        self.s.acquire(1).await.unwrap_or_else(|_| {
            // The semaphore was closed. but, we never explicitly close it, and we have a
            // handle to it through the Arc, which means that this can never happen.
            unreachable!()
        });
        RwLockReadGuard {
            s: &self.s,
            data: self.c.get(),
            marker: marker::PhantomData,
        }
    }

    /// Locks this rwlock with exclusive write access, causing the current task
    /// to yield until the lock has been acquired.
    ///
    /// This function will not return while other writers or other readers
    /// currently have access to the lock.
    ///
    /// Returns an RAII guard which will drop the write access of this rwlock
    /// when dropped.
    ///
    /// # Examples
    ///
    /// ```
    /// use tokio::sync::RwLock;
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///   let lock = RwLock::new(1);
    ///
    ///   let mut n = lock.write().await;
    ///   *n = 2;
    ///}
    /// ```
    pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
        self.s.acquire(MAX_READS as u32).await.unwrap_or_else(|_| {
            // The semaphore was closed. but, we never explicitly close it, and we have a
            // handle to it through the Arc, which means that this can never happen.
            unreachable!()
        });
        RwLockWriteGuard {
            s: &self.s,
            data: self.c.get(),
            marker: marker::PhantomData,
        }
    }

    /// Consumes the lock, returning the underlying data.
    pub fn into_inner(self) -> T
    where
        T: Sized,
    {
        self.c.into_inner()
    }
}

impl<T: ?Sized> ops::Deref for RwLockReadGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.data }
    }
}

impl<T: ?Sized> ops::Deref for RwLockWriteGuard<'_, T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.data }
    }
}

impl<T: ?Sized> ops::DerefMut for RwLockWriteGuard<'_, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.data }
    }
}

impl<T> From<T> for RwLock<T> {
    fn from(s: T) -> Self {
        Self::new(s)
    }
}

impl<T: ?Sized> Default for RwLock<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}
<|endoftext|>