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

use frame::{
  ChannelAssignment, NumberType,
  Header, Footer,
};

use utility::to_u32;

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)             = tuple0;
      let (channel_assignment, bits_per_sample) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(tuple0.0 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(tuple0.0 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Add parser for frame<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use utility::to_u32;

pub fn frame_parser(input: &[u8], channels: u8) -> IResult<&[u8], Frame> {
  chain!(input,
    frame_header: header ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  )
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)             = tuple0;
      let (channel_assignment, bits_per_sample) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(tuple0.0 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(tuple0.0 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


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

use std::io;
use inflections::Inflect;

use WriteRust;
use common::Specs;

use super::spec_struct::SpecStructWriter;
use super::protocol_trait::ProtocolTraitWriter;

pub struct RootModuleWriter<'a> {
    specs: &'a Specs<'a>,
}

impl<'a> WriteRust for RootModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        // ensure that class ids remain consistent across the specs
        self.specs.assert_name_indexes_consistent();

        try!(writeln!(writer, "\npub mod method;"));
        for spec in self.specs {
            try!(writeln!(writer, "pub mod {};", spec.mod_name()));
        }
        try!(writeln!(writer, ""));

        try!(self.write_frame_type_constants(writer));
        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let protocol_trait = ProtocolTraitWriter::new(self.specs);
        try!(protocol_trait.write_rust_to(writer));

        for spec in self.specs {
            let spec_struct = SpecStructWriter::new(spec);
            try!(spec_struct.write_rust_to(writer));
        }

        Ok(())
    }
}

impl<'a> RootModuleWriter<'a> {
    pub fn new(specs: &'a Specs) -> Self {
        RootModuleWriter {
            specs: specs
        }
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Index values for classes shared among multiple specs\n\
            //\n\
            // Sometimes, the index value is repeated in different classes, but these are not reused\n\
            // within a single protocol\n\
            //\n\
            // Classes are currently only considered common if they are used in more than one\n\
            // spec. This behavior *may* change in the future as more specs are added.\n\
            //"
        ));

        let common_classes = {
            let mut classes = self.specs.common_classes().into_iter().collect::<Vec<_>>();
            classes.sort_by_key(|entry| (entry.1, entry.0));
            classes
        };

        for (class_name, index) in common_classes {
            let constant_class = class_name.to_constant_case();
            try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, index));
        }
        try!(writeln!(writer, ""));

        Ok(())
    }

    pub fn write_frame_type_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Frame types ids shared among multiple specs\n\
            //"
        ));

        let common_frame_types = {
            let mut frame_types = self.specs.common_frame_types().into_iter().collect::<Vec<_>>();
            frame_types.sort_by(|&(_, a), &(_, b)| a.cmp(&b));
            frame_types
        };

        for (class_name, index) in common_frame_types {
            let constant_class = class_name.to_constant_case();
            try!(writeln!(writer, "pub const {}: u8 = {};", constant_class, index));
        }
        try!(writeln!(writer, ""));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Index values for methods common among the different specs\n\
            //\n\
            // Methods are only considered common when:\n\
            //\n\
            //   * The index value is consistent across all of the specs\n\
            //   * The method is used in more than one primalgen.spec\n\
            //\n\
            // This may change in the future-- in that case, methods *may* be removed, or\n\
            // one of the requirements may be relaxed.\n\
            //"
        ));

        let common_methods = {
            let mut methods = self.specs.common_methods().into_iter().collect::<Vec<_>>();
            methods.sort_by(|&(a, _), &(b, _)| a.cmp(b));
            methods
        };

        for (class_name, methods) in common_methods {
            if methods.is_empty() {
                continue
            };

            let methods = {
                let mut methods = methods.into_iter().collect::<Vec<_>>();
                methods.sort_by(|&(_, a), &(_, b)| a.cmp(&b));
                methods
            };

            let constant_class = class_name.to_constant_case();

            for (method_name, index) in methods {
                let constant_method = method_name.to_constant_case();

                if constant_method != "_" {
                    try!(writeln!(writer, "pub const METHOD_{}_{}: u16 = {};", constant_class, constant_method, index));
                }
            }
            try!(writeln!(writer, ""));
        }

        Ok(())
    }
}<commit_msg>[primitives] Use explicit lifetimes for RootModuleWriter<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;
use inflections::Inflect;

use WriteRust;
use common::Specs;

use super::spec_struct::SpecStructWriter;
use super::protocol_trait::ProtocolTraitWriter;

pub struct RootModuleWriter<'a> {
    specs: &'a Specs<'a>,
}

impl<'a> WriteRust for RootModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        // ensure that class ids remain consistent across the specs
        self.specs.assert_name_indexes_consistent();

        try!(writeln!(writer, "\npub mod method;"));
        for spec in self.specs {
            try!(writeln!(writer, "pub mod {};", spec.mod_name()));
        }
        try!(writeln!(writer, ""));

        try!(self.write_frame_type_constants(writer));
        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let protocol_trait = ProtocolTraitWriter::new(self.specs);
        try!(protocol_trait.write_rust_to(writer));

        for spec in self.specs {
            let spec_struct = SpecStructWriter::new(spec);
            try!(spec_struct.write_rust_to(writer));
        }

        Ok(())
    }
}

impl<'a> RootModuleWriter<'a> {
    pub fn new(specs: &'a Specs<'a>) -> Self {
        RootModuleWriter {
            specs: specs
        }
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Index values for classes shared among multiple specs\n\
            //\n\
            // Sometimes, the index value is repeated in different classes, but these are not reused\n\
            // within a single protocol\n\
            //\n\
            // Classes are currently only considered common if they are used in more than one\n\
            // spec. This behavior *may* change in the future as more specs are added.\n\
            //"
        ));

        let common_classes = {
            let mut classes = self.specs.common_classes().into_iter().collect::<Vec<_>>();
            classes.sort_by_key(|entry| (entry.1, entry.0));
            classes
        };

        for (class_name, index) in common_classes {
            let constant_class = class_name.to_constant_case();
            try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, index));
        }
        try!(writeln!(writer, ""));

        Ok(())
    }

    pub fn write_frame_type_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Frame types ids shared among multiple specs\n\
            //"
        ));

        let common_frame_types = {
            let mut frame_types = self.specs.common_frame_types().into_iter().collect::<Vec<_>>();
            frame_types.sort_by(|&(_, a), &(_, b)| a.cmp(&b));
            frame_types
        };

        for (class_name, index) in common_frame_types {
            let constant_class = class_name.to_constant_case();
            try!(writeln!(writer, "pub const {}: u8 = {};", constant_class, index));
        }
        try!(writeln!(writer, ""));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(
            writer,
            "//\n\
            // Index values for methods common among the different specs\n\
            //\n\
            // Methods are only considered common when:\n\
            //\n\
            //   * The index value is consistent across all of the specs\n\
            //   * The method is used in more than one primalgen.spec\n\
            //\n\
            // This may change in the future-- in that case, methods *may* be removed, or\n\
            // one of the requirements may be relaxed.\n\
            //"
        ));

        let common_methods = {
            let mut methods = self.specs.common_methods().into_iter().collect::<Vec<_>>();
            methods.sort_by(|&(a, _), &(b, _)| a.cmp(b));
            methods
        };

        for (class_name, methods) in common_methods {
            if methods.is_empty() {
                continue
            };

            let methods = {
                let mut methods = methods.into_iter().collect::<Vec<_>>();
                methods.sort_by(|&(_, a), &(_, b)| a.cmp(&b));
                methods
            };

            let constant_class = class_name.to_constant_case();

            for (method_name, index) in methods {
                let constant_method = method_name.to_constant_case();

                if constant_method != "_" {
                    try!(writeln!(writer, "pub const METHOD_{}_{}: u16 = {};", constant_class, constant_method, index));
                }
            }
            try!(writeln!(writer, ""));
        }

        Ok(())
    }
}<|endoftext|>


<commit_before>//! The geometry module defines the Geometry trait implemented by
//! the various geometry in the ray tracer and provides some standard
//! geometry for rendering

use linalg;

pub use self::differential_geometry::DifferentialGeometry;
pub use self::intersection::Intersection;
pub use self::instance::Instance;
pub use self::sphere::Sphere;

pub mod differential_geometry;
pub mod intersection;
pub mod instance;
pub mod sphere;

