<commit_before>use std::old_io::fs::PathExtensions;
use std::rc::Rc;
use std::old_io::File;
use handlebars::Handlebars;

mod markdown;

enum FileType {
    Dir(Handlebars, String),
    Markdown(Handlebars, String)
}

impl FileType {

    fn register(source_root: &Path) -> Result<Vec<FileType>, &'static str> {
        // Validate generic stuff
        let header_hbs_path = source_root.clone().join("partials/header.hbs");
        if !header_hbs_path.exists() {
            return Err("Missing partials/header.hbs");
        }

        let footer_hbs_path = source_root.clone().join("partials/footer.hbs");
        if !footer_hbs_path.exists() {
            return Err("Missing partials/footer.hbs");
        }

        // Validate Dir
        let dir_hbs_path = source_root.clone().join("layouts/dir.hbs");
        if !dir_hbs_path.exists() {
            return Err("Missing /layouts/dir.hbs");
        }

        // Validate Markdown
        let note_hbs_path = source_root.clone().join("layouts/note.hbs");
        if !note_hbs_path.exists() {
            return Err("Missing /layouts/note.hbs");
        }

        // Grab generic stuff
        let header_hbs_contents = File::open(&header_hbs_path).read_to_string().unwrap();
        let footer_hbs_contents = File::open(&footer_hbs_path).read_to_string().unwrap();

        let mut result: Vec<FileType> = Vec::new();

        // Create Dir
        let dir_template_name = "dir_template";
        let dir_hbs_contents = File::open(&dir_hbs_path).read_to_string().unwrap();
        let mut handlebars = Handlebars::new();
        handlebars.register_template_string(dir_template_name, format!("{}\n{}\n{}", header_hbs_contents, dir_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|dir|footer template");

        result.push(FileType::Dir(handlebars, String::from_str(dir_template_name)));

        // Create Markdown
        let note_template_name = "note_template";
        let note_hbs_contents = File::open(&note_hbs_path).read_to_string().unwrap();
        let mut handlebars = Handlebars::new();
        handlebars.register_template_string(note_template_name, format!("{}\n{}\n{}", header_hbs_contents, note_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|note|footer template");

        result.push(FileType::Markdown(handlebars, String::from_str(note_template_name)));

        Ok(result)
    }

    fn create_converter(&self, path: &Path) -> FileTypeConverter {
            FileType::Dir(hbs, template_name) => {

            },
            FileType::Markdown(hbs, template_name) => {
            }
    }

    fn is_valid_path(&self, path: &Path) -> bool {
        let name = path.as_str().expect("Could not parse file type");
        match *self {
            FileType::Dir(_, _) if path.is_dir() => true,
            FileType::Markdown(_, _) => path.is_file() && (
                name.ends_with(".md") ||
                name.ends_with(".markdown") ||
                name.ends_with(".mkd")),
            _ => false
        }
    }

    fn type_str(&self) -> &'static str {
        match *self {
            FileType::Dir(_, _) => "dir",
            FileType::Markdown(_, _) => "markdown"
        }
    }

    /*
    fn convert(&self, fc: &FileConverter, relative: &Path) {
    }

    fn converted_url(&self, fc: &FileConverter, relative: &Path) -> &str {
        "hello world"
    }
    */

}

trait FileTypeConverter {
    /// I expect source_root to be the notes directory, so relative works for both source_root and
    /// dest_root.
    fn convert(&self,
               source_root: &Path,
               dest_root: &Path,
               relative: &Path,
               base_url: &str);

    fn converted_url(&self, base_url: &str, relative: &Path) -> String;

    fn type_str(&self) -> &str;

    fn is_valid_path(path: &Path) -> bool;
}

#[derive(RustcEncodable)]
struct Link {
    name: String,
    url: String
}

pub fn create_parent_links(base_url: &str, path: &Path, is_dir: bool) -> Vec<Link> {
    if is_dir && path.filename().is_none() {
        Vec::new()
    } else {
        let mut result: Vec<Link> = vec![Link {
            name: String::from_str("root"),
            url: format!("{}", base_url)
        }];
        let mut temp = path.clone().dir_path();
        while temp.filename().is_some() {
            result.insert(1, Link {
                name: String::from_str(temp.filename_str().unwrap()),
                url: format!("{}{}", base_url, temp.as_str().unwrap())
            });
            temp.pop();
        }
        result
    }
}

/*
struct FileConverter<'a> {
    source_root: Path,
    dest_root: Path,
    base_url: String,
    file_types: Vec<FileType>
}

impl<'a> FileConverter<'a> {
    fn init(source_root: &Path, dest_root: &Path, base_url: &str) -> FileConverter<'a> {
        let dir_ft = FileType::Dir(String::from_str("first string"));
        let markdown_ft = FileType::Markdown(String::from_str("second string"));
        FileConverter {
            source_root: source_root.clone(),
            dest_root: dest_root.clone(),
            base_url: String::from_str(base_url),
            file_types: vec![dir_ft, markdown_ft]
        }
    }

    pub fn convert(&self, relative: &Path) {
        match self.file_type_by_path(relative) {
            Some(ft) => {
                // Valid file, can process
                println!("Can process file: {:?}", relative);
            },
            None => println!("Cannot process file, unknown type: {:?}", relative)
        }
    }

    fn converted_url(&self, relative: &Path) -> Option<&str> {
        self.file_type_by_path(relative).map(|ft| ft.converted_url(&self, relative))
    }

    fn file_type_by_path(&self, relative: &Path) -> Option<&FileType> {
        self.file_types.iter().find(|ft| ft.is_valid_path(relative))
    }
}

*/
<commit_msg>possibly broken<commit_after>use std::old_io::fs::PathExtensions;
use std::rc::Rc;
use std::old_io::File;
use handlebars::Handlebars;

mod markdown;

enum FileType {
    Dir(Rc<Handlebars>, String),
    Markdown(Rc<Handlebars>, String)
}

impl FileType {

    fn register(source_root: &Path) -> Result<Vec<FileType>, &'static str> {
        // Validate generic stuff
        let header_hbs_path = source_root.clone().join("partials/header.hbs");
        if !header_hbs_path.exists() {
            return Err("Missing partials/header.hbs");
        }

        let footer_hbs_path = source_root.clone().join("partials/footer.hbs");
        if !footer_hbs_path.exists() {
            return Err("Missing partials/footer.hbs");
        }

        // Validate Dir
        let dir_hbs_path = source_root.clone().join("layouts/dir.hbs");
        if !dir_hbs_path.exists() {
            return Err("Missing /layouts/dir.hbs");
        }

        // Validate Markdown
        let note_hbs_path = source_root.clone().join("layouts/note.hbs");
        if !note_hbs_path.exists() {
            return Err("Missing /layouts/note.hbs");
        }

        // Grab generic stuff
        let header_hbs_contents = File::open(&header_hbs_path).read_to_string().unwrap();
        let footer_hbs_contents = File::open(&footer_hbs_path).read_to_string().unwrap();

        let mut result: Vec<FileType> = Vec::new();

        // Create Dir
        let dir_template_name = "dir_template";
        let dir_hbs_contents = File::open(&dir_hbs_path).read_to_string().unwrap();
        let mut handlebars = Handlebars::new();
        handlebars.register_template_string(dir_template_name, format!("{}\n{}\n{}", header_hbs_contents, dir_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|dir|footer template");

        result.push(FileType::Dir(Rc::new(handlebars), String::from_str(dir_template_name)));

        // Create Markdown
        let note_template_name = "note_template";
        let note_hbs_contents = File::open(&note_hbs_path).read_to_string().unwrap();
        let mut handlebars = Handlebars::new();
        handlebars.register_template_string(note_template_name, format!("{}\n{}\n{}", header_hbs_contents, note_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|note|footer template");

        result.push(FileType::Markdown(Rc::new(handlebars), String::from_str(note_template_name)));

        Ok(result)
    }

    fn create_converter(&self, path: &Path) -> FileTypeConverter {
            FileType::Dir(hbs, template_name) => {

            },
            FileType::Markdown(hbs, template_name) => {
                markdown::MarkdownConverter {
                    path: path.clone(),
                    handlebars: hbs.clone(),
                    template_name: template_name.clone()
                }
            }
    }

    fn is_valid_path(&self, path: &Path) -> bool {
        let name = path.as_str().expect("Could not parse file type");
        match *self {
            FileType::Dir(_, _) if path.is_dir() => true,
            FileType::Markdown(_, _) => path.is_file() && (
                name.ends_with(".md") ||
                name.ends_with(".markdown") ||
                name.ends_with(".mkd")),
            _ => false
        }
    }

    fn type_str(&self) -> &'static str {
        match *self {
            FileType::Dir(_, _) => "dir",
            FileType::Markdown(_, _) => "markdown"
        }
    }

    /*
    fn convert(&self, fc: &FileConverter, relative: &Path) {
    }

    fn converted_url(&self, fc: &FileConverter, relative: &Path) -> &str {
        "hello world"
    }
    */

}

trait FileTypeConverter {
    /// I expect source_root to be the notes directory, so relative works for both source_root and
    /// dest_root.
    fn convert(&self,
               source_root: &Path,
               dest_root: &Path,
               relative: &Path,
               base_url: &str);

    fn converted_url(&self, base_url: &str, relative: &Path) -> String;

    fn type_str(&self) -> &str;

    fn is_valid_path(path: &Path) -> bool;
}

#[derive(RustcEncodable)]
struct Link {
    name: String,
    url: String
}

pub fn create_parent_links(base_url: &str, path: &Path, is_dir: bool) -> Vec<Link> {
    if is_dir && path.filename().is_none() {
        Vec::new()
    } else {
        let mut result: Vec<Link> = vec![Link {
            name: String::from_str("root"),
            url: format!("{}", base_url)
        }];
        let mut temp = path.clone().dir_path();
        while temp.filename().is_some() {
            result.insert(1, Link {
                name: String::from_str(temp.filename_str().unwrap()),
                url: format!("{}{}", base_url, temp.as_str().unwrap())
            });
            temp.pop();
        }
        result
    }
}

/*
struct FileConverter<'a> {
    source_root: Path,
    dest_root: Path,
    base_url: String,
    file_types: Vec<FileType>
}

impl<'a> FileConverter<'a> {
    fn init(source_root: &Path, dest_root: &Path, base_url: &str) -> FileConverter<'a> {
        let dir_ft = FileType::Dir(String::from_str("first string"));
        let markdown_ft = FileType::Markdown(String::from_str("second string"));
        FileConverter {
            source_root: source_root.clone(),
            dest_root: dest_root.clone(),
            base_url: String::from_str(base_url),
            file_types: vec![dir_ft, markdown_ft]
        }
    }

    pub fn convert(&self, relative: &Path) {
        match self.file_type_by_path(relative) {
            Some(ft) => {
                // Valid file, can process
                println!("Can process file: {:?}", relative);
            },
            None => println!("Cannot process file, unknown type: {:?}", relative)
        }
    }

    fn converted_url(&self, relative: &Path) -> Option<&str> {
        self.file_type_by_path(relative).map(|ft| ft.converted_url(&self, relative))
    }

    fn file_type_by_path(&self, relative: &Path) -> Option<&FileType> {
        self.file_types.iter().find(|ft| ft.is_valid_path(relative))
    }
}

*/
<|endoftext|>


<commit_before>//! Defines the render target for tray, where our image will be written too
//! during rendering
//! TODO: Reconstruction filters

use std::vec::Vec;
use std::iter;
use linalg;
use film::Colorf;

/// RenderTarget is a RGBF render target to write our image too while rendering
#[derive(Clone)]
pub struct RenderTarget {
    width: usize,
    height: usize,
    pixels: Vec<Colorf>,
}

impl RenderTarget {
    /// Create a render target with `width * height` pixels
    pub fn new(width: usize, height: usize) -> RenderTarget {
        RenderTarget { width: width, height: height,
            pixels: iter::repeat(Colorf::broadcast(0f32)).take(width * height).collect(),
        }
    }
    /// Write a color value to the image at `(x, y)`
    pub fn write(&mut self, x: f32, y: f32, c: &Colorf) {
        // Compute the discrete pixel coordinates which the sample hits, no filtering for now
        let ix = linalg::clamp(x - 0.5, 0f32, (self.width - 1) as f32) as usize;
        let iy = linalg::clamp(y - 0.5, 0f32, (self.height - 1) as f32) as usize;
        self.pixels[iy * self.width + ix] = *c;
        // Set the filter weight, currently just a box filter with single pixel extent
        self.pixels[iy * self.width + ix].a += 1.0;
    }
    /// Get the dimensions of the render target
    pub fn dimensions(&self) -> (usize, usize) {
        (self.width, self.height)
    }
    /// Convert the floating point color buffer to 24bpp sRGB for output to an image
    pub fn get_render(&self) -> Vec<u8> {
        let mut render: Vec<u8> = iter::repeat(0u8).take(self.width * self.height * 3).collect();
        for y in 0..self.height {
            for x in 0..self.width {
                let c = &self.pixels[y * self.width + x];
                if c.a != 0.0 {
                    let cn = (*c / c.a).clamp().to_srgb();
                    for i in 0..3us {
                        render[y * self.width * 3 + x * 3 + i] = (cn[i] * 255.0) as u8;
                    }
                }
            }
        }
        render
    }
}

<commit_msg>Have render target behave as if we're using a single pixel box filter<commit_after>//! Defines the render target for tray, where our image will be written too
//! during rendering
//! TODO: Reconstruction filters

use std::vec::Vec;
use std::iter;
use std::cmp;
use std::num::Float;

use linalg;
use film::Colorf;

/// RenderTarget is a RGBF render target to write our image too while rendering
#[derive(Clone)]
pub struct RenderTarget {
    width: usize,
    height: usize,
    pixels: Vec<Colorf>,
}

impl RenderTarget {
    /// Create a render target with `width * height` pixels
    pub fn new(width: usize, height: usize) -> RenderTarget {
        RenderTarget { width: width, height: height,
            pixels: iter::repeat(Colorf::broadcast(0.0)).take(width * height).collect(),
        }
    }
    /// Write a color value to the image at `(x, y)`
    pub fn write(&mut self, x: f32, y: f32, c: &Colorf) {
        // Compute the discrete pixel coordinates which the sample hits, no filtering for now
        let img_x = x - 0.5;
        let img_y = y - 0.5;
        // TODO: We're just pretending to be a single pixel box filter for now
        let x_range = (Float::max(Float::ceil(img_x - 0.5), 0.0) as usize,
                       Float::min(Float::floor(img_x + 0.5), self.width as f32 - 1.0) as usize);
        let y_range = (Float::max(Float::ceil(img_y - 0.5), 0.0) as usize,
                       Float::min(Float::floor(img_y + 0.5), self.height as f32 - 1.0) as usize);
        let ix = x_range.0;
        let iy = y_range.0;
        self.pixels[iy * self.width + ix] = *c;
        // Set the filter weight, currently just a box filter with single pixel extent
        self.pixels[iy * self.width + ix].a += 1.0;
    }
    /// Get the dimensions of the render target
    pub fn dimensions(&self) -> (usize, usize) {
        (self.width, self.height)
    }
    /// Convert the floating point color buffer to 24bpp sRGB for output to an image
    pub fn get_render(&self) -> Vec<u8> {
        let mut render: Vec<u8> = iter::repeat(0u8).take(self.width * self.height * 3).collect();
        for y in 0..self.height {
            for x in 0..self.width {
                let c = &self.pixels[y * self.width + x];
                if c.a != 0.0 {
                    let cn = (*c / c.a).clamp().to_srgb();
                    for i in 0..3us {
                        render[y * self.width * 3 + x * 3 + i] = (cn[i] * 255.0) as u8;
                    }
                }
            }
        }
        render
    }
}

<|endoftext|>


<commit_before><commit_msg>Add tests<commit_after><|endoftext|>


<commit_before>use blip_buf::BlipBuf;
use cpal;
use std;

macro_rules! try_opt {
     ( $expr:expr ) => {
         match $expr {
             Some(v) => v,
             None => return None,
         }
     }
}

pub struct Sound {
    waveram: [u8; 16],
    channel3_on: bool,
    channel3_len: u8,
    channel3_vol: u8,
    channel3_freq: u32,
    channel3_freq_div: u32,
    channel3_uselen: bool,
    channel3_started: bool,
    channel3_wave_idx: usize,
    voice: Option<cpal::Voice>,
    blip: Option<BlipBuf>,
    bliptime: u32,
    blipval: i32,
}

impl Sound {
    pub fn new() -> Sound {
        let voice = get_channel();
        if voice.is_none() {
            println!("Could not open audio device");
        }

        let blipbuf = voice.as_ref()
            .map(|v| {
                let mut bb = BlipBuf::new(v.format().samples_rate.0 / 10);
                bb.set_rates(0x400000 as f64, v.format().samples_rate.0 as f64);
                bb
            });

        Sound {
            waveram: [0; 16],
            channel3_on: false,
            channel3_len: 0,
            channel3_vol: 0,
            channel3_freq: 0,
            channel3_uselen: false,
            channel3_started: false,
            channel3_freq_div: 0,
            channel3_wave_idx: 0,
            voice: voice,
            blip: blipbuf,
            bliptime: 0,
            blipval: 0,
        }
    }

   pub fn rb(&self, a: u16) -> u8 {
        match a {
            0xFF1A => if self.channel3_on { 0x80 } else { 0 },
            0xFF1B => self.channel3_len,
            0xFF1C => self.channel3_vol << 5,
            0xFF1D => 0,
            0xFF1E => 0,
            0xFF30 ... 0xFF3F => self.waveram[a as usize - 0xFF30],
            _ => 0,
        }
    }

    pub fn wb(&mut self, a: u16, v: u8) {
        match a {
            0xFF1A => self.channel3_on = v & 0x80 == 0x80,
            0xFF1B => self.channel3_len = v,
            0xFF1C => self.channel3_vol = (v >> 5) & 0x3,
            0xFF1D => self.channel3_freq = self.channel3_freq & 0xFF00 | v as u32,
            0xFF1E => {
                self.channel3_freq = self.channel3_freq & 0x00FF | (((v & 0x7) as u32) << 8);
                self.channel3_started = v & 0x80 == 0x80;
                self.channel3_uselen = v & 0x40 == 0x40;
                self.channel3_wave_idx = 0;
            }
            0xFF30 ... 0xFF3F => self.waveram[a as usize - 0xFF30] = v,
            _ => (),
        }
    }

    fn blip(&mut self) -> &mut BlipBuf {
        self.blip.as_mut().unwrap()
    }

    fn channel(&mut self) -> &mut cpal::Voice {
        self.voice.as_mut().unwrap()
    }

    pub fn do_cycle(&mut self, cycles: u32)
    {
        self.bliptime += cycles;
        if self.channel3_started && self.channel3_on {
            let rfreq = 64 * (2048 - (self.channel3_freq as u32));
            self.channel3_freq_div += cycles;
            while self.channel3_freq_div > rfreq {
                self.channel3_freq_div -= rfreq;
                self.channel3_wave_idx = (self.channel3_wave_idx + 1) % 32;
                if self.channel3_uselen {
                    self.channel3_len = self.channel3_len.wrapping_sub(1);
                    if self.channel3_len == 0 {
                        self.channel3_started = false;
                    }
                }
                let sample = ((self.waveram[self.channel3_wave_idx / 2]
                    >> (if self.channel3_wave_idx % 1 == 0 { 4 } else { 0 }))
                    & 0x0F) as i32;
                let newblip = sample * 1000 - self.blipval;
                let time = self.bliptime;
                if self.blip.is_some() {
                    self.blip().add_delta(time, newblip);
                    self.blipval = sample;
                }
            }
        }
        else if self.blipval != 0 && self.blip.is_some() {
            let time = self.bliptime;
            let newblip = -self.blipval;
            self.blip().add_delta(time, newblip);
            self.blipval = 0;
        }
        if self.bliptime > (1 << 16) && self.blip.is_some() {
            self.blip().end_frame(1 << 16);
            self.bliptime -= 1 << 16;
            self.play_blipbuf();
        }
    }

    fn play_blipbuf(&mut self) {
        let channels_len = self.channel().format().channels.len();

        while self.blip().samples_avail() > 0 {
            let buf = &mut [0; 1024];
            let count = self.blip().read_samples(buf, false);
            let blipbuf = &buf[0..count];
            let mut done = 0;
            let mut lastdone = count;

            while lastdone != done && done < count {
                lastdone = done;
                let channelbuf = &blipbuf[done..];
                match self.channel().append_data(channelbuf.len()) {
                    cpal::UnknownTypeBuffer::U16(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            let value = *value as u16 + std::i16::MAX as u16;
                            for out in sample.iter_mut() { *out = value; }
                            done += 1;
                        }
                    }
                    cpal::UnknownTypeBuffer::I16(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            for out in sample.iter_mut() { *out = *value; }
                            done += 1;
                        }
                    }
                    cpal::UnknownTypeBuffer::F32(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            let value = *value as f32 / std::i16::MAX as f32;
                            for out in sample.iter_mut() { *out = value; }
                            done += 1;
                        }
                    }
                }
                self.channel().play();
            }
        }
    }
}

fn get_channel() -> Option<cpal::Voice> {
    if cpal::get_endpoints_list().count() == 0 { return None; }

    let endpoint = try_opt!(cpal::get_default_endpoint());
    let format = try_opt!(endpoint.get_supported_formats_list().ok().and_then(|mut v| v.next()));
    let channel = try_opt!(cpal::Voice::new(&endpoint, &format).ok());
    Some(channel)
}
<commit_msg>The sounds are somewhat recognizable :)<commit_after>use blip_buf::BlipBuf;
use cpal;
use std;