pub trait Geometry {
    /// Test a ray for intersection with the geometry.
    /// The ray should have been previously transformed into the geometry's
    /// object space otherwise the test will be incorrect.
    /// Returns the differential geometry containing the hit information if the
    /// ray hit the object and set's the ray's `max_t` member accordingly
    fn intersect(&self, ray: &mut linalg::Ray) -> Option<DifferentialGeometry>;
}

<commit_msg>Add Geometry trait description<commit_after>//! The geometry module defines the Geometry trait implemented by
//! the various geometry in the ray tracer and provides some standard
//! geometry for rendering

use linalg;

pub use self::differential_geometry::DifferentialGeometry;
pub use self::intersection::Intersection;
pub use self::instance::Instance;
pub use self::sphere::Sphere;

pub mod differential_geometry;
pub mod intersection;
pub mod instance;
pub mod sphere;

/// Trait implemented by geometric primitives
pub trait Geometry {
    /// Test a ray for intersection with the geometry.
    /// The ray should have been previously transformed into the geometry's
    /// object space otherwise the test will be incorrect.
    /// Returns the differential geometry containing the hit information if the
    /// ray hit the object and set's the ray's `max_t` member accordingly
    fn intersect(&self, ray: &mut linalg::Ray) -> Option<DifferentialGeometry>;
}

<|endoftext|>


<commit_before>use probability::distribution::{Categorical, Sample};
use sqlite::{Connection, State};
use std::collections::HashMap;

use config::Config;
use {Result, Source};

pub struct Workload {
    patterns: Vec<Pattern>,
    source: Source,
    distribution: Categorical,
}

pub struct Pattern {
    pub name: String,
    pub components: Vec<Component>,
}

pub struct Component {
    pub name: String,
    pub dynamic_power: Vec<f64>,
    pub leakage_power: f64,
}

impl Workload {
    pub fn new(config: &Config, source: &Source) -> Result<Workload> {
        let mut patterns = vec![];
        if let Some(ref configs) = config.collection("patterns") {
            for config in configs {
                patterns.push(try!(Pattern::new(config)));
            }
        }
        let count = patterns.len();
        if count == 0 {
            raise!("at least one workload pattern is required");
        }
        Ok(Workload {
            patterns: patterns,
            source: source.clone(),
            distribution: Categorical::new(&vec![1.0 / count as f64; count]),
        })
    }

    pub fn next<'l>(&'l mut self) -> Option<&'l Pattern> {
        Some(&self.patterns[self.distribution.sample(&mut self.source)])
    }
}

impl Pattern {
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload pattern database");
        let backend = ok!(Connection::open(&path));

        info!(target: "workload", "Reading {:?}...", &path);
        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let mut names = match config.get::<String>("query_names") {
            Some(query) => try!(read_names(&backend, query)),
            _ => raise!("an SQL query for reading components’ names is required"),
        };
        let mut dynamic_power = match config.get::<String>("query_dynamic_power") {
            Some(query) => try!(read_dynamic_power(&backend, query)),
            _ => raise!("an SQL query for reading the dynamic power is required"),
        };
        let mut leakage_power = match config.get::<String>("query_leakage_power") {
            Some(query) => try!(read_leakage_power(&backend, query)),
            _ => raise!("an SQL query for reading the leakage power is required"),
        };

        let mut ids = names.keys().map(|&name| name).collect::<Vec<_>>();
        ids.sort();

        let mut components = vec![];
        for i in ids {
            components.push(Component {
                name: names.remove(&i).unwrap(),
                dynamic_power: match dynamic_power.remove(&i) {
                    Some(value) => value,
                    _ => raise!("cannot find the dynamic power of a component"),
                },
                leakage_power: match leakage_power.remove(&i) {
                    Some(value) => value,
                    _ => raise!("cannot find the leakage power of a component"),
                },
            });
        }

        Ok(Pattern { name: name, components: components })
    }
}

fn read_names(backend: &Connection, query: &str) -> Result<HashMap<i64, String>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.insert(ok!(statement.read::<i64>(0)), ok!(statement.read::<String>(1)));
    }
    Ok(data)
}

fn read_dynamic_power(backend: &Connection, query: &str) -> Result<HashMap<i64, Vec<f64>>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.entry(ok!(statement.read::<i64>(0))).or_insert_with(|| vec![])
                                                 .push(ok!(statement.read::<f64>(1)));
    }
    Ok(data)
}

fn read_leakage_power(backend: &Connection, query: &str) -> Result<HashMap<i64, f64>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.insert(ok!(statement.read::<i64>(0)), ok!(statement.read::<f64>(1)));
    }
    Ok(data)
}

#[cfg(test)]
mod tests {
    use assert;
    use sqlite::Connection;

    #[test]
    fn read_names() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_names(&backend, "
            SELECT `component_id`, `name` FROM `static`;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), "core0");
        assert_eq!(data.get(&1).unwrap(), "core1");
        assert_eq!(data.get(&2).unwrap(), "l30");
    }

    #[test]
    fn read_dynamic_power() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_dynamic_power(&backend, "
            SELECT `component_id`, `dynamic_power` FROM `dynamic`
            ORDER BY `time` ASC;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        for (_, data) in &data {
            assert_eq!(data.len(), 76);
        }
        assert::close(&[data.get(&0).unwrap()[2]], &[0.608065803127267], 1e-14);
        assert::close(&[data.get(&1).unwrap()[4]], &[9.19809606345627], 1e-14);
        assert::close(&[data.get(&2).unwrap()[0]], &[0.00613345574868796], 1e-14);
    }

    #[test]
    fn read_leakage_power() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_leakage_power(&backend, "
            SELECT `component_id`, `leakage_power` FROM `static`;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), data.get(&1).unwrap());
    }
}
<commit_msg>A minor clarification<commit_after>use probability::distribution::{Categorical, Sample};
use sqlite::{Connection, State};
use std::collections::HashMap;

use config::Config;
use {Result, Source};

pub struct Workload {
    patterns: Vec<Pattern>,
    source: Source,
    distribution: Categorical,
}

pub struct Pattern {
    pub name: String,
    pub components: Vec<Component>,
}

pub struct Component {
    pub name: String,
    pub dynamic_power: Vec<f64>,
    pub leakage_power: f64,
}

impl Workload {
    pub fn new(config: &Config, source: &Source) -> Result<Workload> {
        let mut patterns = vec![];
        if let Some(ref configs) = config.collection("patterns") {
            for config in configs {
                patterns.push(try!(Pattern::new(config)));
            }
        }
        let count = patterns.len();
        if count == 0 {
            raise!("at least one workload pattern is required");
        }
        Ok(Workload {
            patterns: patterns,
            source: source.clone(),
            distribution: Categorical::new(&vec![1.0 / count as f64; count]),
        })
    }

    pub fn next<'l>(&'l mut self) -> Option<&'l Pattern> {
        Some(&self.patterns[self.distribution.sample(&mut self.source)])
    }
}

impl Pattern {
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload pattern database");
        let backend = ok!(Connection::open(&path));

        info!(target: "workload", "Reading {:?}...", &path);
        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let mut names = match config.get::<String>("query_names") {
            Some(query) => try!(read_names(&backend, query)),
            _ => raise!("an SQL query for reading components’ names is required"),
        };
        let mut dynamic_power = match config.get::<String>("query_dynamic_power") {
            Some(query) => try!(read_dynamic_power(&backend, query)),
            _ => raise!("an SQL query for reading the dynamic power is required"),
        };
        let mut leakage_power = match config.get::<String>("query_leakage_power") {
            Some(query) => try!(read_leakage_power(&backend, query)),
            _ => raise!("an SQL query for reading the leakage power is required"),
        };

        let mut ids = names.keys().map(|&id| id).collect::<Vec<_>>();
        ids.sort();

        let mut components = vec![];
        for id in ids {
            components.push(Component {
                name: names.remove(&id).unwrap(),
                dynamic_power: match dynamic_power.remove(&id) {
                    Some(value) => value,
                    _ => raise!("cannot find the dynamic power of a component"),
                },
                leakage_power: match leakage_power.remove(&id) {
                    Some(value) => value,
                    _ => raise!("cannot find the leakage power of a component"),
                },
            });
        }

        Ok(Pattern { name: name, components: components })
    }
}

fn read_names(backend: &Connection, query: &str) -> Result<HashMap<i64, String>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.insert(ok!(statement.read::<i64>(0)), ok!(statement.read::<String>(1)));
    }
    Ok(data)
}