macro_rules! try_opt {
     ( $expr:expr ) => {
         match $expr {
             Some(v) => v,
             None => return None,
         }
     }
}

pub struct Sound {
    waveram: [u8; 16],
    channel3_on: bool,
    channel3_len: u8,
    channel3_vol: u8,
    channel3_freq: u32,
    channel3_freq_div: u32,
    channel3_uselen: bool,
    channel3_started: bool,
    channel3_wave_idx: usize,
    voice: Option<cpal::Voice>,
    blip: Option<BlipBuf>,
    bliptime: u32,
    blipval: i32,
    hz256: u32,
}

impl Sound {
    pub fn new() -> Sound {
        let voice = get_channel();
        if voice.is_none() {
            println!("Could not open audio device");
        }

        let blipbuf = voice.as_ref()
            .map(|v| {
                let mut bb = BlipBuf::new(v.format().samples_rate.0 / 10);
                bb.set_rates((1 << 22) as f64, v.format().samples_rate.0 as f64);
                bb
            });

        Sound {
            waveram: [0; 16],
            channel3_on: false,
            channel3_len: 0,
            channel3_vol: 0,
            channel3_freq: 0,
            channel3_uselen: false,
            channel3_started: false,
            channel3_freq_div: 0,
            channel3_wave_idx: 0,
            voice: voice,
            blip: blipbuf,
            bliptime: 0,
            blipval: 0,
            hz256: 0,
        }
    }

   pub fn rb(&self, a: u16) -> u8 {
        match a {
            0xFF1A => if self.channel3_on { 0x80 } else { 0 },
            0xFF1B => self.channel3_len,
            0xFF1C => self.channel3_vol << 5,
            0xFF1D => 0,
            0xFF1E => 0,
            0xFF30 ... 0xFF3F => self.waveram[a as usize - 0xFF30],
            _ => 0,
        }
    }

    pub fn wb(&mut self, a: u16, v: u8) {
        match a {
            0xFF1A => if v & 0x80 == 0x80 { self.channel3_on = true; } else { self.channel3_started = false; },
            0xFF1B => self.channel3_len = v,
            0xFF1C => self.channel3_vol = (v & 0x60) >> 5,
            0xFF1D => self.channel3_freq = self.channel3_freq & 0xFF00 | v as u32,
            0xFF1E => {
                self.channel3_freq = self.channel3_freq & 0x00FF | (((v & 0x7) as u32) << 8);
                self.channel3_started = v & 0x80 == 0x80;
                self.channel3_uselen = v & 0x40 == 0x40;
                self.channel3_wave_idx = 31;
                self.channel3_freq_div = 0;
                self.hz256 = 0;
            }
            0xFF30 ... 0xFF3F => self.waveram[a as usize - 0xFF30] = v,
            _ => (),
        }
    }

    #[inline]
    fn blip(&mut self) -> &mut BlipBuf {
        self.blip.as_mut().unwrap()
    }

    #[inline]
    fn channel(&mut self) -> &mut cpal::Voice {
        self.voice.as_mut().unwrap()
    }

    pub fn do_cycle(&mut self, cycles: u32)
    {
        self.bliptime += cycles;
        self.hz256 += cycles;
        let trigger256 = if self.hz256 >= (1 << 22) / 256 {
            self.hz256 -= (1 << 22) / 256;
            true
        }
        else {
            false
        };
        if self.channel3_started && self.channel3_on {
            //let rfreq = ((2048 - (self.channel3_freq as u32)) << 5);
            let rfreq = 64 * (2048 - (self.channel3_freq as u32));
            self.channel3_freq_div += cycles;
            if self.channel3_uselen && trigger256 {
                self.channel3_len = self.channel3_len.wrapping_sub(1);
                if self.channel3_len == 0 {
                    self.channel3_started = false;
                }
            }
            if self.channel3_freq_div > rfreq {
                self.channel3_freq_div -= rfreq;
                self.channel3_wave_idx = (self.channel3_wave_idx + 1) % 32;
                let sample = {
                    let ramitem = self.waveram[self.channel3_wave_idx / 2];
                    let shifted = if self.channel3_wave_idx % 2 == 0 {
                        ramitem >> 4
                    }
                    else {
                        ramitem & 0x0F
                    };
                    shifted as i8
                };
                let volmul = match self.channel3_vol {
                    1 => 1.0,
                    2 => 0.5,
                    3 => 0.25,
                    _ => 0.0,
                };
                let newblip = ((sample as f64 / 7.5 - 1.0) * volmul * 5000.0) as i32 - self.blipval;
                let time = self.bliptime;
                if self.blip.is_some() {
                    self.blip().add_delta(time, newblip);
                    self.blipval += newblip;
                }
            }
        }
        else if self.blipval != 0 && self.blip.is_some() {
            let time = self.bliptime;
            let newblip = -self.blipval;
            self.blip().add_delta(time, newblip);
            self.blipval = 0;
        }
        if self.bliptime >= (1 << 18) && self.blip.is_some() {
            self.blip().end_frame(1 << 18);
            self.bliptime -= 1 << 18;
            self.play_blipbuf();
        }
    }

    fn play_blipbuf(&mut self) {
        let channels_len = self.channel().format().channels.len();

        while self.blip().samples_avail() > 0 {
            let buf = &mut [0; 1 << 13];
            let count = self.blip().read_samples(buf, false);
            let blipbuf = &buf[..count];
            let mut done = 0;
            let mut lastdone = count;

            while lastdone != done && done < count {
                lastdone = done;
                let channelbuf = &blipbuf[done..];
                match self.channel().append_data(channelbuf.len()) {
                    cpal::UnknownTypeBuffer::U16(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            let value = *value as u16 + std::i16::MAX as u16;
                            for out in sample.iter_mut() { *out = value; }
                            done += 1;
                        }
                    }
                    cpal::UnknownTypeBuffer::I16(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            for out in sample.iter_mut() { *out = *value; }
                            done += 1;
                        }
                    }
                    cpal::UnknownTypeBuffer::F32(mut buffer) => {
                        for (sample, value) in buffer.chunks_mut(channels_len).zip(channelbuf) {
                            let value = *value as f32 / std::i16::MAX as f32;
                            for out in sample.iter_mut() { *out = value; }
                            done += 1;
                        }
                    }
                }
                self.channel().play();
            }
        }
    }
}

fn get_channel() -> Option<cpal::Voice> {
    if cpal::get_endpoints_list().count() == 0 { return None; }

    let endpoint = try_opt!(cpal::get_default_endpoint());
    let format = try_opt!(endpoint.get_supported_formats_list().ok().and_then(|mut v| v.next()));
    let channel = try_opt!(cpal::Voice::new(&endpoint, &format).ok());
    Some(channel)
}
<|endoftext|>


<commit_before>use eventual::Async;
use protobuf::{self, Message, RepeatedField};
use std::sync::{mpsc, Mutex, Arc};
use std::collections::HashMap;

use mercury::{MercuryRequest, MercuryMethod};
use messaging::{SpircMessage, MercuryResponseSender, UpdateMessageSender};
use player::{Player, PlayerState};
use mixer::Mixer;
use session::Session;
use util;
use util::SpotifyId;
use version;

use protocol;
pub use protocol::spirc::{PlayStatus, MessageType};

#[derive(Clone)]
pub struct SpircManager(Arc<Mutex<SpircInternal>>);

struct SpircInternal {
    player: Player,
    session: Session,
    mixer: Box<Mixer + Send>,

    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32,

    devices: HashMap<String, String>,
}

#[derive(Clone)]
pub struct State {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub update_time: i64,
    pub volume: u16,
    pub track: Option<SpotifyId>,
    pub end_of_track: bool,
}

impl State {
    pub fn new() -> State {
        let state = State {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: 0,
            volume: 0,
            track: None,
            end_of_track: false,
        };
        state.update_time()
    }

    pub fn update_from_player(mut self, player: &Player) -> State {
        let player_state = player.state();
        let (position_ms, position_measured_at) = player_state.position();
        self.status = player_state.status();
        self.position_ms = position_ms;
        self.position_measured_at = position_measured_at;
        self.track = player_state.track;
        self.end_of_track = player_state.end_of_track();
        self.update_time()
    }

    pub fn update_from_mixer(mut self, mixer: &Box<Mixer + Send>) -> State {
        self.volume = mixer.volume();
        self.update_time()
    }

    fn update_time(mut self) -> State {
        self.update_time = util::now_ms();
        self
    }
}

impl SpircManager {
    pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>) -> SpircManager {
        let ident = session.device_id().to_owned();
        let name = session.config().device_name.clone();

        SpircManager(Arc::new(Mutex::new(SpircInternal {
            player: player,
            session: session,
            mixer: mixer,

            seq_nr: 0,

            name: name,
            ident: ident,
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0,

            devices: HashMap::new(),
        })))
    }

    pub fn run(&self) {
        let rx = {
            let mut internal = self.0.lock().unwrap();
            let (tx, rx) = mpsc::channel::<SpircMessage>();

            let mercury_response_sender = MercuryResponseSender::create(tx.clone());

            internal.session.mercury_sub(internal.uri(), mercury_response_sender);

            let update_message_sender = UpdateMessageSender::create(tx.clone());

            internal.mixer.init(update_message_sender);

            internal.notify(true, None);

            // Use a weak pointer to avoid creating an Rc cycle between the player and the
            // SpircManager
            let _self = Arc::downgrade(&self.0);
            internal.player.add_observer(Box::new(move |state| {
                if let Some(_self) = _self.upgrade() {
                    let mut internal = _self.lock().unwrap();
                    internal.on_update(state);
                }
            }));

            rx
        };

        for msg in rx {
            match msg {
                SpircMessage::MercuryMsg(pkt) => {
                    let data = pkt.payload.first().unwrap();
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(data).unwrap();

                    debug!("{:?} {:?} {} {} {}",
                            frame.get_typ(),
                            frame.get_device_state().get_name(),
                            frame.get_ident(),
                            frame.get_seq_nr(),
                            frame.get_state_update_id());

                    self.0.lock().unwrap().handle(frame);
                }
                SpircMessage::UpdateMsg(_) => {
                    self.0.lock().unwrap().notify(false, None);
                }
            }
        }
    }

    pub fn devices(&self) -> HashMap<String, String> {
        self.0.lock().unwrap().devices.clone()
    }

    pub fn send_play(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePlay)
            .recipient(recipient)
            .send();
    }

    pub fn send_pause(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePause)
            .recipient(recipient)
            .send();
    }

    pub fn send_prev(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePrev)
            .recipient(recipient)
            .send();
    }

    pub fn send_next(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeNext)
            .recipient(recipient)
            .send();
    }

    pub fn send_replace_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                              recipient: &str,
                                                              track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeReplace)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_load_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                           recipient: &str,
                                                           track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeLoad)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_goodbye(&self) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeGoodbye)
            .send();
    }

    pub fn get_queue(&self) -> Vec<SpotifyId> {
        self.0.lock().unwrap().tracks.clone()
    }
}

impl SpircInternal {
    fn on_update(&mut self, player_state: &PlayerState) {
        let end_of_track = player_state.end_of_track();
        if end_of_track {
            self.index = (self.index + 1) % self.tracks.len() as u32;
            let track = self.tracks[self.index as usize];
            self.player.load(track, true, 0);
        } else {
            self.notify(false, None);
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_ident() == self.ident ||
           (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) {
            return;
        }

        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }

        if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() {
            self.devices.insert(frame.get_ident().into(),
                                frame.get_device_state().get_name().into());
        }

        match frame.get_typ() {
            MessageType::kMessageTypeHello => {
                self.notify(false, Some(frame.get_ident()));
            }
            MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.reload_tracks(&frame);
                if self.tracks.len() > 0 {
                    let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                    let track = self.tracks[self.index as usize];
                    let position = frame.get_state().get_position_ms();
                    self.player.load(track, play, position);
                } else {
                    self.notify(false, Some(frame.get_ident()));
                }
            }
            MessageType::kMessageTypePlay => {
                self.player.play();
            }
            MessageType::kMessageTypePause => {
                self.player.pause();
            }
            MessageType::kMessageTypeNext => {
                self.index = (self.index + 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypePrev => {
                self.index = (self.index - 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypeSeek => {
                self.player.seek(frame.get_position());
            }
            MessageType::kMessageTypeReplace => {
                self.reload_tracks(&frame);
            }
            MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.player.stop();
                }
            }
            MessageType::kMessageTypeVolume => {
                self.mixer.set_volume(frame.get_volume() as u16);
            }
            MessageType::kMessageTypeGoodbye => {
                if frame.has_ident() {
                    self.devices.remove(frame.get_ident());
                }
            }
            _ => (),
        }
    }

    fn reload_tracks(&mut self, ref frame: &protocol::spirc::Frame) {
        self.index = frame.get_state().get_playing_track_index();
        self.tracks = frame.get_state()
                           .get_track()
                           .iter()
                           .filter(|track| track.has_gid())
                           .map(|track| SpotifyId::from_raw(track.get_gid()))
                           .collect();
    }

    fn notify(&mut self, hello: bool, recipient: Option<&str>) {
        let mut cs = CommandSender::new(self,
                                        if hello {
                                            MessageType::kMessageTypeHello
                                        } else {
                                            MessageType::kMessageTypeNotify
                                        });
        if let Some(s) = recipient {
            cs = cs.recipient(&s);
        }
        cs.send();
    }

    fn spirc_state(&self, state: &State) -> protocol::spirc::State {
        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status,
            position_ms: state.position_ms,
            position_measured_at: state.position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self, state: &State) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version::version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: state.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [64]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album",
                        "playlist",
                        "search",
                        "inbox",
                        "toplist",
                        "starred",
                        "publishedstarred",
                        "track",
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local",
                        "audio/track",
                        "local",
                        "track",
                    ]
                }
            ],
        })
    }

    fn uri(&self) -> String {
        format!("hm://remote/user/{}", self.session.username())
    }
}

struct CommandSender<'a> {
    spirc_internal: &'a mut SpircInternal,
    cmd: MessageType,
    recipient: Option<&'a str>,
    state: Option<protocol::spirc::State>,
}

impl<'a> CommandSender<'a> {
    fn new(spirc_internal: &'a mut SpircInternal, cmd: MessageType) -> CommandSender {
        CommandSender {
            spirc_internal: spirc_internal,
            cmd: cmd,
            recipient: None,
            state: None,
        }
    }

    fn recipient(mut self, r: &'a str) -> CommandSender {
        self.recipient = Some(r);
        self
    }

    fn state(mut self, s: protocol::spirc::State) -> CommandSender<'a> {
        self.state = Some(s);
        self
    }

    fn send(self) {
        let state = State::new()
                         .update_from_player(&self.spirc_internal.player)
                         .update_from_mixer(&self.spirc_internal.mixer);

        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.spirc_internal.ident.clone(),
            protocol_version: "2.0.0",
            seq_nr: { self.spirc_internal.seq_nr += 1; self.spirc_internal.seq_nr  },
            typ: self.cmd,
            recipient: RepeatedField::from_vec(
                self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
                ),
            device_state: self.spirc_internal.device_state(&state),
            state_update_id: state.update_time
        });

        if self.spirc_internal.is_active {
            pkt.set_state(self.spirc_internal.spirc_state(&state));
        }

        self.spirc_internal
            .session
            .mercury(MercuryRequest {
                method: MercuryMethod::SEND,
                uri: self.spirc_internal.uri(),
                content_type: None,
                payload: vec![pkt.write_to_bytes().unwrap()],
            })
            .fire();
    }
}