fn read_dynamic_power(backend: &Connection, query: &str) -> Result<HashMap<i64, Vec<f64>>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.entry(ok!(statement.read::<i64>(0))).or_insert_with(|| vec![])
                                                 .push(ok!(statement.read::<f64>(1)));
    }
    Ok(data)
}

fn read_leakage_power(backend: &Connection, query: &str) -> Result<HashMap<i64, f64>> {
    let mut data = HashMap::new();
    let mut statement = ok!(backend.prepare(query));
    while State::Row == ok!(statement.step()) {
        data.insert(ok!(statement.read::<i64>(0)), ok!(statement.read::<f64>(1)));
    }
    Ok(data)
}

#[cfg(test)]
mod tests {
    use assert;
    use sqlite::Connection;

    #[test]
    fn read_names() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_names(&backend, "
            SELECT `component_id`, `name` FROM `static`;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), "core0");
        assert_eq!(data.get(&1).unwrap(), "core1");
        assert_eq!(data.get(&2).unwrap(), "l30");
    }

    #[test]
    fn read_dynamic_power() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_dynamic_power(&backend, "
            SELECT `component_id`, `dynamic_power` FROM `dynamic`
            ORDER BY `time` ASC;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        for (_, data) in &data {
            assert_eq!(data.len(), 76);
        }
        assert::close(&[data.get(&0).unwrap()[2]], &[0.608065803127267], 1e-14);
        assert::close(&[data.get(&1).unwrap()[4]], &[9.19809606345627], 1e-14);
        assert::close(&[data.get(&2).unwrap()[0]], &[0.00613345574868796], 1e-14);
    }

    #[test]
    fn read_leakage_power() {
        let backend = Connection::open("tests/fixtures/parsec/blackscholes.sqlite3").unwrap();
        let data = super::read_leakage_power(&backend, "
            SELECT `component_id`, `leakage_power` FROM `static`;
        ").unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), data.get(&1).unwrap());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;
use std::net::ToSocketAddrs;
use std::cell::RefCell;
use std::rc::Rc;
use gj::io::{AsyncRead, AsyncWrite};

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(S, B), gj::io::Error<(S, B)>>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled((stream, buf)))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).then_else(move |r| match r {
                Ok((stream, slice)) => Ok(echo(stream, slice.buf)),
                Err(gj::io::Error {state: (stream, slice), error}) =>
                    Err(gj::io::Error::new((stream, slice.buf), error)),
            }))
        }
    })
}

type ThreadedState = (::gj::io::tcp::Stream, Vec<u8>);

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet<ThreadedState, gj::io::Error<ThreadedState>>,
               buffer_pool: Rc<RefCell<Vec<Vec<u8>>>>)
               -> gj::Promise<(), ::std::io::Error>
{
    receiver.accept().lift().then(move |(receiver, stream)| {
        match buffer_pool.borrow_mut().pop() {
            None => println!("Dropping new connection because buffer pool is full."),
            Some(buf) => task_set.add(echo(stream, buf)),
        }
        Ok(accept_loop(receiver, task_set, buffer_pool))
    })
}

struct Reaper {
    buffer_pool: Rc<RefCell<Vec<Vec<u8>>>>,
}

impl gj::TaskReaper<ThreadedState, gj::io::Error<ThreadedState>> for Reaper {
    fn task_succeeded(&mut self, (_, buf): ThreadedState) {
        self.buffer_pool.borrow_mut().push(buf);
    }
    fn task_failed(&mut self, error: gj::io::Error<ThreadedState>) {
        self.buffer_pool.borrow_mut().push(error.state.1);
        println!("Task failed: {}", error.error);
    }
}

pub fn main() {
    let args : Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    const NUM_BUFFERS: usize = 1;

    gj::EventLoop::top_level(move |wait_scope| {
        let mut buffers = Vec::with_capacity(NUM_BUFFERS);
        for _ in 0..NUM_BUFFERS {
            buffers.push(vec![0; 1024]);
        }
        let buffer_pool = Rc::new(RefCell::new(buffers));

        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        let reaper = Box::new(Reaper { buffer_pool: buffer_pool.clone() });
        accept_loop(listener, gj::TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope)
    }).unwrap();
}
<commit_msg>A bit of cleanup on the echo server.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Echo server with a bounded buffer pool.

extern crate gj;
use std::net::ToSocketAddrs;
use std::cell::RefCell;
use std::rc::Rc;
use gj::io::{AsyncRead, AsyncWrite};

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(S, B), gj::io::Error<(S, B)>>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled((stream, buf)))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).then_else(move |r| match r {
                Ok((stream, slice)) => Ok(echo(stream, slice.buf)),
                Err(gj::io::Error {state: (stream, slice), error}) =>
                    Err(gj::io::Error::new((stream, slice.buf), error)),
            }))
        }
    })
}

type ThreadedState = (::gj::io::tcp::Stream, Vec<u8>);

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet<ThreadedState, gj::io::Error<ThreadedState>>,
               buffer_pool: Rc<RefCell<Vec<Vec<u8>>>>)
               -> gj::Promise<(), ::std::io::Error>
{
    receiver.accept().lift().then(move |(receiver, stream)| {
        match buffer_pool.borrow_mut().pop() {
            None => println!("Buffer pool has no free buffers. Dropping connection."),
            Some(buf) => task_set.add(echo(stream, buf)),
        }
        Ok(accept_loop(receiver, task_set, buffer_pool))
    })
}

struct Reaper {
    buffer_pool: Rc<RefCell<Vec<Vec<u8>>>>,
}

impl gj::TaskReaper<ThreadedState, gj::io::Error<ThreadedState>> for Reaper {
    fn task_succeeded(&mut self, (_, buf): ThreadedState) {
        self.buffer_pool.borrow_mut().push(buf);
    }
    fn task_failed(&mut self, error: gj::io::Error<ThreadedState>) {
        self.buffer_pool.borrow_mut().push(error.state.1);
        println!("Task failed: {}", error.error);
    }
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    const NUM_BUFFERS: usize = 64;

    gj::EventLoop::top_level(move |wait_scope| {
        let mut buffers = Vec::with_capacity(NUM_BUFFERS);
        for _ in 0..NUM_BUFFERS {
            buffers.push(vec![0; 1024]);
        }
        let buffer_pool = Rc::new(RefCell::new(buffers));

        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        let reaper = Box::new(Reaper { buffer_pool: buffer_pool.clone() });
        accept_loop(listener, gj::TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope)
    }).unwrap();
}
<|endoftext|>


<commit_before>use crate::{config::Colors, termbox, utils};
use std::{cmp::min, ops::RangeBounds, vec::Drain};
use termbox_simple::Termbox;

#[derive(Clone, Debug)]
pub(crate) struct InputLine {
    /// Input buffer
    buffer: Vec<char>,

    /// Vector of whitespace indices in `buffer`. Used to split lines in wrapping mode. Gets
    /// invalidated in `calculate_height` is called.
    ws_indices: Vec<i32>,
}

impl InputLine {
    pub(crate) fn new() -> InputLine {
        InputLine {
            buffer: Vec::with_capacity(512),
            ws_indices: Vec::with_capacity(32),
        }
    }

    /// Creates an InputLine from a buffer.
    pub(crate) fn from_buffer(buffer: Vec<char>) -> InputLine {
        InputLine {
            buffer,
            ws_indices: Vec::with_capacity(32),
        }
    }

    /// Returns pointer to InputLine's buffer
    pub(crate) fn get_buffer(&self) -> &[char] {
        &self.buffer
    }

    /**
     **    Functions to interface with InputLine::buffer
     **/

    /// Interface for Vec::get()
    pub(crate) fn get(&self, idx: usize) -> char {
        self.buffer[idx]
    }

    /// Interface for Vec::len()
    pub(crate) fn len(&self) -> usize {
        self.buffer.len()
    }

    /// Interface for Vec::drain()
    pub(crate) fn drain<R>(&mut self, range: R) -> Drain<char>
    where
        R: RangeBounds<usize>,
    {
        self.buffer.drain(range)
    }

    /// Interface for Vec::remove()
    pub(crate) fn remove(&mut self, idx: usize) -> char {
        self.buffer.remove(idx)
    }

    /// Interface for Vec::insert()
    pub(crate) fn insert(&mut self, idx: usize, element: char) {
        self.buffer.insert(idx, element);
    }

    /**
     **    End of InputLine::buffer interface
     **/

    /// Calculate hedight of the widget, taking nickname length into account. Only needed when
    /// buffer is wider than width and scrolling is off.
    pub(crate) fn calculate_height(&mut self, width: i32, nick_length: usize) -> usize {
        let mut line_count: i32 = 1;
        let mut line_width: i32 = width - nick_length as i32;
        let mut last_whitespace_idx: Option<i32> = None;
        let mut prev_char_is_whitespace = false;
        let mut current_line_length = 0;

        // clear cached indices
        self.ws_indices.clear();

        for (current_idx, c) in self.buffer.iter().enumerate() {
            let current_idx = current_idx as i32;
            current_line_length += 1;

            if c.is_whitespace() {
                // Splitting
                if current_line_length > line_width {
                    // we're on a whitespace so just go to next line
                    line_count += 1;
                    // this character will be the first one on the next line
                    current_line_length = 1;
                    // nick is shown on the first line, set width to full width in the consecutive
                    // lines
                    line_width = width;
                    // store index for drawing
                    self.ws_indices.push(current_idx);
                }
                // store whitespace for splitting
                last_whitespace_idx = Some(current_idx);
                prev_char_is_whitespace = true;
            } else {
                // Splitting
                if current_line_length > line_width {
                    // if the previous character was a whitespace, then we have a clean split
                    if !prev_char_is_whitespace && last_whitespace_idx.is_some() {
                        // move back to the last whitespace and get the length of the input that
                        // will be on the next line
                        current_line_length = current_idx - last_whitespace_idx.unwrap();
                        // store index for drawing
                        self.ws_indices.push(last_whitespace_idx.unwrap() + 1);
                    } else {
                        // unclean split on non-whitespace
                        current_line_length = 1;
                        // store index for drawing
                        self.ws_indices.push(current_idx);
                    }
                    // invalidate whitespace since we split here
                    last_whitespace_idx = None;
                    // moved to next line
                    line_count += 1;
                    // set width to full width
                    line_width = width;
                }
                prev_char_is_whitespace = false;
            }
        }

        // Last line length is `line_width`, make room for cursor
        if current_line_length == line_width {
            line_count += 1;
        }

        line_count as usize
    }
}

fn draw_line_scroll(
    tb: &mut Termbox,
    colors: &Colors,
    line: &[char],
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    scroll: i32,
) {
    let slice: &[char] =
        &line[scroll as usize..min(line.len(), (scroll + (width - pos_x)) as usize)];
    termbox::print_chars(tb, pos_x, pos_y, colors.user_msg, slice.iter().copied());
    // On my terminal the cursor is only shown when there's a character
    // under it.
    if cursor as usize >= line.len() {
        tb.change_cell(
            pos_x + cursor - scroll,
            pos_y,
            ' ',
            colors.cursor.fg,
            colors.cursor.bg,
        );
    }

    tb.set_cursor(Some(((pos_x + cursor - scroll) as u16, pos_y as u16)));
}

pub(crate) struct CompletionRange {
    start_idx: usize,
    end_idx: usize,
}

fn draw_line_wrapped(
    tb: &mut Termbox,
    colors: &Colors,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    line: &InputLine,
    completion_range: &Option<CompletionRange>,
) {
    let mut col = pos_x;
    let mut line_num = 0;

    let mut cursor_xychar = (0, 0, ' ');
    let mut check_cursor = |char_idx: usize, cursor: i32, pos_x: i32, pos_y: i32, c: char| {
        if char_idx == cursor as usize {
            cursor_xychar = (pos_x, pos_y, c);
        }
    };
    let mut ws_indices_iter = line.ws_indices.iter().copied().peekable();
    for (char_idx, c) in line.buffer.iter().enumerate() {
        let mut style = colors.user_msg;
        // for autocompletion highlighting
        if let Some(completion_range) = completion_range {
            if char_idx >= completion_range.start_idx && char_idx < completion_range.end_idx {
                style = colors.completion;
            }
        }
        // If ws_indices_iter yields we already know the indices for the start of each line. If it
        // does not then we just continue outputting on this line.
        if let Some(next_line_start) = ws_indices_iter.peek() {
            if char_idx == *next_line_start as usize {
                // move to next line
                line_num += 1;
                // reset column
                col = 0;
                // move to the next line start index
                ws_indices_iter.next();
            }
        }
        // Write out the character
        tb.change_cell(col, pos_y + line_num, *c, style.fg, style.bg);
        // Check if the cursor is on this character
        check_cursor(char_idx, cursor, col, pos_y + line_num, *c);
        col += 1;
    }

    // Cursor may be (probably) after all text
    if col == width {
        // render cursor on next line
        line_num += 1;
        col = 0;
    }
    check_cursor(line.buffer.len(), cursor, col, pos_y + line_num, ' ');

    tb.change_cell(
        cursor_xychar.0,
        cursor_xychar.1,
        cursor_xychar.2,
        colors.cursor.fg,
        colors.cursor.bg,
    );

    tb.set_cursor(Some(((cursor_xychar.0) as u16, (cursor_xychar.1) as u16)));
}

pub(crate) fn draw_line_autocomplete(
    original_buffer: &InputLine,
    insertion_point: usize,
    word_starts: usize,
    completions: &[String],
    current_completion: usize,
    tb: &mut Termbox,
    colors: &Colors,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    should_scroll: bool,
    scroll: Option<i32>,
) {
    let completion: &str = &completions[current_completion];

    let mut orig_buf_iter = original_buffer.get_buffer().iter().copied();
    let mut completion_iter = completion.chars();

    if should_scroll {
        let cursor_x_off = cursor - scroll.unwrap();
        let cursor_y_off = 0;

        // draw a placeholder for the cursor
        tb.change_cell(
            pos_x + cursor_x_off,
            pos_y + cursor_y_off,
            ' ',
            colors.user_msg.fg,
            colors.user_msg.bg,
        );

        let iter: utils::InsertIterator<char> =
            utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

        for (char_idx, char) in iter.enumerate() {
            let x_off;
            let y_off;
            let mut can_scroll = true;
            if should_scroll {
                let scroll = scroll.unwrap_or(0);
                x_off = (char_idx as i32) - scroll;
                y_off = 0;
                if char_idx >= ((scroll + width) as usize) {
                    break;
                }
                if char_idx < scroll as usize {
                    can_scroll = false
                }
            } else {
                x_off = char_idx as i32 % width;
                y_off = char_idx as i32 / width;
            }
            if can_scroll {
                if char_idx >= word_starts && char_idx < insertion_point + completion.len() {
                    tb.change_cell(
                        pos_x + x_off,
                        pos_y + y_off,
                        char,
                        colors.completion.fg,
                        colors.completion.bg,
                    );
                } else {
                    tb.change_cell(
                        pos_x + x_off,
                        pos_y + y_off,
                        char,
                        colors.user_msg.fg,
                        colors.user_msg.bg,
                    );
                }
            }
        }
        tb.set_cursor(Some((
            (pos_x + cursor_x_off) as u16,
            (pos_y + cursor_y_off) as u16,
        )));
    } else {
        // TODO: Think of a better way to handle this inefficiency
        let iter: utils::InsertIterator<char> =
            utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

        let mut line = InputLine::from_buffer(iter.collect());
        line.calculate_height(width, pos_x as usize);
        let completion_range = CompletionRange {
            start_idx: word_starts,
            end_idx: (insertion_point + completion.len()),
        };
        draw_line_wrapped(
            tb,
            colors,
            pos_x,
            pos_y,
            width,
            cursor,
            &line,
            &Some(completion_range),
        );
    }
}

pub(crate) fn draw_line(
    tb: &mut Termbox,
    colors: &Colors,
    line: &InputLine,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    should_scroll: bool,
    scroll: Option<i32>,
    completion_range: Option<CompletionRange>,
) {
    if should_scroll || (line.len() as i32) < width - pos_x {
        draw_line_scroll(
            tb,
            colors,
            &line.buffer,
            pos_x,
            pos_y,
            width,
            cursor,
            scroll.unwrap_or(0),
        );
    } else {
        draw_line_wrapped(
            tb,
            colors,
            pos_x,
            pos_y,
            width,
            cursor,
            &line,
            &completion_range,
        );
    }
}