fn track_ids_to_state<I: Iterator<Item = SpotifyId>>(track_ids: I) -> protocol::spirc::State {
    let tracks: Vec<protocol::spirc::TrackRef> =
        track_ids.map(|i| {
                     protobuf_init!(protocol::spirc::TrackRef::new(), { gid: i.to_raw().to_vec()})
                 })
                 .collect();
    protobuf_init!(protocol::spirc::State::new(), {
                    track: RepeatedField::from_vec(tracks)
                })
}
<commit_msg>Call start and stop on mixer<commit_after>use eventual::Async;
use protobuf::{self, Message, RepeatedField};
use std::sync::{mpsc, Mutex, Arc};
use std::collections::HashMap;

use mercury::{MercuryRequest, MercuryMethod};
use messaging::{SpircMessage, MercuryResponseSender, UpdateMessageSender};
use player::{Player, PlayerState};
use mixer::Mixer;
use session::Session;
use util;
use util::SpotifyId;
use version;

use protocol;
pub use protocol::spirc::{PlayStatus, MessageType};

#[derive(Clone)]
pub struct SpircManager(Arc<Mutex<SpircInternal>>);

struct SpircInternal {
    player: Player,
    session: Session,
    mixer: Box<Mixer + Send>,

    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32,

    devices: HashMap<String, String>,
}

#[derive(Clone)]
pub struct State {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub update_time: i64,
    pub volume: u16,
    pub track: Option<SpotifyId>,
    pub end_of_track: bool,
}

impl State {
    pub fn new() -> State {
        let state = State {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: 0,
            volume: 0,
            track: None,
            end_of_track: false,
        };
        state.update_time()
    }

    pub fn update_from_player(mut self, player: &Player) -> State {
        let player_state = player.state();
        let (position_ms, position_measured_at) = player_state.position();
        self.status = player_state.status();
        self.position_ms = position_ms;
        self.position_measured_at = position_measured_at;
        self.track = player_state.track;
        self.end_of_track = player_state.end_of_track();
        self.update_time()
    }

    pub fn update_from_mixer(mut self, mixer: &Box<Mixer + Send>) -> State {
        self.volume = mixer.volume();
        self.update_time()
    }

    fn update_time(mut self) -> State {
        self.update_time = util::now_ms();
        self
    }
}

impl SpircManager {
    pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>) -> SpircManager {
        let ident = session.device_id().to_owned();
        let name = session.config().device_name.clone();

        SpircManager(Arc::new(Mutex::new(SpircInternal {
            player: player,
            session: session,
            mixer: mixer,

            seq_nr: 0,

            name: name,
            ident: ident,
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0,

            devices: HashMap::new(),
        })))
    }

    pub fn run(&self) {
        let rx = {
            let mut internal = self.0.lock().unwrap();
            let (tx, rx) = mpsc::channel::<SpircMessage>();

            let mercury_response_sender = MercuryResponseSender::create(tx.clone());

            internal.session.mercury_sub(internal.uri(), mercury_response_sender);

            let update_message_sender = UpdateMessageSender::create(tx.clone());

            internal.mixer.init(update_message_sender);

            internal.notify(true, None);

            // Use a weak pointer to avoid creating an Rc cycle between the player and the
            // SpircManager
            let _self = Arc::downgrade(&self.0);
            internal.player.add_observer(Box::new(move |state| {
                if let Some(_self) = _self.upgrade() {
                    let mut internal = _self.lock().unwrap();
                    internal.on_update(state);
                }
            }));

            rx
        };

        for msg in rx {
            match msg {
                SpircMessage::MercuryMsg(pkt) => {
                    let data = pkt.payload.first().unwrap();
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(data).unwrap();

                    debug!("{:?} {:?} {} {} {}",
                            frame.get_typ(),
                            frame.get_device_state().get_name(),
                            frame.get_ident(),
                            frame.get_seq_nr(),
                            frame.get_state_update_id());

                    self.0.lock().unwrap().handle(frame);
                }
                SpircMessage::UpdateMsg(_) => {
                    self.0.lock().unwrap().notify(false, None);
                }
            }
        }
    }

    pub fn devices(&self) -> HashMap<String, String> {
        self.0.lock().unwrap().devices.clone()
    }

    pub fn send_play(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePlay)
            .recipient(recipient)
            .send();
    }

    pub fn send_pause(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePause)
            .recipient(recipient)
            .send();
    }

    pub fn send_prev(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePrev)
            .recipient(recipient)
            .send();
    }

    pub fn send_next(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeNext)
            .recipient(recipient)
            .send();
    }

    pub fn send_replace_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                              recipient: &str,
                                                              track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeReplace)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_load_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                           recipient: &str,
                                                           track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeLoad)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_goodbye(&self) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeGoodbye)
            .send();
    }

    pub fn get_queue(&self) -> Vec<SpotifyId> {
        self.0.lock().unwrap().tracks.clone()
    }
}

impl SpircInternal {
    fn on_update(&mut self, player_state: &PlayerState) {
        let end_of_track = player_state.end_of_track();
        if end_of_track {
            self.index = (self.index + 1) % self.tracks.len() as u32;
            let track = self.tracks[self.index as usize];
            self.player.load(track, true, 0);
        } else {
            self.notify(false, None);
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_ident() == self.ident ||
           (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) {
            return;
        }

        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }

        if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() {
            self.devices.insert(frame.get_ident().into(),
                                frame.get_device_state().get_name().into());
        }

        match frame.get_typ() {
            MessageType::kMessageTypeHello => {
                self.notify(false, Some(frame.get_ident()));
            }
            MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.reload_tracks(&frame);
                if self.tracks.len() > 0 {
                    let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                    let track = self.tracks[self.index as usize];
                    let position = frame.get_state().get_position_ms();
                    self.player.load(track, play, position);
                } else {
                    self.notify(false, Some(frame.get_ident()));
                }
            }
            MessageType::kMessageTypePlay => {
                self.player.play();
                self.mixer.start();
            }
            MessageType::kMessageTypePause => {
                self.player.pause();
                self.mixer.stop();
            }
            MessageType::kMessageTypeNext => {
                self.index = (self.index + 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypePrev => {
                self.index = (self.index - 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypeSeek => {
                self.player.seek(frame.get_position());
            }
            MessageType::kMessageTypeReplace => {
                self.reload_tracks(&frame);
            }
            MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.player.stop();
                    self.mixer.stop();
                }
            }
            MessageType::kMessageTypeVolume => {
                self.mixer.set_volume(frame.get_volume() as u16);
            }
            MessageType::kMessageTypeGoodbye => {
                if frame.has_ident() {
                    self.devices.remove(frame.get_ident());
                }
            }
            _ => (),
        }
    }

    fn reload_tracks(&mut self, ref frame: &protocol::spirc::Frame) {
        self.index = frame.get_state().get_playing_track_index();
        self.tracks = frame.get_state()
                           .get_track()
                           .iter()
                           .filter(|track| track.has_gid())
                           .map(|track| SpotifyId::from_raw(track.get_gid()))
                           .collect();
    }

    fn notify(&mut self, hello: bool, recipient: Option<&str>) {
        let mut cs = CommandSender::new(self,
                                        if hello {
                                            MessageType::kMessageTypeHello
                                        } else {
                                            MessageType::kMessageTypeNotify
                                        });
        if let Some(s) = recipient {
            cs = cs.recipient(&s);
        }
        cs.send();
    }

    fn spirc_state(&self, state: &State) -> protocol::spirc::State {
        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status,
            position_ms: state.position_ms,
            position_measured_at: state.position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self, state: &State) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version::version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: state.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [64]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album",
                        "playlist",
                        "search",
                        "inbox",
                        "toplist",
                        "starred",
                        "publishedstarred",
                        "track",
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local",
                        "audio/track",
                        "local",
                        "track",
                    ]
                }
            ],
        })
    }

    fn uri(&self) -> String {
        format!("hm://remote/user/{}", self.session.username())
    }
}

struct CommandSender<'a> {
    spirc_internal: &'a mut SpircInternal,
    cmd: MessageType,
    recipient: Option<&'a str>,
    state: Option<protocol::spirc::State>,
}

impl<'a> CommandSender<'a> {
    fn new(spirc_internal: &'a mut SpircInternal, cmd: MessageType) -> CommandSender {
        CommandSender {
            spirc_internal: spirc_internal,
            cmd: cmd,
            recipient: None,
            state: None,
        }
    }

    fn recipient(mut self, r: &'a str) -> CommandSender {
        self.recipient = Some(r);
        self
    }

    fn state(mut self, s: protocol::spirc::State) -> CommandSender<'a> {
        self.state = Some(s);
        self
    }

    fn send(self) {
        let state = State::new()
                         .update_from_player(&self.spirc_internal.player)
                         .update_from_mixer(&self.spirc_internal.mixer);

        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.spirc_internal.ident.clone(),
            protocol_version: "2.0.0",
            seq_nr: { self.spirc_internal.seq_nr += 1; self.spirc_internal.seq_nr  },
            typ: self.cmd,
            recipient: RepeatedField::from_vec(
                self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
                ),
            device_state: self.spirc_internal.device_state(&state),
            state_update_id: state.update_time
        });

        if self.spirc_internal.is_active {
            pkt.set_state(self.spirc_internal.spirc_state(&state));
        }

        self.spirc_internal
            .session
            .mercury(MercuryRequest {
                method: MercuryMethod::SEND,
                uri: self.spirc_internal.uri(),
                content_type: None,
                payload: vec![pkt.write_to_bytes().unwrap()],
            })
            .fire();
    }
}