#[cfg(test)]
mod tests {
    use super::InputLine;
    #[test]
    fn test_calculate_height() {
        let buffer: Vec<char> = String::from("012345").chars().collect();
        let mut line = InputLine::from_buffer(buffer);

        assert_eq!(line.calculate_height(6, 2), 2);

        // one extra line for the cursor
        assert_eq!(line.calculate_height(6, 0), 2);
        assert_eq!(line.calculate_height(3, 0), 3);

        line.insert(3, ' '); // 123 456
        assert_eq!(line.calculate_height(6, 0), 2);

        // Input containing lines that are longer than the width
        let buffer: Vec<char> = String::from("01 3456").chars().collect();
        let mut line = InputLine::from_buffer(buffer);
        assert_eq!(line.calculate_height(3, 0), 3);
        line.insert(line.len(), ' ');
        // "01 3456 "
        // Each line should be:
        // "01 "
        // "345"
        // "6 "
        assert_eq!(line.calculate_height(3, 0), 3);

        line.insert(line.len(), '8');
        line.insert(line.len(), '9');
        line.insert(line.len(), 'X');
        line.insert(line.len(), '1');
        line.insert(line.len(), '2');
        line.insert(line.len(), ' ');
        line.insert(line.len(), '4');
        // "01 3456 89X12 "
        // Each line should be:
        // "01 "
        // "345"
        // "6 "
        // "89X"
        // "12 "
        // "4"
        assert_eq!(line.calculate_height(3, 0), 6);

        // First line has no whitespaces, but whitespaces follow
        let buffer: Vec<char> = String::from("012345 78 X 12 34").chars().collect();
        let mut line = InputLine::from_buffer(buffer);
        // "0123"
        // "45 "
        // "78 X"
        // " 12 "
        // "34"
        assert_eq!(line.calculate_height(4, 0), 5);
    }
}
<commit_msg>tui: Update a doc, add a TODO<commit_after>use crate::{config::Colors, termbox, utils};
use std::{cmp::min, ops::RangeBounds, vec::Drain};
use termbox_simple::Termbox;

#[derive(Clone, Debug)]
pub(crate) struct InputLine {
    /// Input buffer
    buffer: Vec<char>,

    /// Vector of whitespace indices in `buffer`. Used to split lines in wrapping mode.
    /// Generated/updated in `calculate_height`, used when drawing.
    // TODO (osa): Cache this and generate only when needed when drawing?
    ws_indices: Vec<i32>,
}

impl InputLine {
    pub(crate) fn new() -> InputLine {
        InputLine {
            buffer: Vec::with_capacity(512),
            ws_indices: Vec::with_capacity(32),
        }
    }

    /// Creates an InputLine from a buffer.
    pub(crate) fn from_buffer(buffer: Vec<char>) -> InputLine {
        InputLine {
            buffer,
            ws_indices: Vec::with_capacity(32),
        }
    }

    /// Returns pointer to InputLine's buffer
    pub(crate) fn get_buffer(&self) -> &[char] {
        &self.buffer
    }

    /**
     **    Functions to interface with InputLine::buffer
     **/

    /// Interface for Vec::get()
    pub(crate) fn get(&self, idx: usize) -> char {
        self.buffer[idx]
    }

    /// Interface for Vec::len()
    pub(crate) fn len(&self) -> usize {
        self.buffer.len()
    }

    /// Interface for Vec::drain()
    pub(crate) fn drain<R>(&mut self, range: R) -> Drain<char>
    where
        R: RangeBounds<usize>,
    {
        self.buffer.drain(range)
    }

    /// Interface for Vec::remove()
    pub(crate) fn remove(&mut self, idx: usize) -> char {
        self.buffer.remove(idx)
    }

    /// Interface for Vec::insert()
    pub(crate) fn insert(&mut self, idx: usize, element: char) {
        self.buffer.insert(idx, element);
    }

    /**
     **    End of InputLine::buffer interface
     **/

    /// Calculate hedight of the widget, taking nickname length into account. Only needed when
    /// buffer is wider than width and scrolling is off.
    pub(crate) fn calculate_height(&mut self, width: i32, nick_length: usize) -> usize {
        let mut line_count: i32 = 1;
        let mut line_width: i32 = width - nick_length as i32;
        let mut last_whitespace_idx: Option<i32> = None;
        let mut prev_char_is_whitespace = false;
        let mut current_line_length = 0;

        // clear cached indices
        self.ws_indices.clear();

        for (current_idx, c) in self.buffer.iter().enumerate() {
            let current_idx = current_idx as i32;
            current_line_length += 1;

            if c.is_whitespace() {
                // Splitting
                if current_line_length > line_width {
                    // we're on a whitespace so just go to next line
                    line_count += 1;
                    // this character will be the first one on the next line
                    current_line_length = 1;
                    // nick is shown on the first line, set width to full width in the consecutive
                    // lines
                    line_width = width;
                    // store index for drawing
                    self.ws_indices.push(current_idx);
                }
                // store whitespace for splitting
                last_whitespace_idx = Some(current_idx);
                prev_char_is_whitespace = true;
            } else {
                // Splitting
                if current_line_length > line_width {
                    // if the previous character was a whitespace, then we have a clean split
                    if !prev_char_is_whitespace && last_whitespace_idx.is_some() {
                        // move back to the last whitespace and get the length of the input that
                        // will be on the next line
                        current_line_length = current_idx - last_whitespace_idx.unwrap();
                        // store index for drawing
                        self.ws_indices.push(last_whitespace_idx.unwrap() + 1);
                    } else {
                        // unclean split on non-whitespace
                        current_line_length = 1;
                        // store index for drawing
                        self.ws_indices.push(current_idx);
                    }
                    // invalidate whitespace since we split here
                    last_whitespace_idx = None;
                    // moved to next line
                    line_count += 1;
                    // set width to full width
                    line_width = width;
                }
                prev_char_is_whitespace = false;
            }
        }

        // Last line length is `line_width`, make room for cursor
        if current_line_length == line_width {
            line_count += 1;
        }

        line_count as usize
    }
}

fn draw_line_scroll(
    tb: &mut Termbox,
    colors: &Colors,
    line: &[char],
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    scroll: i32,
) {
    let slice: &[char] =
        &line[scroll as usize..min(line.len(), (scroll + (width - pos_x)) as usize)];
    termbox::print_chars(tb, pos_x, pos_y, colors.user_msg, slice.iter().copied());
    // On my terminal the cursor is only shown when there's a character
    // under it.
    if cursor as usize >= line.len() {
        tb.change_cell(
            pos_x + cursor - scroll,
            pos_y,
            ' ',
            colors.cursor.fg,
            colors.cursor.bg,
        );
    }

    tb.set_cursor(Some(((pos_x + cursor - scroll) as u16, pos_y as u16)));
}

pub(crate) struct CompletionRange {
    start_idx: usize,
    end_idx: usize,
}

fn draw_line_wrapped(
    tb: &mut Termbox,
    colors: &Colors,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    line: &InputLine,
    completion_range: &Option<CompletionRange>,
) {
    let mut col = pos_x;
    let mut line_num = 0;

    let mut cursor_xychar = (0, 0, ' ');
    let mut check_cursor = |char_idx: usize, cursor: i32, pos_x: i32, pos_y: i32, c: char| {
        if char_idx == cursor as usize {
            cursor_xychar = (pos_x, pos_y, c);
        }
    };
    let mut ws_indices_iter = line.ws_indices.iter().copied().peekable();
    for (char_idx, c) in line.buffer.iter().enumerate() {
        let mut style = colors.user_msg;
        // for autocompletion highlighting
        if let Some(completion_range) = completion_range {
            if char_idx >= completion_range.start_idx && char_idx < completion_range.end_idx {
                style = colors.completion;
            }
        }
        // If ws_indices_iter yields we already know the indices for the start of each line. If it
        // does not then we just continue outputting on this line.
        if let Some(next_line_start) = ws_indices_iter.peek() {
            if char_idx == *next_line_start as usize {
                // move to next line
                line_num += 1;
                // reset column
                col = 0;
                // move to the next line start index
                ws_indices_iter.next();
            }
        }
        // Write out the character
        tb.change_cell(col, pos_y + line_num, *c, style.fg, style.bg);
        // Check if the cursor is on this character
        check_cursor(char_idx, cursor, col, pos_y + line_num, *c);
        col += 1;
    }

    // Cursor may be (probably) after all text
    if col == width {
        // render cursor on next line
        line_num += 1;
        col = 0;
    }
    check_cursor(line.buffer.len(), cursor, col, pos_y + line_num, ' ');

    tb.change_cell(
        cursor_xychar.0,
        cursor_xychar.1,
        cursor_xychar.2,
        colors.cursor.fg,
        colors.cursor.bg,
    );

    tb.set_cursor(Some(((cursor_xychar.0) as u16, (cursor_xychar.1) as u16)));
}

pub(crate) fn draw_line_autocomplete(
    original_buffer: &InputLine,
    insertion_point: usize,
    word_starts: usize,
    completions: &[String],
    current_completion: usize,
    tb: &mut Termbox,
    colors: &Colors,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    should_scroll: bool,
    scroll: Option<i32>,
) {
    let completion: &str = &completions[current_completion];

    let mut orig_buf_iter = original_buffer.get_buffer().iter().copied();
    let mut completion_iter = completion.chars();

    if should_scroll {
        let cursor_x_off = cursor - scroll.unwrap();
        let cursor_y_off = 0;

        // draw a placeholder for the cursor
        tb.change_cell(
            pos_x + cursor_x_off,
            pos_y + cursor_y_off,
            ' ',
            colors.user_msg.fg,
            colors.user_msg.bg,
        );

        let iter: utils::InsertIterator<char> =
            utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

        for (char_idx, char) in iter.enumerate() {
            let x_off;
            let y_off;
            let mut can_scroll = true;
            if should_scroll {
                let scroll = scroll.unwrap_or(0);
                x_off = (char_idx as i32) - scroll;
                y_off = 0;
                if char_idx >= ((scroll + width) as usize) {
                    break;
                }
                if char_idx < scroll as usize {
                    can_scroll = false
                }
            } else {
                x_off = char_idx as i32 % width;
                y_off = char_idx as i32 / width;
            }
            if can_scroll {
                if char_idx >= word_starts && char_idx < insertion_point + completion.len() {
                    tb.change_cell(
                        pos_x + x_off,
                        pos_y + y_off,
                        char,
                        colors.completion.fg,
                        colors.completion.bg,
                    );
                } else {
                    tb.change_cell(
                        pos_x + x_off,
                        pos_y + y_off,
                        char,
                        colors.user_msg.fg,
                        colors.user_msg.bg,
                    );
                }
            }
        }
        tb.set_cursor(Some((
            (pos_x + cursor_x_off) as u16,
            (pos_y + cursor_y_off) as u16,
        )));
    } else {
        // TODO: Think of a better way to handle this inefficiency
        let iter: utils::InsertIterator<char> =
            utils::insert_iter(&mut orig_buf_iter, &mut completion_iter, insertion_point);

        let mut line = InputLine::from_buffer(iter.collect());
        line.calculate_height(width, pos_x as usize);
        let completion_range = CompletionRange {
            start_idx: word_starts,
            end_idx: (insertion_point + completion.len()),
        };
        draw_line_wrapped(
            tb,
            colors,
            pos_x,
            pos_y,
            width,
            cursor,
            &line,
            &Some(completion_range),
        );
    }
}

pub(crate) fn draw_line(
    tb: &mut Termbox,
    colors: &Colors,
    line: &InputLine,
    pos_x: i32,
    pos_y: i32,
    width: i32,
    cursor: i32,
    should_scroll: bool,
    scroll: Option<i32>,
    completion_range: Option<CompletionRange>,
) {
    if should_scroll || (line.len() as i32) < width - pos_x {
        draw_line_scroll(
            tb,
            colors,
            &line.buffer,
            pos_x,
            pos_y,
            width,
            cursor,
            scroll.unwrap_or(0),
        );
    } else {
        draw_line_wrapped(
            tb,
            colors,
            pos_x,
            pos_y,
            width,
            cursor,
            &line,
            &completion_range,
        );
    }
}

#[cfg(test)]
mod tests {
    use super::InputLine;
    #[test]
    fn test_calculate_height() {
        let buffer: Vec<char> = String::from("012345").chars().collect();
        let mut line = InputLine::from_buffer(buffer);

        assert_eq!(line.calculate_height(6, 2), 2);

        // one extra line for the cursor
        assert_eq!(line.calculate_height(6, 0), 2);
        assert_eq!(line.calculate_height(3, 0), 3);

        line.insert(3, ' '); // 123 456
        assert_eq!(line.calculate_height(6, 0), 2);

        // Input containing lines that are longer than the width
        let buffer: Vec<char> = String::from("01 3456").chars().collect();
        let mut line = InputLine::from_buffer(buffer);
        assert_eq!(line.calculate_height(3, 0), 3);
        line.insert(line.len(), ' ');
        // "01 3456 "
        // Each line should be:
        // "01 "
        // "345"
        // "6 "
        assert_eq!(line.calculate_height(3, 0), 3);

        line.insert(line.len(), '8');
        line.insert(line.len(), '9');
        line.insert(line.len(), 'X');
        line.insert(line.len(), '1');
        line.insert(line.len(), '2');
        line.insert(line.len(), ' ');
        line.insert(line.len(), '4');
        // "01 3456 89X12 "
        // Each line should be:
        // "01 "
        // "345"
        // "6 "
        // "89X"
        // "12 "
        // "4"
        assert_eq!(line.calculate_height(3, 0), 6);

        // First line has no whitespaces, but whitespaces follow
        let buffer: Vec<char> = String::from("012345 78 X 12 34").chars().collect();
        let mut line = InputLine::from_buffer(buffer);
        // "0123"
        // "45 "
        // "78 X"
        // " 12 "
        // "34"
        assert_eq!(line.calculate_height(4, 0), 5);
    }
}
<|endoftext|>


<commit_before>extern crate cursive;

use std::sync::mpsc;
use std::thread;

use cursive::Cursive;
use cursive::printer::Printer;
use cursive::view::{View,FullView};

fn main() {
    // As usual, create the Cursive root
    let mut siv = Cursive::new();

    // We want to refresh the page even when no input is given.
    siv.set_fps(10);
    siv.add_global_callback('q' as i32, |s,_| s.quit());

    // A channel will communicate data from our running task to the UI.
    let (tx,rx) = mpsc::channel();

    // Generate data in a separate thread.
    thread::spawn(|| { generate_logs(tx); });

    // And sets the view to read from the other end of the channel.
    // (We use FullView to force fullscreen because
    // we have no min_size for the BufferView).
    siv.add_layer(FullView::new(BufferView::new(200, rx)));

    siv.run();
}

// We will only simulate log generation here.
// In real life, this may come from a running task, a separate process, ...
fn generate_logs(tx: mpsc::Sender<String>) {
    let mut i = 1;
    loop {
        let line = format!("Interesting log line {}", i);
        i += 1;
        match tx.send(line) {
            Err(_) => panic!("Uh?..."),
            Ok(_) => (),
        }
        thread::sleep_ms(30);
    }
}

// Let's define a buffer view, that shows the last lines from a stream.
struct BufferView {
    // We will emulate a ring buffer
    buffer: Vec<String>,
    // Current position in the buffer
    pos: usize,
    // Receiving end of the stream
    rx: mpsc::Receiver<String>,
}

impl BufferView {
    // Creates a new view with the given buffer size
    fn new(size: usize, rx: mpsc::Receiver<String>) -> Self {
        BufferView {
            rx: rx,
            buffer: (0..size).map(|_| String::new()).collect(),
            pos: 0,
        }
    }

    // Reads available data from the stream into the buffer
    fn update(&mut self) {
        let mut i = self.pos;
        while let Ok(line) = self.rx.try_recv() {
            i = (i+1) % self.buffer.len();
            self.buffer[i] = line;
        }
        self.pos = i;
    }

    // Chain together the two parts of the buffer to appear as a circular one.
    // The signature is quite ugly, but basically we return an iterator:
    // a Chain of two slice iterators.
    fn ring<'a>(&'a self) -> std::iter::Chain<std::slice::Iter<'a,String>, std::slice::Iter<'a,String>> {
        // The main buffer is "circular" starting at self.pos
        // So we chain the two parts as one
        self.buffer[self.pos..].iter().chain(self.buffer[..self.pos].iter())
    }
}

impl View for BufferView {
    fn draw(&mut self, printer: &Printer, _: bool) {
        // Before drawing, we'll want to update the buffer
        self.update();

        // If the buffer is large enough, we can fill the window
        if self.buffer.len() > printer.size.y as usize {
            // We'll only print the last entries that fit.
            // So discard entries if there are too many.
            let discard = self.buffer.len() - printer.size.y as usize;
            // And we discard the first entries if needed
            for (i, line) in self.ring().skip(discard).enumerate() {
                printer.print((0,i as u32), line);
            }
        } else {

        }
    }
}
<commit_msg>Don't panic in log generator<commit_after>extern crate cursive;

use std::sync::mpsc;
use std::thread;