fn track_ids_to_state<I: Iterator<Item = SpotifyId>>(track_ids: I) -> protocol::spirc::State {
    let tracks: Vec<protocol::spirc::TrackRef> =
        track_ids.map(|i| {
                     protobuf_init!(protocol::spirc::TrackRef::new(), { gid: i.to_raw().to_vec()})
                 })
                 .collect();
    protobuf_init!(protocol::spirc::State::new(), {
                    track: RepeatedField::from_vec(tracks)
                })
}
<|endoftext|>


<commit_before>extern crate rand;
use std::ops::Index;
use table::rand::Rng;

#[derive(Clone)]
pub struct Bucket {
    pointers: Vec<usize>,
    hash_sig: usize
}

impl Bucket {
    pub fn new(hash_sig: usize) -> Self {
        Bucket {
            pointers: Vec::new(),
            hash_sig: hash_sig
        }
    }
    pub fn push(&mut self, value: usize) {
        self.pointers.push(value);
    }
}

#[derive(Clone)]
pub struct BucketChain {
    chain: Vec<Bucket>
}

impl BucketChain {
    pub fn new() -> Self {
        BucketChain{
            chain: Vec::new()
        }
    }
    pub fn get(&self, _index: usize) -> Option<&Bucket> {
        for bucket_ref in self.chain.iter() {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn get_mut(&mut self, _index: usize) -> Option<&mut Bucket> {
        for bucket_ref in self.chain.iter_mut() {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn create_and_add_bucket(&mut self, bucket_sig: usize, value: usize) {
        let mut new_bucket = Bucket::new(bucket_sig);
        new_bucket.push(value);
        self.chain.push(new_bucket);
    }
}

 // later this will have chaining, for now just blob
 // everything together
const P: f64 = (0xFFFFFFFE as usize - 4) as f64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<BucketChain>,
    data: &'a [T],
    hash_functions: &'a [Box<Q>],
    ri1: Vec<f64>,
    ri2: Vec<f64>,
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f64 {
    pub fn new(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        LSHTable {
            buckets: vec![BucketChain::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
            ri2: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f64> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, P, x_to_build.buckets.len());
            let ref mut bucket_chain = x_to_build.buckets[bucket_ind];
            let chain_ind = hash_func_t2(&hash_sig, &x_to_build.ri2, P );
            let mut bad = false;
            {
                let bucket_opt = bucket_chain.get_mut(chain_ind);
                match bucket_opt {
                    Some(bucket_ref) => bucket_ref.push(i),
                    None => bad = true
                };
            }
            if bad {
                bucket_chain.create_and_add_bucket(chain_ind, i);
            }
        }
        x_to_build
    }

    pub fn query_vec(&self, v: &'a T) -> Vec<&T> {
        let sig = self.get_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, P, self.buckets.len());
        let chain_ind = hash_func_t2(&sig, &self.ri2, P );
        match self.buckets[sig_ind].get(chain_ind) {
           Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                &self.data[*bucket_ind]
           }).collect(),
            None => Vec::new()
        }
    }
}

fn hash_func_t1(signature: &[f64], rand_ints: &[f64], primes: f64, num_buckets: usize) -> usize {
    let total: usize = hash_func_t2(signature, rand_ints, primes);
    total % num_buckets
}

fn hash_func_t2(signature: &[f64], rand_ints: &[f64], primes: f64) -> usize {
    let mut counter: f64 = 0.0;
    for element in signature.iter().zip(rand_ints).map(|(a, b)| {(a * b)}) {
        counter = ((counter + element)) % primes;
    }
    counter as usize
}
#[cfg(test)]
mod tests {
    use super::LSHTable;
    #[test]
    fn test_init() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new(&test_data, &funcs);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
    }

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
        x.query_vec(&test_data[0]);
    }
}
<commit_msg>some changes to satisfy clippy<commit_after>extern crate rand;
use table::rand::Rng;

#[derive(Clone)]
pub struct Bucket {
    pointers: Vec<usize>,
    hash_sig: usize
}

impl Bucket {
    pub fn new(hash_sig: usize) -> Self {
        Bucket {
            pointers: Vec::new(),
            hash_sig: hash_sig
        }
    }
    pub fn push(&mut self, value: usize) {
        self.pointers.push(value);
    }
}

#[derive(Clone, Default)]
pub struct BucketChain {
    chain: Vec<Bucket>
}

impl BucketChain {
    pub fn new() -> Self {
        BucketChain{
            chain: Vec::new()
        }
    }
    pub fn get(&self, _index: usize) -> Option<&Bucket> {
        for bucket_ref in &self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn get_mut(&mut self, _index: usize) -> Option<&mut Bucket> {
        for bucket_ref in &mut self.chain {
            if bucket_ref.hash_sig == _index {
                return Some(bucket_ref);
            }
        }
        None
    }
    pub fn create_and_add_bucket(&mut self, bucket_sig: usize, value: usize) {
        let mut new_bucket = Bucket::new(bucket_sig);
        new_bucket.push(value);
        self.chain.push(new_bucket);
    }
}

 // later this will have chaining, for now just blob
 // everything together
const P: f64 = (0xFFFFFFFE as usize - 4) as f64;
pub struct LSHTable<'a, T: 'a, Q: 'a+?Sized>  {
    buckets: Vec<BucketChain>,
    data: &'a [T],
    hash_functions: &'a [Box<Q>],
    ri1: Vec<f64>,
    ri2: Vec<f64>,
}

impl<'a, T, Q: 'a+?Sized> LSHTable<'a, T, Q> where Q: Fn(&'a T) -> f64 {
    pub fn new(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        LSHTable {
            buckets: vec![BucketChain::new(); data.len()],
            data: data,
            hash_functions: hashes,
            ri1: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
            ri2: rand::thread_rng().gen_iter().take(hashes.len()).collect(),
        }
    }
    fn get_signature(&self, v: &'a T) -> Vec<f64> {
        self.hash_functions.iter().map(|x| {
            (*x)(v)
        }).collect()
    }
    pub fn new_build(data: &'a [T], hashes: &'a [Box<Q>]) -> Self {
        let mut x_to_build = LSHTable::new(data, hashes);
        for (i, v) in x_to_build.data.iter().enumerate() {
            let hash_sig = x_to_build.get_signature(v);
            let bucket_ind = hash_func_t1(&hash_sig, &x_to_build.ri1, P, x_to_build.buckets.len());
            let mut bucket_chain = &mut (x_to_build.buckets[bucket_ind]);
            let chain_ind = hash_func_t2(&hash_sig, &x_to_build.ri2, P );
            let mut bad = false;
            {
                let bucket_opt = bucket_chain.get_mut(chain_ind);
                match bucket_opt {
                    Some(bucket_ref) => bucket_ref.push(i),
                    None => bad = true
                };
            }
            if bad {
                bucket_chain.create_and_add_bucket(chain_ind, i);
            }
        }
        x_to_build
    }

    pub fn query_vec(&self, v: &'a T) -> Vec<&T> {
        let sig = self.get_signature(v);
        let sig_ind = hash_func_t1(&sig, &self.ri1, P, self.buckets.len());
        let chain_ind = hash_func_t2(&sig, &self.ri2, P );
        match self.buckets[sig_ind].get(chain_ind) {
           Some(bucket) => bucket.pointers.iter().map(|bucket_ind| {
                &self.data[*bucket_ind]
           }).collect(),
            None => Vec::new()
        }
    }
}

fn hash_func_t1(signature: &[f64], rand_ints: &[f64], primes: f64, num_buckets: usize) -> usize {
    let total: usize = hash_func_t2(signature, rand_ints, primes);
    total % num_buckets
}

fn hash_func_t2(signature: &[f64], rand_ints: &[f64], primes: f64) -> usize {
    let mut counter: f64 = 0.0;
    for element in signature.iter().zip(rand_ints).map(|(a, b)| {(a * b)}) {
        counter = ((counter + element)) % primes;
    }
    counter as usize
}
#[cfg(test)]
mod tests {
    use super::LSHTable;
    #[test]
    fn test_init() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new(&test_data, &funcs);
    }
    #[test]
    fn test_new_build() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
    }

    #[test]
    fn test_query() {
        let test_data = vec![
            vec![1,2,3,4,5],
            vec![0,0,0,0,0],
            vec![1,2,3,4,5]
        ];

        let val = |q: &Vec<i32>| {0.0 as f64};
        let funcs = vec![Box::new(val)];
        let x = LSHTable::new_build(&test_data, &funcs);
        x.query_vec(&test_data[0]);
    }
}
<|endoftext|>


<commit_before>use super::*;

// This is the runtime cursor on iteration
// It hold a copy of the containing page next page lock guard
// These lock guards are preventing the node and their neighbourhoods been changed externally
// Ordering are specified that can also change lock pattern
pub struct RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub index: usize,
    pub ordering: Ordering,
    pub page: Option<NodeCellRef>,
    pub deleted: DeletionSet,
    pub marker: PhantomData<(KS, PS)>,
}