use cursive::Cursive;
use cursive::printer::Printer;
use cursive::view::{View,FullView};

fn main() {
    // As usual, create the Cursive root
    let mut siv = Cursive::new();

    // We want to refresh the page even when no input is given.
    siv.set_fps(10);
    siv.add_global_callback('q' as i32, |s,_| s.quit());

    // A channel will communicate data from our running task to the UI.
    let (tx,rx) = mpsc::channel();

    // Generate data in a separate thread.
    thread::spawn(|| { generate_logs(tx); });

    // And sets the view to read from the other end of the channel.
    // (We use FullView to force fullscreen because
    // we have no min_size for the BufferView).
    siv.add_layer(FullView::new(BufferView::new(200, rx)));

    siv.run();
}

// We will only simulate log generation here.
// In real life, this may come from a running task, a separate process, ...
fn generate_logs(tx: mpsc::Sender<String>) {
    let mut i = 1;
    loop {
        let line = format!("Interesting log line {}", i);
        i += 1;
        // The send will fail when the other side is dropped.
        // (When the application ends).
        match tx.send(line) {
            Err(_) => return,
            Ok(_) => (),
        }
        thread::sleep_ms(30);
    }
}

// Let's define a buffer view, that shows the last lines from a stream.
struct BufferView {
    // We will emulate a ring buffer
    buffer: Vec<String>,
    // Current position in the buffer
    pos: usize,
    // Receiving end of the stream
    rx: mpsc::Receiver<String>,
}

impl BufferView {
    // Creates a new view with the given buffer size
    fn new(size: usize, rx: mpsc::Receiver<String>) -> Self {
        BufferView {
            rx: rx,
            buffer: (0..size).map(|_| String::new()).collect(),
            pos: 0,
        }
    }

    // Reads available data from the stream into the buffer
    fn update(&mut self) {
        let mut i = self.pos;
        while let Ok(line) = self.rx.try_recv() {
            i = (i+1) % self.buffer.len();
            self.buffer[i] = line;
        }
        self.pos = i;
    }

    // Chain together the two parts of the buffer to appear as a circular one.
    // The signature is quite ugly, but basically we return an iterator:
    // a Chain of two slice iterators.
    fn ring<'a>(&'a self) -> std::iter::Chain<std::slice::Iter<'a,String>, std::slice::Iter<'a,String>> {
        // The main buffer is "circular" starting at self.pos
        // So we chain the two parts as one
        self.buffer[self.pos..].iter().chain(self.buffer[..self.pos].iter())
    }
}

impl View for BufferView {
    fn draw(&mut self, printer: &Printer, _: bool) {
        // Before drawing, we'll want to update the buffer
        self.update();

        // If the buffer is large enough, we can fill the window
        if self.buffer.len() > printer.size.y as usize {
            // We'll only print the last entries that fit.
            // So discard entries if there are too many.
            let discard = self.buffer.len() - printer.size.y as usize;
            // And we discard the first entries if needed
            for (i, line) in self.ring().skip(discard).enumerate() {
                printer.print((0,i as u32), line);
            }
        } else {

        }
    }
}
<|endoftext|>


<commit_before>/// An example demonstrating how to send and recieve a custom ping/pong frame.
/// This example also shows using a separate thread to represent another
/// component of your system as well as how to use a custom Factory.
extern crate ws;
extern crate env_logger;
extern crate time;

use std::thread;
use std::thread::sleep;
use std::time::Duration;
use std::str::from_utf8;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender as ThreadOut;

use ws::{Builder, CloseCode, OpCode, Sender, Frame, Factory, Handler, Message, Result};

fn main () {

    // Setup logging
    env_logger::init().unwrap();

    // Set timer channel
    let (tx, rx) = channel();

    // Create WebSocket
    let socket = ws::Builder::new().build(ServerFactory { timer: tx }).unwrap();

    // Get broadcaster for timer
    let all = socket.broadcaster();

    // Start timer thread
    let timer = thread::spawn(move || {
        loop {
            // Test latency every 5 seconds
            sleep(Duration::from_secs(5));

            // Check if timer needs to go down
            if let Ok(_) = rx.try_recv() {
                println!("Timer is going down.");
                break;
            }

            // Ping all connections with current time
            if let Err(err) = all.ping(time::precise_time_ns().to_string().into()) {
                println!("Unable to ping connections: {:?}", err);
                println!("Timer is going down.");
                break;
            }
        }
    });

    // Start WebSocket server
    socket.listen("127.0.0.1:3012").unwrap();

    // Once the server is done, wait for the timer to shutdown as well
    timer.join().unwrap();
}

struct ServerFactory {
    timer: ThreadOut<usize>,
}

impl Factory for ServerFactory {
    type Handler = Server;

    fn connection_made(&mut self, out: Sender) -> Self::Handler {
        Server { out: out }
    }

    fn on_shutdown(&mut self) {
        if let Err(err) = self.timer.send(0) {
            println!("Unable to shut down timer: {:?}", err)
        }
    }

}

// For accessing the default handler implementation
struct DefaultHandler;

impl Handler for DefaultHandler {}

// Server WebSocket handler
struct Server {
    out: Sender,
}

impl Handler for Server {

    fn on_message(&mut self, msg: Message) -> Result<()> {
        println!("Server got message '{}'. ", msg);
        self.out.send(msg)
    }

    fn on_close(&mut self, code: CloseCode, reason: &str) {
        println!("WebSocket closing for ({:?}) {}", code, reason);
        println!("Shutting down server after first connection closes.");
        self.out.shutdown().unwrap();
    }

    fn on_frame(&mut self, frame: Frame) -> Result<Option<Frame>> {
        if frame.opcode() == OpCode::Pong {
            if let Ok(pong) = try!(from_utf8(frame.payload())).parse::<u64>() {
                let now = time::precise_time_ns();
                println!("Latency is {:.3}ms.", (now - pong) as f64 / 1_000_000f64);
            } else {
                println!("Received bad pong.");
            }
        }

        // Run default frame validation
        DefaultHandler.on_frame(frame)
    }
}

<commit_msg>Squash pong warning.<commit_after>/// An example demonstrating how to send and recieve a custom ping/pong frame.
/// This example also shows using a separate thread to represent another
/// component of your system as well as how to use a custom Factory.
extern crate ws;
extern crate env_logger;
extern crate time;

use std::thread;
use std::thread::sleep;
use std::time::Duration;
use std::str::from_utf8;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender as ThreadOut;

use ws::{Builder, CloseCode, OpCode, Sender, Frame, Factory, Handler, Message, Result};

fn main () {

    // Setup logging
    env_logger::init().unwrap();

    // Set timer channel
    let (tx, rx) = channel();

    // Create WebSocket
    let socket = Builder::new().build(ServerFactory { timer: tx }).unwrap();

    // Get broadcaster for timer
    let all = socket.broadcaster();

    // Start timer thread
    let timer = thread::spawn(move || {
        loop {
            // Test latency every 5 seconds
            sleep(Duration::from_secs(5));

            // Check if timer needs to go down
            if let Ok(_) = rx.try_recv() {
                println!("Timer is going down.");
                break;
            }

            // Ping all connections with current time
            if let Err(err) = all.ping(time::precise_time_ns().to_string().into()) {
                println!("Unable to ping connections: {:?}", err);
                println!("Timer is going down.");
                break;
            }
        }
    });

    // Start WebSocket server
    socket.listen("127.0.0.1:3012").unwrap();

    // Once the server is done, wait for the timer to shutdown as well
    timer.join().unwrap();
}

struct ServerFactory {
    timer: ThreadOut<usize>,
}

impl Factory for ServerFactory {
    type Handler = Server;

    fn connection_made(&mut self, out: Sender) -> Self::Handler {
        Server { out: out }
    }

    fn on_shutdown(&mut self) {
        if let Err(err) = self.timer.send(0) {
            println!("Unable to shut down timer: {:?}", err)
        }
    }

}

// For accessing the default handler implementation
struct DefaultHandler;

impl Handler for DefaultHandler {}

// Server WebSocket handler
struct Server {
    out: Sender,
}

impl Handler for Server {

    fn on_message(&mut self, msg: Message) -> Result<()> {
        println!("Server got message '{}'. ", msg);
        self.out.send(msg)
    }

    fn on_close(&mut self, code: CloseCode, reason: &str) {
        println!("WebSocket closing for ({:?}) {}", code, reason);
        println!("Shutting down server after first connection closes.");
        self.out.shutdown().unwrap();
    }

    fn on_frame(&mut self, frame: Frame) -> Result<Option<Frame>> {
        if frame.opcode() == OpCode::Pong {
            if let Ok(pong) = try!(from_utf8(frame.payload())).parse::<u64>() {
                let now = time::precise_time_ns();
                println!("Latency is {:.3}ms.", (now - pong) as f64 / 1_000_000f64);
            } else {
                println!("Received bad pong.");
            }
        }

        // Run default frame validation
        DefaultHandler.on_frame(frame)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::net::SocketAddr;

use serde::de::DeserializeOwned;
use serde_json;

use super::http_method::Method;
use util::url;
use error::Result;

pub struct Request {
    method: Method,
    path: String,
    headers: HashMap<String, String>,
    params: HashMap<String, String>,
    querys: HashMap<String, String>,
    remote_addr: SocketAddr,
    pub data: Vec<u8>
}

impl Request {
    pub fn new(method: Method, path: String, headers: HashMap<String, String>, remote_addr: SocketAddr, data: Vec<u8>) -> Request {
        Request {
            method: method,
            path: path,
            headers: headers,
            params: HashMap::new(),
            querys: HashMap::new(),
            remote_addr: remote_addr,
            data: data
        }
    }

    pub fn method(&self) -> &Method {
        &self.method
    }

    pub fn path(&self) -> &str {
        &self.path
    }

    pub fn headers(&mut self) -> &mut HashMap<String, String> {
        &mut self.headers
    }

    pub fn get_header<'a, S>(&self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.headers.get(key.into()).map(|v| v.to_string())
    }

    pub fn remote_addr(&self) -> &SocketAddr {
        &self.remote_addr
    }

    pub fn data_length(&self) -> usize {
        self.data.len()
    }

    pub fn data(&mut self) -> &mut Vec<u8> {
        &mut self.data
    }

    pub fn params(&mut self) -> &mut HashMap<String, String> {
        &mut self.params
    }

    pub fn get_param<'a, S>(&self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.params.get(key.into()).map(|v| v.to_string())
    }

    fn decode_query(&mut self) {
        if self.querys.len() == 0 {
            let url: String = self.path.find('?').map_or("".to_owned(), |pos| self.path[pos + 1..].to_owned());
            if url.len() > 0 {
                self.querys = url::from_str::<HashMap<String, String>>(&url).unwrap();
            }
        }
    }

    pub fn querys(&mut self) -> &mut HashMap<String, String> {
        self.decode_query();

        &mut self.querys
    }

    pub fn get_query<'a, S>(&mut self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.decode_query();

        self.querys.get(key.into()).map(|v| v.to_string())
    }

    pub fn bind_json<D: DeserializeOwned>(&self) -> Result<D> {
        Ok(serde_json::from_slice(&self.data)?)
    }
}

trait VecFind {
    fn find(&self, key: &str) -> Option<&str>;
}

impl VecFind for Vec<(String, String)> {
    fn find(&self, key: &str) -> Option<&str> {
        self.iter().find(|&&(ref k, _)| k == key ).map(|&(_, ref v)| &**v)
    }
}
<commit_msg>update<commit_after>use std::collections::HashMap;
use std::net::SocketAddr;

use serde::de::DeserializeOwned;
use serde_json;

use super::http_method::Method;
use util::url;
use error::Result;

pub struct Request {
    method: Method,
    path: String,
    headers: HashMap<String, String>,
    params: HashMap<String, String>,
    querys: HashMap<String, String>,
    remote_addr: SocketAddr,
    pub data: Vec<u8>
}

impl Request {
    pub fn new(method: Method, path: String, headers: HashMap<String, String>, remote_addr: SocketAddr, data: Vec<u8>) -> Request {
        let mut request = Request {
            method: method,
            path: path,
            headers: headers,
            params: HashMap::new(),
            querys: HashMap::new(),
            remote_addr: remote_addr,
            data: data
        };

        request.decode_query();

        request
    }

    pub fn method(&self) -> &Method {
        &self.method
    }

    pub fn path(&self) -> &str {
        &self.path
    }

    pub fn headers(&mut self) -> &mut HashMap<String, String> {
        &mut self.headers
    }

    pub fn get_header<'a, S>(&self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.headers.get(key.into()).map(|v| v.to_string())
    }

    pub fn remote_addr(&self) -> &SocketAddr {
        &self.remote_addr
    }

    pub fn data_length(&self) -> usize {
        self.data.len()
    }

    pub fn data(&mut self) -> &mut Vec<u8> {
        &mut self.data
    }

    pub fn params(&mut self) -> &mut HashMap<String, String> {
        &mut self.params
    }

    pub fn get_param<'a, S>(&self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.params.get(key.into()).map(|v| v.to_string())
    }

    fn decode_query(&mut self) {
        if self.querys.len() == 0 {
            let url: String = self.path.find('?').map_or("".to_owned(), |pos| self.path[pos + 1..].to_owned());
            if url.len() > 0 {
                self.querys = url::from_str::<HashMap<String, String>>(&url).unwrap();
            }
        }
    }

    pub fn querys(&self) -> &HashMap<String, String> {
        &self.querys
    }

    pub fn get_query<'a, S>(&self, key: S) -> Option<String>
        where S: Into<&'a str>
    {
        self.querys.get(key.into()).map(|v| v.to_string())
    }

    pub fn bind_json<D: DeserializeOwned>(&self) -> Result<D> {
        Ok(serde_json::from_slice(&self.data)?)
    }
}

trait VecFind {
    fn find(&self, key: &str) -> Option<&str>;
}

impl VecFind for Vec<(String, String)> {
    fn find(&self, key: &str) -> Option<&str> {
        self.iter().find(|&&(ref k, _)| k == key ).map(|&(_, ref v)| &**v)
    }
}
<|endoftext|>


<commit_before>use std::fmt;

const PIF_ROM_SIZE: usize = 2048;

const RAM_SIZE: usize = 4 * 1024 * 1024;

pub struct Interconnect {
    pif_rom: Vec<u8>,

    ram: Vec<u16>
}

impl Interconnect {
    pub fn new(pif_rom: Vec<u8>) -> Interconnect {
        Interconnect {
            pif_rom: pif_rom,

            ram: vec![0; RAM_SIZE]
        }
    }

    pub fn read_word(&self, addr: u32) -> u32 {
        // TODO: Replace constants with useful names
        if addr >= 0x1fc0_0000 && addr < 0x1fc0_07c0 {
            let rel_addr = addr - 0x1fc0_0000;
            // TODO: Check endianness
            // TODO: Check out byteorder crate
            ((self.pif_rom[rel_addr as usize] as u32) << 24) |
            ((self.pif_rom[(rel_addr + 1) as usize] as u32) << 16) |
            ((self.pif_rom[(rel_addr + 2) as usize] as u32) << 8) |
            (self.pif_rom[(rel_addr + 3) as usize] as u32)
        } else {
            // TODO
            panic!("Unrecognized address: {:#x}", addr);
        }
    }
}

impl fmt::Debug for Interconnect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TODO: Impl Debug for Interconnect")
    }
}
<commit_msg>Cleanup some alignment for my OCD<commit_after>use std::fmt;

const PIF_ROM_SIZE: usize = 2048;

const RAM_SIZE: usize = 4 * 1024 * 1024;

pub struct Interconnect {
    pif_rom: Vec<u8>,

    ram: Vec<u16>
}

impl Interconnect {
    pub fn new(pif_rom: Vec<u8>) -> Interconnect {
        Interconnect {
            pif_rom: pif_rom,

            ram: vec![0; RAM_SIZE]
        }
    }

    pub fn read_word(&self, addr: u32) -> u32 {
        // TODO: Replace constants with useful names
        if addr >= 0x1fc0_0000 && addr < 0x1fc0_07c0 {
            let rel_addr = addr - 0x1fc0_0000;
            // TODO: Check endianness
            // TODO: Check out byteorder crate
            (self.pif_rom[(rel_addr + 0) as usize] as u32) << 24 |
            (self.pif_rom[(rel_addr + 1) as usize] as u32) << 16 |
            (self.pif_rom[(rel_addr + 2) as usize] as u32) <<  8 |
            (self.pif_rom[(rel_addr + 3) as usize] as u32)
        } else {
            // TODO
            panic!("Unrecognized address: {:#x}", addr);
        }
    }
}

impl fmt::Debug for Interconnect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TODO: Impl Debug for Interconnect")
    }
}
<|endoftext|>