impl<KS, PS> RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub fn new(pos: usize, page: &NodeCellRef, ordering: Ordering, deleted: &DeletionSet) -> Self {
        let mut cursor = RTCursor {
            index: pos,
            ordering,
            page: Some(page.clone()),
            deleted: deleted.clone(),
            marker: PhantomData,
        };
        match ordering {
            Ordering::Forward => {
                let len = read_node(page, |node: &NodeReadHandler<KS, PS>| node.len());
                if pos >= len {
                    cursor.next();
                }
            }
            Ordering::Backward => {}
        }
        cursor
    }
    fn boxed(self) -> Box<IndexCursor> {
        box self
    }

    fn next_candidate(&mut self) -> bool {
        if self.page.is_some() {
            let current_page = self.page.clone().unwrap();
            read_node(&current_page, |page: &NodeReadHandler<KS, PS>| {
                let ext_page = page.extnode();
                // debug!("Next id with index: {}, length: {}", self.index + 1, ext_page.len);
                match self.ordering {
                    Ordering::Forward => {
                        if page.is_empty() {
                            let next_node = read_unchecked::<KS, PS>(&ext_page.next);
                            self.index = 0;
                            self.page = Some(ext_page.next.clone());
                            if next_node.is_none() {
                                self.page = None;
                                return false;
                            } else if next_node.is_empty() {
                                return self.next();
                            } else if next_node.is_ext() {
                                return true;
                            } else {
                                unreachable!()
                            }
                        }
                        if self.index + 1 >= page.len() {
                            // next page
                            return read_node(
                                &ext_page.next,
                                |next_page: &NodeReadHandler<KS, PS>| {
                                    if !next_page.is_none() {
                                        // debug!("Shifting page forward, next page len: {}", next_page.len());
                                        self.index = 0;
                                        self.page = Some(ext_page.next.clone());
                                        return true;
                                    } else {
                                        // debug!("iterated to end");
                                        self.page = None;
                                        return false;
                                    }
                                },
                            );
                        } else {
                            self.index += 1;
                            // debug!("Advancing cursor to index {}", self.index);
                        }
                    }
                    Ordering::Backward => {
                        if page.is_empty() {
                            let prev_node = read_unchecked::<KS, PS>(&ext_page.prev);
                            self.index = 0;
                            self.page = Some(ext_page.next.clone());
                            if prev_node.is_none() {
                                self.page = None;
                                return false;
                            } else if prev_node.is_empty() {
                                return self.next();
                            } else if prev_node.is_ext() {
                                return true;
                            } else {
                                unreachable!()
                            }
                        }
                        if self.index == 0 {
                            // next page
                            return read_node(
                                &ext_page.prev,
                                |prev_page: &NodeReadHandler<KS, PS>| {
                                    if !prev_page.is_none() {
                                        debug!("Shifting page backward");
                                        self.page = Some(ext_page.prev.clone());
                                        self.index = prev_page.len() - 1;
                                        return true;
                                    } else {
                                        debug!("iterated to end");
                                        self.page = None;
                                        return false;
                                    }
                                },
                            );
                        } else {
                            self.index -= 1;
                            // debug!("Advancing cursor to index {}", self.index);
                        }
                    }
                }
                true
            })
        } else {
            false
        }
    }
}

impl<KS, PS> IndexCursor for RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    fn next(&mut self) -> bool {
        loop {
            let has_candidate = self.next_candidate();
            if has_candidate {
                // search in deleted set and skip if exists
                if !self.deleted.read().contains(self.current().unwrap()) {
                    return true;
                }
            } else {
                return false;
            }
        }
    }

    fn current(&self) -> Option<&EntryKey> {
        if let &Some(ref page_ref) = &self.page {
            read_node(page_ref, |handler: &NodeReadHandler<KS, PS>| {
                let page = unsafe { &*handler.ptr };
                if self.index >= page.len() {
                    panic!(
                        "FIXME: cursor position overflowed {}/{}",
                        self.index,
                        page.len()
                    )
                }
                Some(&page.extnode().keys.as_slice_immute()[self.index])
            })
        } else {
            return None;
        }
    }
}
<commit_msg>use read with retry always for cursor<commit_after>use super::*;

// This is the runtime cursor on iteration
// It hold a copy of the containing page next page lock guard
// These lock guards are preventing the node and their neighbourhoods been changed externally
// Ordering are specified that can also change lock pattern
pub struct RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub index: usize,
    pub ordering: Ordering,
    pub page: Option<NodeCellRef>,
    pub deleted: DeletionSet,
    pub marker: PhantomData<(KS, PS)>,
}

impl<KS, PS> RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub fn new(pos: usize, page: &NodeCellRef, ordering: Ordering, deleted: &DeletionSet) -> Self {
        let mut cursor = RTCursor {
            index: pos,
            ordering,
            page: Some(page.clone()),
            deleted: deleted.clone(),
            marker: PhantomData,
        };
        match ordering {
            Ordering::Forward => {
                let len = read_node(page, |node: &NodeReadHandler<KS, PS>| node.len());
                if pos >= len {
                    cursor.next();
                }
            }
            Ordering::Backward => {}
        }
        cursor
    }
    fn boxed(self) -> Box<IndexCursor> {
        box self
    }

    fn next_candidate(&mut self) -> bool {
        if self.page.is_some() {
            let current_page = self.page.clone().unwrap();
            read_node(&current_page, |page: &NodeReadHandler<KS, PS>| {
                let ext_page = page.extnode();
                // debug!("Next id with index: {}, length: {}", self.index + 1, ext_page.len);
                match self.ordering {
                    Ordering::Forward => {
                        if page.is_empty() {
                            return read_node(
                                &ext_page.next,
                                |next_node: &NodeReadHandler<KS, PS>| {
                                    self.index = 0;
                                    self.page = Some(ext_page.next.clone());
                                    if next_node.is_none() {
                                        self.page = None;
                                        return false;
                                    } else if next_node.is_empty() {
                                        return self.next();
                                    } else if next_node.is_ext() {
                                        return true;
                                    } else {
                                        unreachable!()
                                    }
                                },
                            );
                        }
                        if self.index + 1 >= page.len() {
                            // next page
                            return read_node(
                                &ext_page.next,
                                |next_page: &NodeReadHandler<KS, PS>| {
                                    if !next_page.is_none() {
                                        // debug!("Shifting page forward, next page len: {}", next_page.len());
                                        self.index = 0;
                                        self.page = Some(ext_page.next.clone());
                                        return true;
                                    } else {
                                        // debug!("iterated to end");
                                        self.page = None;
                                        return false;
                                    }
                                },
                            );
                        } else {
                            self.index += 1;
                            // debug!("Advancing cursor to index {}", self.index);
                        }
                    }
                    Ordering::Backward => {
                        if page.is_empty() {
                            return read_node(
                                &ext_page.prev,
                                |prev_node: &NodeReadHandler<KS, PS>| {
                                    self.index = prev_node.len() - 1;
                                    self.page = Some(ext_page.prev.clone());
                                    if prev_node.is_none() {
                                        self.page = None;
                                        return false;
                                    } else if prev_node.is_empty() {
                                        return self.next();
                                    } else if prev_node.is_ext() {
                                        return true;
                                    } else {
                                        unreachable!()
                                    }
                                },
                            );
                        }
                        if self.index == 0 {
                            // next page
                            return read_node(
                                &ext_page.prev,
                                |prev_page: &NodeReadHandler<KS, PS>| {
                                    if !prev_page.is_none() {
                                        debug!("Shifting page backward");
                                        self.page = Some(ext_page.prev.clone());
                                        self.index = prev_page.len() - 1;
                                        return true;
                                    } else {
                                        debug!("iterated to end");
                                        self.page = None;
                                        return false;
                                    }
                                },
                            );
                        } else {
                            self.index -= 1;
                            // debug!("Advancing cursor to index {}", self.index);
                        }
                    }
                }
                true
            })
        } else {
            false
        }
    }
}

impl<KS, PS> IndexCursor for RTCursor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    // TODO: Copy current after next
    fn next(&mut self) -> bool {
        loop {
            let has_candidate = self.next_candidate();
            if has_candidate {
                // search in deleted set and skip if exists
                if !self.deleted.read().contains(self.current().unwrap()) {
                    return true;
                }
            } else {
                return false;
            }
        }
    }

    // TODO: Use copied key reference
    fn current(&self) -> Option<&EntryKey> {
        if let &Some(ref page_ref) = &self.page {
            read_node(page_ref, |handler: &NodeReadHandler<KS, PS>| {
                let page = unsafe { &*handler.ptr };
                if self.index >= page.len() {
                    panic!(
                        "FIXME: cursor position overflowed {}/{}",
                        self.index,
                        page.len()
                    )
                }
                Some(&page.extnode().keys.as_slice_immute()[self.index])
            })
        } else {
            return None;
        }
    }
}
<|endoftext|>


<commit_before>use crate::{decode_config, encode::encoded_size, encode_config_buf, CharacterSet, Config};

use std::str;

use rand::{
    distributions::{Distribution, Uniform},
    seq::SliceRandom,
    FromEntropy, Rng,
};

#[test]
fn roundtrip_random_config_short() {
    // exercise the slower encode/decode routines that operate on shorter buffers more vigorously
    roundtrip_random_config(Uniform::new(0, 50), 10_000);
}

#[test]
fn roundtrip_random_config_long() {
    roundtrip_random_config(Uniform::new(0, 1000), 10_000);
}

pub fn assert_encode_sanity(encoded: &str, config: Config, input_len: usize) {
    let input_rem = input_len % 3;
    let expected_padding_len = if input_rem > 0 {
        if config.pad {
            3 - input_rem
        } else {
            0
        }
    } else {
        0
    };

    let expected_encoded_len = encoded_size(input_len, config).unwrap();

    assert_eq!(expected_encoded_len, encoded.len());

    let padding_len = encoded.chars().filter(|&c| c == '=').count();

    assert_eq!(expected_padding_len, padding_len);

    let _ = str::from_utf8(encoded.as_bytes()).expect("Base64 should be valid utf8");
}

fn roundtrip_random_config(input_len_range: Uniform<usize>, iterations: u32) {
    let mut input_buf: Vec<u8> = Vec::new();
    let mut encoded_buf = String::new();
    let mut rng = rand::rngs::SmallRng::from_entropy();

    for _ in 0..iterations {
        input_buf.clear();
        encoded_buf.clear();

        let input_len = input_len_range.sample(&mut rng);

        let config = random_config(&mut rng);

        for _ in 0..input_len {
            input_buf.push(rng.gen());
        }

        encode_config_buf(&input_buf, config, &mut encoded_buf);

        assert_encode_sanity(&encoded_buf, config, input_len);

        assert_eq!(input_buf, decode_config(&encoded_buf, config).unwrap());
    }
}

pub fn random_config<R: Rng>(rng: &mut R) -> Config {
    const CHARSETS: &[CharacterSet] = &[
        CharacterSet::UrlSafe,
        CharacterSet::Standard,
        CharacterSet::Crypt,
    ];
    let charset = *CHARSETS.choose(rng).unwrap();

    Config::new(charset, rng.gen())
}
<commit_msg>Include new charset in random tests<commit_after>use crate::{decode_config, encode::encoded_size, encode_config_buf, CharacterSet, Config};

use std::str;

use rand::{
    distributions::{Distribution, Uniform},
    seq::SliceRandom,
    FromEntropy, Rng,
};

#[test]
fn roundtrip_random_config_short() {
    // exercise the slower encode/decode routines that operate on shorter buffers more vigorously
    roundtrip_random_config(Uniform::new(0, 50), 10_000);
}

#[test]
fn roundtrip_random_config_long() {
    roundtrip_random_config(Uniform::new(0, 1000), 10_000);
}

pub fn assert_encode_sanity(encoded: &str, config: Config, input_len: usize) {
    let input_rem = input_len % 3;
    let expected_padding_len = if input_rem > 0 {
        if config.pad {
            3 - input_rem
        } else {
            0
        }
    } else {
        0
    };

    let expected_encoded_len = encoded_size(input_len, config).unwrap();

    assert_eq!(expected_encoded_len, encoded.len());

    let padding_len = encoded.chars().filter(|&c| c == '=').count();

    assert_eq!(expected_padding_len, padding_len);

    let _ = str::from_utf8(encoded.as_bytes()).expect("Base64 should be valid utf8");
}

fn roundtrip_random_config(input_len_range: Uniform<usize>, iterations: u32) {
    let mut input_buf: Vec<u8> = Vec::new();
    let mut encoded_buf = String::new();
    let mut rng = rand::rngs::SmallRng::from_entropy();

    for _ in 0..iterations {
        input_buf.clear();
        encoded_buf.clear();

        let input_len = input_len_range.sample(&mut rng);

        let config = random_config(&mut rng);

        for _ in 0..input_len {
            input_buf.push(rng.gen());
        }

        encode_config_buf(&input_buf, config, &mut encoded_buf);

        assert_encode_sanity(&encoded_buf, config, input_len);

        assert_eq!(input_buf, decode_config(&encoded_buf, config).unwrap());
    }
}

pub fn random_config<R: Rng>(rng: &mut R) -> Config {
    const CHARSETS: &[CharacterSet] = &[
        CharacterSet::UrlSafe,
        CharacterSet::Standard,
        CharacterSet::Crypt,
        CharacterSet::ImapMutf7
    ];
    let charset = *CHARSETS.choose(rng).unwrap();

    Config::new(charset, rng.gen())
}
<|endoftext|>


<commit_before>use term::Term;
use term::Atom::{Nil, True, False};
use vm::opcode::OpCode::*;
use interpreter::*;

#[test]
fn test_op_add() {
    let code = [
        LoadU8 as u8, 73, 0,
        LoadU8 as u8, 68, 1,
        Add as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(141)));
}

#[test]
fn test_op_sub() {
    let code1 = [
        LoadU8 as u8, 10, 0,
        LoadU8 as u8, 8, 1,
        Sub as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code1), Ok(Term::Integer(2)));

    let code2 = [
        LoadU8 as u8, 8, 0,
        LoadU8 as u8, 10, 1,
        Sub as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code2), Ok(Term::Integer(-2)));
}

#[test]
fn test_op_mult() {
    let code = [
        LoadU8 as u8, 2, 0,
        LoadU8 as u8, 4, 1,
        Mult as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(8)));
}

#[test]
fn test_op_lt() {
    let code1 = [
        LoadU8 as u8, 73, 0,
        LoadU8 as u8, 68, 1,
        LessThan as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code1), Ok(Term::Atom(False)));

    let code2 = [
        LoadU8 as u8, 68, 0,
        LoadU8 as u8, 73, 1,
        LessThan as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code2), Ok(Term::Atom(True)));
}

#[test]
fn test_loop() {
    let code = [
        // Some bytecode to multiply two numbers.
        LoadU8 as u8, 6, 0,  // load the number 6 into R0 (`X`, the first number to multiply)
        LoadU8 as u8, 8, 1,  // load the number 8 into R1 (`Y`, the second number to multiply)
        LoadU8 as u8, 0, 2,  // load the number 0 into R2 (`i`, the loop counter)
        LoadU8 as u8, 0, 3,  // load the number 0 into R3 (`acc`, the accumulator)
        LoadU8 as u8, 1, 4,  // load the number 1 into R4 - it stays there forever

        // for (int i = 0; i < x; i++) {
        //   acc += y;
        // }

        Add as u8, 1, 3, 3,   // add R1 to R3, store the result in R3
        Add as u8, 2, 4, 2,   // increment R2 by 1 (because the value in R4 is 1)
        LessThan as u8, 2, 0, 5,    // is R2 < R0?
        JumpTrue as u8, 5, 0xee, 0xff, 0xff, 0xff, // if so, jump back 18 bytes

        Return as u8, 3,      // return contents of R3 (`acc`)
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(48)));
}
<commit_msg>update loop test comments<commit_after>use term::Term;
use term::Atom::{Nil, True, False};
use vm::opcode::OpCode::*;
use interpreter::*;

#[test]
fn test_op_add() {
    let code = [
        LoadU8 as u8, 73, 0,
        LoadU8 as u8, 68, 1,
        Add as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(141)));
}

#[test]
fn test_op_sub() {
    let code1 = [
        LoadU8 as u8, 10, 0,
        LoadU8 as u8, 8, 1,
        Sub as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code1), Ok(Term::Integer(2)));

    let code2 = [
        LoadU8 as u8, 8, 0,
        LoadU8 as u8, 10, 1,
        Sub as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code2), Ok(Term::Integer(-2)));
}

#[test]
fn test_op_mult() {
    let code = [
        LoadU8 as u8, 2, 0,
        LoadU8 as u8, 4, 1,
        Mult as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(8)));
}

#[test]
fn test_op_lt() {
    let code1 = [
        LoadU8 as u8, 73, 0,
        LoadU8 as u8, 68, 1,
        LessThan as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code1), Ok(Term::Atom(False)));

    let code2 = [
        LoadU8 as u8, 68, 0,
        LoadU8 as u8, 73, 1,
        LessThan as u8, 0, 1, 2,
        Return as u8, 2
    ];

    assert_eq!(interpret(&code2), Ok(Term::Atom(True)));
}

#[test]
fn test_loop() {
    let code = [
        // Some bytecode to multiply two numbers.
        //
        // x = 6;
        // y = 8;
        // acc = 0;
        //
        // for (i = 0; i < x; i++) {
        //   acc += y;
        // }
        //
        // return acc;

        LoadU8 as u8, 6, 0, // load the number 6 into R0 (`X`, the first number to multiply)
        LoadU8 as u8, 8, 1, // load the number 8 into R1 (`Y`, the second number to multiply)
        LoadU8 as u8, 0, 2, // load the number 0 into R2 (`i`, the loop counter)
        LoadU8 as u8, 0, 3, // load the number 0 into R3 (`acc`, the accumulator)
        LoadU8 as u8, 1, 4, // load the number 1 into R4 - it stays there forever
        Add as u8, 1, 3, 3, // add R1 to R3, store the result in R3
        Add as u8, 2, 4, 2, // increment R2 by 1 (because the value in R4 is 1)
        LessThan as u8, 2, 0, 5, // is R2 < R0?
        JumpTrue as u8, 5, 0xee, 0xff, 0xff, 0xff, // if so, jump back 18 bytes

        Return as u8, 3, // return contents of R3 (`acc`)
    ];

    assert_eq!(interpret(&code), Ok(Term::Integer(48)));
}
<|endoftext|>