<commit_before>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::Each =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::Each => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::Each =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    byte = set_bit(byte, i as u8, val % 2 == 1);
                }

                buf.push(byte);
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in each field even/odd
    Each,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Alpha, rng);

        let dec = decode_rgba(&image, RgbaMode::Alpha);

        assert_eq!(payload, dec);
    }

    #[test]
    fn each()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            2,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Each, rng);

        let dec = decode_rgba(&image, RgbaMode::Each);

        assert_eq!(payload, dec);
    }
}
<commit_msg>Renamed 'Each' to 'All' in RgbaMode<commit_after>use image::RgbaImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;

pub fn encode_rgba<R: Rng>(source: &mut RgbaImage, payload: &[u8], mode: RgbaMode, mut rng: R)
{
    // number of pixels per byte
    let ppb = match mode
    {
        // 1 values per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // 4 values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    for (mut pixels, byte) in source.pixels_mut() // iterate pixels mutably
        .chunks(ppb).into_iter()              // split them into ppb-size chunks
        .map(|ch| ch.collect::<Vec<_>>())     // make them vectors so we can check their lengths later
        .zip(payload.iter().map(|x| *x))      // give each chunk a byte
    {
        // if the pixels don't fit exactly into their chunks,
        // the last chunk will be short. we won't use that chunk
        // (making sure the payload fits into the image is not
        // this functions job!)
        if pixels.len() != ppb
        {
            return;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                for (i, px) in pixels.into_iter().enumerate()
                {
                    // a true, or 1 bit
                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if px.data[3] % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if px.data[3] == 0
                            {
                                px.data[3] = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if px.data[3] % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if px.data[3] == 255
                            {
                                px.data[3] = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    px.data[3] += 1;
                                }
                                else
                                {
                                    px.data[3] -= 1;
                                }
                            }
                        }
                    }
                }
            },
            RgbaMode::All =>
            {
                for i in 0..8
                {
                    let val = if i < 4
                    {
                        &mut pixels[0].data[i]
                    }
                    else
                    {
                        &mut pixels[1].data[i - 4]
                    };

                    if get_bit(byte, i as u8)
                    {
                        // even = 0 bit, so it needs to be changed
                        if *val % 2 == 0
                        {
                            // special case: if it's zero, we have to go up
                            if *val == 0
                            {
                                *val = 1;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                    // a false, or 0 bit
                    else
                    {
                        // odd = 1 bit, so it needs to be changed
                        if *val % 2 == 1
                        {
                            // special case: if it's 255, we have to go down
                            if *val == 255
                            {
                                *val = 254;
                            }
                            else
                            {
                                if rng.gen()
                                {
                                    *val += 1;
                                }
                                else
                                {
                                    *val -= 1;
                                }
                            }
                        }
                    }
                }
            },
        }
    }
}

pub fn decode_rgba(source: &RgbaImage, mode: RgbaMode) -> Vec<u8>
{
    // pixels per byte
    let ppb: usize = match mode
    {
        // one value per pixel = 8 pixels per byte
        RgbaMode::Alpha => 8,
        // four values per pixel = 2 pixels per byte
        RgbaMode::All => 2,
    };

    let mut buf = Vec::with_capacity(source.width() as usize* source.height() as usize/ ppb);

    for pixels in source.pixels()         // iterate pixels
        .chunks(ppb).into_iter()          // split into ppb-sized chunks
        .map(|ch| ch.collect::<Vec<_>>()) // make them vectors so we can check their lengths
    {
        // only decode while we have enough data
        if pixels.len() != ppb
        {
            break;
        }

        match mode
        {
            RgbaMode::Alpha =>
            {
                let mut byte = 0u8;

                for (i, px) in pixels.into_iter().enumerate()
                {
                    byte = set_bit(byte, i as u8, px.data[3] % 2 == 1);
                }

                buf.push(byte)
            },
            RgbaMode::All =>
            {
                let mut byte = 0u8;

                for i in 0..8
                {
                    let val = if i < 4
                    {
                        pixels[0].data[i]
                    }
                    else
                    {
                        pixels[1].data[i - 4]
                    };

                    byte = set_bit(byte, i as u8, val % 2 == 1);
                }

                buf.push(byte);
            }
        }
    }

    buf

}

/// The encoding/decoding mode
#[derive(Copy, Clone)]
pub enum RgbaMode
{
    /// encode in alpha even/odd
    Alpha,
    /// encode in all field even/odd
    All,
}

use std::default::Default;

impl Default for RgbaMode
{
    fn default() -> RgbaMode
    {
        RgbaMode::Alpha
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgba};
    use rand::StdRng;

    use super::*;

    #[test]
    fn alpha()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            8,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::Alpha, rng);

        let dec = decode_rgba(&image, RgbaMode::Alpha);

        assert_eq!(payload, dec);
    }

    #[test]
    fn all()
    {
        let mut image = ImageBuffer::from_pixel(
            25,
            2,
            Rgba
            {
                data: [127u8; 4],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25
        ];

        let rng = StdRng::new().unwrap();

        encode_rgba(&mut image, &payload, RgbaMode::All, rng);

        let dec = decode_rgba(&image, RgbaMode::All);

        assert_eq!(payload, dec);
    }
}
<|endoftext|>


<commit_before>use line::Line;
use update::Update;

#[derive(Clone)]
pub struct View {
    last_rev: u64,
    pub filepath: String,
    lines: Vec<Line>,
}

impl View {
    pub fn new(filepath: String) -> View {
        View {
            last_rev: 0,
            filepath: filepath,
            lines: vec![],
        }
    }

    pub fn update(&mut self, update: &Update) {
        if self.last_rev > update.rev {
            return;
        }
        let mut lines = vec![];
        let mut index = 0;

        for op in update.ops.iter() {
            index = op.apply(&self.lines, index, &mut lines);
        }

        self.last_rev = update.rev;
        self.lines = lines;
    }
}
<commit_msg>Makes `lines` public in View<commit_after>use line::Line;
use update::Update;

#[derive(Clone)]
pub struct View {
    last_rev: u64,
    pub filepath: String,
    pub lines: Vec<Line>,
}

impl View {
    pub fn new(filepath: String) -> View {
        View {
            last_rev: 0,
            filepath: filepath,
            lines: vec![],
        }
    }

    pub fn update(&mut self, update: &Update) {
        if self.last_rev > update.rev {
            return;
        }
        let mut lines = vec![];
        let mut index = 0;

        for op in update.ops.iter() {
            index = op.apply(&self.lines, index, &mut lines);
        }

        self.last_rev = update.rev;
        self.lines = lines;
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;

pub fn wrap_msg(s: String, n: usize) -> String {
    let split = s.split(' ').collect::<Vec<_>>();
    let mut chunks = split.chunks(8).map(|x| x.join(" "));

    chunks.next().unwrap_or("?".to_string()) + "\n" + &chunks.map(|ref x| {

        "           >  ".to_string() + &repeat(" ").take(n)
                                                     .collect::<String>() + x

    }).collect::<Vec<_>>().join("\n")
}
<commit_msg>Fix word wrapping<commit_after>use std::iter::repeat;

pub fn wrap_msg(s: String, n: usize) -> String {
    let split = s.split(' ').collect::<Vec<_>>();
    let mut chunks = split.chunks(8).map(|x| x.join(" "));

    chunks.next().unwrap_or("?".to_string()) + &chunks.map(|ref x| {

        "\n           >  ".to_string() + &repeat(" ").take(n)
                                                   .collect::<String>()
                                     + x

    }).collect::<String>()
}
<|endoftext|>


<commit_before>use super::node::write_node;
use super::node::NodeWriteGuard;
use super::search::MutSearchResult;
use super::BPlusTree;
use super::LevelTree;
use super::NodeCellRef;
use super::*;
use itertools::Itertools;
use std::cmp::min;
use std::fmt::Debug;
use std::sync::atomic::Ordering;

pub const LEVEL_PAGE_DIFF_MULTIPLIER: usize = 4;
pub const LEVEL_TREE_DEPTH: u32 = 2;

pub const LEVEL_M: usize = 4;
pub const LEVEL_0: usize = LEVEL_M * LEVEL_M; // Smaller can be faster but more fragmented
pub const LEVEL_1: usize = LEVEL_0 * LEVEL_PAGE_DIFF_MULTIPLIER;
pub const LEVEL_2: usize = LEVEL_1 * LEVEL_PAGE_DIFF_MULTIPLIER;

pub const NUM_LEVELS: usize = 3;

enum NodeSelection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    WholePage(Vec<NodeWriteGuard<KS, PS>>, NodeWriteGuard<KS, PS>),
    PartialPage(Vec<NodeWriteGuard<KS, PS>>, NodeWriteGuard<KS, PS>),
}

// Both src and dest tree MUST be immutable
fn merge_prune<KS, PS>(
    level: usize,
    node: &NodeCellRef,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    boundary: &EntryKey,
    prune: bool,
    lsm: usize,
) -> (usize, Option<NodeWriteGuard<KS, PS>>)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_first::<KS, PS>(node);
    match search {
        MutSearchResult::External => {
            if let NodeSelection::WholePage(nodes, mut new_first) =
                select_nodes_in_boundary::<KS, PS>(node, boundary, level, lsm)
            {
                let new_first_ref = new_first.node_ref().clone();
                let head_id = nodes[0].ext_id();
                new_first.extnode_mut(src_tree).id = head_id;
                new_first.left_ref_mut().map(|lr| *lr = Default::default());
                drop(new_first);
                debug_assert!(
                    !nodes.is_empty(),
                    "Cannot find any keys in range in external with boundary {:?}",
                    boundary
                );
                let mut num_keys_merged = 0;
                debug!("Selected {} pages to merge", nodes.len());
                for mut node in nodes {
                    let node_id = node.ext_id();
                    let node_len = node.len();
                    let deleted_keys = node
                        .keys()
                        .iter()
                        .filter(|k| src_tree.deletion.contains(k))
                        .cloned()
                        .collect_vec();
                    let merging_keys = node.extnode_mut_no_persist().keys.as_slice()[..node_len]
                        .iter_mut()
                        .filter(|k| !src_tree.deletion.contains(k))
                        .map(|k| mem::take(k))
                        .collect_vec();
                    let num_merging_keys = merging_keys.len();
                    num_keys_merged += num_merging_keys;
                    debug!(
                        "Collected {} keys, merging to destination tree",
                        num_merging_keys
                    );
                    dest_tree.merge_with_keys(box merging_keys);
                    if prune {
                        debug!("Merge completed, cleanup");
                        clear_node(node, &new_first_ref);
                        if node_id != head_id {
                            external::make_deleted::<KS, PS>(&node_id);
                        }
                        src_tree.len.fetch_sub(num_merging_keys, Ordering::Relaxed);
                    }
                }
                debug!("Merge prune completed in external level");
                return (num_keys_merged, None);
            } else {
                unreachable!();
            }
        }
        MutSearchResult::Internal(sub_node) => {
            enum RightCheck<KS, PS>
            where
                KS: Slice<EntryKey> + Debug + 'static,
                PS: Slice<NodeCellRef> + 'static,
            {
                SinglePtr,
                LevelTerminal(NodeWriteGuard<KS, PS>),
                Normal,
            }
            let check_right = |node: NodeWriteGuard<KS, PS>| {
                if node.right_ref().unwrap().is_default() {
                    debug_assert_eq!(node.right_bound(), &EntryKey::max());
                    if node.len() == 0 {
                        RightCheck::SinglePtr
                    } else {
                        RightCheck::LevelTerminal(node)
                    }
                } else {
                    debug_assert_ne!(node.right_bound(), &EntryKey::max());
                    debug_assert!(node.len() > 0);
                    RightCheck::Normal
                }
            };
            let (num_keys_merged, sub_level_new_root) = merge_prune(
                level + 1,
                &sub_node,
                src_tree,
                dest_tree,
                boundary,
                prune,
                lsm,
            );
            let mut new_root = None;
            if prune {
                let right_node =
                    match select_nodes_in_boundary::<KS, PS>(node, boundary, level, lsm) {
                        NodeSelection::WholePage(nodes, right_node) => {
                            let right_ref = right_node.node_ref().clone();
                            let right_checks = check_right(right_node);
                            clear_nodes(nodes, &right_ref);
                            right_checks
                        }
                        NodeSelection::PartialPage(nodes, mut terminal_node) => {
                            clear_nodes(nodes, terminal_node.node_ref());
                            let search_pos = terminal_node.keys().binary_search(boundary);
                            let pos = match search_pos {
                                Ok(n) => n + 1,
                                Err(n) => n,
                            };
                            let mut new_keys = KS::init();
                            let mut new_ptrs = PS::init();
                            let mut num_keys = 0;
                            for (i, k) in terminal_node.keys()[pos..].iter().enumerate() {
                                new_keys.as_slice()[i] = k.clone();
                                num_keys += 1;
                            }
                            for (i, p) in terminal_node.ptrs()[pos..].iter().enumerate() {
                                new_ptrs.as_slice()[i] = p.clone();
                            }
                            {
                                let innode = terminal_node.innode_mut();
                                innode.keys = new_keys;
                                innode.ptrs = new_ptrs;
                                innode.len = num_keys;
                            }
                            check_right(terminal_node)
                        }
                    };
                new_root = {
                    if let Some(sub_level_new_root) = sub_level_new_root {
                        if cfg!(debug_assertions) {
                            match right_node {
                                RightCheck::SinglePtr => {}
                                _ => panic!("Unexpected node status"),
                            }
                        }
                        Some(sub_level_new_root)
                    } else {
                        match right_node {
                            RightCheck::Normal => None,
                            RightCheck::LevelTerminal(node) => Some(node),
                            RightCheck::SinglePtr => unreachable!(),
                        }
                    }
                };
            }
            return (num_keys_merged, new_root);
        }
    }
}

fn clear_node<KS, PS>(mut node: NodeWriteGuard<KS, PS>, right_ref: &NodeCellRef)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    node.make_empty_node(false);
    *node.right_ref_mut().unwrap() = right_ref.clone();
    node.left_ref_mut().map(|r| *r = right_ref.clone());
}

fn clear_nodes<KS, PS>(nodes: Vec<NodeWriteGuard<KS, PS>>, right_ref: &NodeCellRef)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    for node in nodes {
        clear_node(node, right_ref);
    }
}

fn select_nodes_in_boundary<KS, PS>(
    first_node: &NodeCellRef,
    right_boundary: &EntryKey,
    level: usize,
    lsm: usize,
) -> NodeSelection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let first_node = write_node::<KS, PS>(first_node);
    if first_node.right_bound() > right_boundary {
        return NodeSelection::PartialPage(vec![], first_node);
    }
    let mut next_node = write_node(first_node.right_ref().unwrap());
    let mut collected = vec![first_node];
    loop {
        let first_key = next_node.first_key();
        let node_right = next_node.right_bound();
        debug_assert!(
            first_key < right_boundary,
            "First key {:?} out of bound {:?}, collected {}. Level {}, LSM {}",
            first_key,
            right_boundary,
            collected.len(),
            level,
            lsm
        );
        if node_right <= right_boundary {
            let next_right = write_node(next_node.right_ref().unwrap());
            collected.push(next_node);
            next_node = next_right;
            if next_node.first_key() >= right_boundary {
                trace!("Collected {} nodes at level {}", collected.len(), level);
                return NodeSelection::WholePage(collected, next_node);
            }
        } else {
            return NodeSelection::PartialPage(collected, next_node);
        }
    }
}

fn select_boundary<KS, PS>(node: &NodeCellRef) -> EntryKey
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let res = read_node(node, |node: &NodeReadHandler<KS, PS>| {
        let node_keys = node.keys();
        let node_len = node_keys.len();
        if node.len() < 1 {
            return Err(node.ptrs()[0].clone());
        }
        // Pick half of the keys in the root
        // Genreally, higher level sub tree in LSM tree will select more keys to merged
        // into next level
        let mid_idx = min(node_len / 2, 8);
        // Return the mid key as the boundary for selection (cut)
        Ok(node_keys[mid_idx].clone())
    });
    match res {
        Ok(key) => key.clone(),
        Err(r) => select_boundary::<KS, PS>(&r),
    }
}

pub fn level_merge<KS, PS>(
    level: usize,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    prune: bool,
) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!("Merging LSM tree level {}", level);
    let root = src_tree.get_root();
    let key_boundary = select_boundary::<KS, PS>(&root);
    merge_with_boundary(level, src_tree, dest_tree, &key_boundary, prune)
}

pub fn merge_with_boundary<KS, PS>(
    level: usize,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    key_boundary: &EntryKey,
    prune: bool,
) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!(
        "Level merge level {} with boundary {:?}",
        level, key_boundary
    );
    debug_assert!(verification::tree_has_no_empty_node(&src_tree));
    debug_assert!(verification::is_tree_in_order(&src_tree, level));
    let (num_keys, new_root) = merge_prune(
        0,
        &src_tree.get_root(),
        src_tree,
        dest_tree,
        &key_boundary,
        prune,
        level,
    );
    if let Some(new_root) = new_root {
        let new_root_ref = new_root.node_ref().clone();
        debug!("Level merge update source root {:?}", &new_root_ref);
        *src_tree.root.write() = new_root_ref;
    }
    debug_assert!(verification::tree_has_no_empty_node(&src_tree));
    debug_assert!(verification::is_tree_in_order(&src_tree, level));
    debug!("MERGE LEVEL {} COMPLETED", level);
    return num_keys;
}
<commit_msg>pruning and not pruning<commit_after>use super::node::write_node;
use super::node::NodeWriteGuard;
use super::search::MutSearchResult;
use super::BPlusTree;
use super::LevelTree;
use super::NodeCellRef;
use super::*;
use itertools::Itertools;
use std::cmp::min;
use std::fmt::Debug;
use std::sync::atomic::Ordering;

pub const LEVEL_PAGE_DIFF_MULTIPLIER: usize = 4;
pub const LEVEL_TREE_DEPTH: u32 = 2;

pub const LEVEL_M: usize = 4;
pub const LEVEL_0: usize = LEVEL_M * LEVEL_M; // Smaller can be faster but more fragmented
pub const LEVEL_1: usize = LEVEL_0 * LEVEL_PAGE_DIFF_MULTIPLIER;
pub const LEVEL_2: usize = LEVEL_1 * LEVEL_PAGE_DIFF_MULTIPLIER;

pub const NUM_LEVELS: usize = 3;

enum NodeSelection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    WholePage(Vec<NodeReadHandler<KS, PS>>, NodeReadHandler<KS, PS>),
    PartialPage(Vec<NodeReadHandler<KS, PS>>, NodeReadHandler<KS, PS>),
}

fn merge_prune<KS, PS>(
    level: usize,
    node: &NodeCellRef,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    boundary: &EntryKey,
    prune_src: bool,
    lsm: usize,
) -> (usize, Option<NodeCellRef>)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let search = mut_first::<KS, PS>(node);
    match search {
        MutSearchResult::External => {
            debug!("Selecting external nodes in boundary {:?}, tree level {}, lsm {}", boundary, level, lsm);
            if let NodeSelection::WholePage(nodes, new_first) =
                select_nodes_in_boundary::<KS, PS>(node, boundary, level, lsm)
            {
                let head_id = nodes[0].ext_id();
                debug_assert!(
                    !nodes.is_empty(),
                    "Cannot find any keys in range in external with boundary {:?}",
                    boundary
                );
                debug!("Selected {} pages to merge", nodes.len());
                let deleted_keys = nodes
                    .iter()
                    .map(|node| {
                        node
                        .keys()
                        .iter()
                        .filter(|k| src_tree.deletion.contains(k))
                        .cloned()
                    })
                    .flatten();
                let merging_keys = nodes
                    .iter()
                    .map(|node| {
                        node.keys()
                        .iter()
                        .filter(|k| !src_tree.deletion.contains(k))
                        .map(|k| k.clone())
                    })
                    .flatten()
                    .collect_vec();
                let num_keys_merged = merging_keys.len();
                debug!(
                    "Collected {} keys at level {}, merging to destination tree",
                    num_keys_merged, level
                );
                dest_tree.merge_with_keys(box merging_keys);
                debug!("Merge completed in external level");
                if prune_src {
                    debug!("Pruning source tree for {} external pages", nodes.len());
                    for node in nodes.into_iter() {
                        let node_ref = node.node_ref().clone();
                        drop(node); // unlock read
                        let node = write_node::<KS, PS>(&node_ref);
                        clear_node(node, new_first.node_ref());
                    }
                    let new_first_ref = new_first.node_ref().clone();
                    drop(new_first);
                    let mut new_first = write_node::<KS, PS>(&new_first_ref);
                    new_first.extnode_mut(src_tree).id = head_id;
                    debug!("Source tree external nodes pruned");
                }
                return (num_keys_merged, None);
            } else {
                error!("Found partial external node in selection");
                unreachable!();
            }
        }
        MutSearchResult::Internal(sub_node) => {
            enum RightCheck
            {
                SinglePtr,
                LevelTerminal(NodeCellRef),
                Normal,
            }
            let check_right = |node: NodeReadHandler<KS, PS>| {
                if node.right_ref().unwrap().is_default() {
                    debug_assert_eq!(node.right_bound(), &EntryKey::max());
                    if node.len() == 0 {
                        RightCheck::SinglePtr
                    } else {
                        RightCheck::LevelTerminal(node.right_ref().unwrap().clone())
                    }
                } else {
                    debug_assert_ne!(node.right_bound(), &EntryKey::max());
                    debug_assert!(node.len() > 0);
                    RightCheck::Normal
                }
            };
            let (num_keys_merged, sub_level_new_root) = merge_prune(
                level + 1,
                &sub_node,
                src_tree,
                dest_tree,
                boundary,
                prune_src,
                lsm,
            );
            let mut new_root = None;
            if prune_src {
                let right_node =
                    match select_nodes_in_boundary::<KS, PS>(node, boundary, level, lsm) {
                        NodeSelection::WholePage(nodes, right_node) => {
                            clear_nodes(nodes, right_node.node_ref());
                            check_right(right_node)
                        }
                        NodeSelection::PartialPage(nodes, mut terminal_node) => {
                            clear_nodes(nodes, terminal_node.node_ref());
                            let search_pos = terminal_node.keys().binary_search(boundary);
                            let pos = match search_pos {
                                Ok(n) => n + 1,
                                Err(n) => n,
                            };
                            let mut new_keys = KS::init();
                            let mut new_ptrs = PS::init();
                            let mut num_keys = 0;
                            for (i, k) in terminal_node.keys()[pos..].iter().enumerate() {
                                new_keys.as_slice()[i] = k.clone();
                                num_keys += 1;
                            }
                            for (i, p) in terminal_node.ptrs()[pos..].iter().enumerate() {
                                new_ptrs.as_slice()[i] = p.clone();
                            }
                            let terminal_ref = terminal_node.node_ref().clone();
                            let right_stat = check_right(terminal_node);
                            {
                                let mut terminal_node = write_node(&terminal_ref);
                                let innode = terminal_node.innode_mut();
                                innode.keys = new_keys;
                                innode.ptrs = new_ptrs;
                                innode.len = num_keys;
                            }
                            right_stat
                        }
                    };
                new_root = {
                    if let Some(sub_level_new_root) = sub_level_new_root {
                        if cfg!(debug_assertions) {
                            match right_node {
                                RightCheck::SinglePtr => {}
                                _ => panic!("Unexpected node status"),
                            }
                        }
                        Some(sub_level_new_root)
                    } else {
                        match right_node {
                            RightCheck::Normal => None,
                            RightCheck::LevelTerminal(node) => Some(node),
                            RightCheck::SinglePtr => unreachable!(),
                        }
                    }
                };
            }
            return (num_keys_merged, new_root);
        }
    }
}

fn clear_node<KS, PS>(mut node: NodeWriteGuard<KS, PS>, right_ref: &NodeCellRef)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    node.make_empty_node(false);
    *node.right_ref_mut().unwrap() = right_ref.clone();
    node.left_ref_mut().map(|r| *r = right_ref.clone());
}

fn clear_nodes<KS, PS>(nodes: Vec<NodeReadHandler<KS, PS>>, right_ref: &NodeCellRef)
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    for node in nodes.into_iter() {
        let node_ref = node.node_ref().clone();
        drop(node);
        let node = write_node::<KS, PS>(&node_ref);
        clear_node(node, right_ref);
    }
}

fn select_nodes_in_boundary<KS, PS>(
    first_node: &NodeCellRef,
    right_boundary: &EntryKey,
    level: usize,
    lsm: usize,
) -> NodeSelection<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let first_node = read_unchecked(first_node);
    if first_node.right_bound() > right_boundary {
        return NodeSelection::PartialPage(vec![], first_node);
    }
    let mut next_node = read_unchecked(first_node.right_ref().unwrap());
    let mut collected = vec![first_node];
    loop {
        let first_key = next_node.first_key();
        let node_right = next_node.right_bound();
        debug_assert!(
            first_key < right_boundary,
            "First key {:?} out of bound {:?}, collected {}. Level {}, LSM {}",
            first_key,
            right_boundary,
            collected.len(),
            level,
            lsm
        );
        if node_right <= right_boundary {
            let next_right = read_unchecked(next_node.right_ref().unwrap());
            debug!("Selection collected page {:?}", next_node.node_ref());
            collected.push(next_node);
            next_node = next_right;
            if next_node.first_key() >= right_boundary {
                debug!("Collected {} whole pages at level {}", collected.len(), level);
                return NodeSelection::WholePage(collected, next_node);
            }
        } else {
            debug!("Collected {} pages and partial at level {}", collected.len(), level);
            return NodeSelection::PartialPage(collected, next_node);
        }
    }
}

fn select_boundary<KS, PS>(node: &NodeCellRef) -> EntryKey
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let res = read_node(node, |node: &NodeReadHandler<KS, PS>| {
        let node_keys = node.keys();
        let node_len = node_keys.len();
        if node.len() < 1 {
            return Err(node.ptrs()[0].clone());
        }
        // Pick half of the keys in the root
        // Genreally, higher level sub tree in LSM tree will select more keys to merged
        // into next level
        let mid_idx = min(node_len / 2, 8);
        // Return the mid key as the boundary for selection (cut)
        Ok(node_keys[mid_idx].clone())
    });
    match res {
        Ok(key) => key.clone(),
        Err(r) => select_boundary::<KS, PS>(&r),
    }
}

pub fn level_merge<KS, PS>(
    level: usize,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    prune: bool,
) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!("Merging LSM tree level {}", level);
    let root = src_tree.get_root();
    let key_boundary = select_boundary::<KS, PS>(&root);
    merge_with_boundary(level, src_tree, dest_tree, &key_boundary, prune)
}

pub fn merge_with_boundary<KS, PS>(
    level: usize,
    src_tree: &BPlusTree<KS, PS>,
    dest_tree: &dyn LevelTree,
    key_boundary: &EntryKey,
    prune: bool,
) -> usize
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    debug!(
        "Level merge level {} with boundary {:?}",
        level, key_boundary
    );
    debug_assert!(verification::tree_has_no_empty_node(&src_tree));
    debug_assert!(verification::is_tree_in_order(&src_tree, level));
    debug!("Start merge prune level {}", level);
    let (num_keys, new_root) = merge_prune(
        0,
        &src_tree.get_root(),
        src_tree,
        dest_tree,
        &key_boundary,
        prune,
        level,
    );
    if let Some(new_root_ref) = new_root {
        debug!("Level merge update source root {:?}", &new_root_ref);
        *src_tree.root.write() = new_root_ref;
    }
    debug_assert!(verification::tree_has_no_empty_node(&src_tree));
    debug_assert!(verification::is_tree_in_order(&src_tree, level));
    debug!("MERGE LEVEL {} COMPLETED", level);
    return num_keys;
}
<|endoftext|>


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

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::user::{UserNoEmailType, ALL_COLUMNS};
use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken { auth_header: String },
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table
                .select(ALL_COLUMNS)
                .find(id)
                .first::<UserNoEmailType>(&*conn);
            drop(conn);
            if let Ok(user) = maybe_user {
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user_auth = if let Some(headers) = req.headers().find("Authorization") {
                let auth_header = headers[0].to_string();

                User::find_by_api_token(&conn, &auth_header)
                    .map(|user| (AuthenticationSource::ApiToken { auth_header }, user))
                    .optional()
                    .map_err(|e| Box::new(e) as Box<dyn Error + Send>)?
            } else {
                None
            };

            drop(conn);

            if let Some((api_token, user)) = user_auth {
                // Attach the `User` model from the database and the API token to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(api_token);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<commit_msg>Missed a conversion from UserNoEmailType to User<commit_after>use super::prelude::*;

use conduit_cookie::RequestSession;
use diesel::prelude::*;

use crate::db::RequestTransaction;
use crate::util::errors::{std_error, CargoResult, ChainError, Unauthorized};

use crate::models::user::{UserNoEmailType, ALL_COLUMNS};
use crate::models::User;
use crate::schema::users;

#[derive(Debug, Clone, Copy)]
pub struct CurrentUser;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum AuthenticationSource {
    SessionCookie,
    ApiToken { auth_header: String },
}

impl Middleware for CurrentUser {
    fn before(&self, req: &mut dyn Request) -> Result<(), Box<dyn Error + Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = {
            req.session()
                .get("user_id")
                .and_then(|s| s.parse::<i32>().ok())
        };

        let conn = req.db_conn().map_err(std_error)?;

        if let Some(id) = id {
            // If it did, look for a user in the database with the given `user_id`
            let maybe_user = users::table
                .select(ALL_COLUMNS)
                .find(id)
                .first::<UserNoEmailType>(&*conn);
            drop(conn);
            if let Ok(user) = maybe_user {
                let user = User::from(user);
                // Attach the `User` model from the database to the request
                req.mut_extensions().insert(user);
                req.mut_extensions()
                    .insert(AuthenticationSource::SessionCookie);
            }
        } else {
            // Otherwise, look for an `Authorization` header on the request
            // and try to find a user in the database with a matching API token
            let user_auth = if let Some(headers) = req.headers().find("Authorization") {
                let auth_header = headers[0].to_string();

                User::find_by_api_token(&conn, &auth_header)
                    .map(|user| (AuthenticationSource::ApiToken { auth_header }, user))
                    .optional()
                    .map_err(|e| Box::new(e) as Box<dyn Error + Send>)?
            } else {
                None
            };

            drop(conn);

            if let Some((api_token, user)) = user_auth {
                // Attach the `User` model from the database and the API token to the request
                req.mut_extensions().insert(user);
                req.mut_extensions().insert(api_token);
            }
        }

        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
    fn authentication_source(&self) -> CargoResult<AuthenticationSource>;
}

impl<'a> RequestUser for dyn Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions()
            .find::<User>()
            .chain_error(|| Unauthorized)
    }

    fn authentication_source(&self) -> CargoResult<AuthenticationSource> {
        self.extensions()
            .find::<AuthenticationSource>()
            .cloned()
            .chain_error(|| Unauthorized)
    }
}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

pub mod ffi;

use std::ffi::CString;
use std::io;

use domain::*;
use types::*;

use self::ffi::*;

pub struct LVar {
    subscriptions: Vec<Subscription>,
}

impl LVar {
    pub fn new() -> LVar {
        LVar { subscriptions: Vec::new() }
    }
}

impl Domain for LVar {
    fn write(&mut self, variable: &Var, value: &Value) -> io::Result<()> {
        debug!("processing a write operation for {:?} <- {}", variable, value);
        match variable {
            &Var::Named(ref lvar) => {
                let id = try!(check_named_variable(lvar).ok_or(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("there is no such named variable '{}'", lvar))));
                set_named_variable_value(id, f64::from(value));
                Ok(())
            }
            _ => {
                let error = io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("lvar domain does not support variable {:?}", variable));
                Err(error)
            }
        }
    }

    fn subscribe(&mut self, device: DeviceId, variable: &Var) -> io::Result<()> {
        info!("receiving a subscription from device {} for {:?}", device, variable);
        match variable {
            &Var::Named(ref lvar) => {
                let subs = Subscription {
                    device: device,
                    lvar: lvar.clone(),
                    retain: None,
                };
                self.subscriptions.push(subs);
                Ok(())
            }
            _ => {
                let error = io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("lvar domain does not support variable {:?}", variable));
                Err(error)
            }
        }
    }

    fn unsubscribe_all(&mut self, device: DeviceId) -> io::Result<()> {
        debug!("removing all subscriptions for device ID {}", device);
        self.subscriptions.retain(|s| s.device != device);
        Ok(())
    }

    fn poll(&mut self, events: &mut Vec<Event>) -> io::Result<()> {
        for sub in self.subscriptions.iter_mut() {
            sub.trigger_event(events);
        }
        Ok(())
    }
}

struct Subscription {
    device: DeviceId,
    lvar: String,
    retain: Option<Value>,
}

impl Subscription {
    fn trigger_event(&mut self, events: &mut Vec<Event>) {
        let id = match check_named_variable(&self.lvar) {
            Some(id) => id,
            None => {
                error!("cannot obtain LVAR ID for variable {}", self.lvar);
                return;
            }
        };
        let val = Value::Number(get_named_variable_value(id) as isize);
        let must_trigger = self.retain.as_ref().map(|v| *v != val).unwrap_or(true);
        if must_trigger {
            let var = Var::Named(self.lvar.clone());
            let event = Event::new(self.device, "lvar", var, val);
            events.push(event);
            self.retain = Some(val);
        }
    }
}

fn check_named_variable(name: &str) -> Option<Id> {
    unsafe {
        let func = (*Panels).check_named_variable;
        let name = CString::new(name).unwrap();
        let id = (func)(name.as_ptr());
        if id != -1 { Some(id) } else { None }
    }
}

fn get_named_variable_value(id: Id) -> f64 {
    unsafe {
        let func = (*Panels).get_named_variable_value;
        (func)(id)
    }
}

fn set_named_variable_value(id: Id, value: f64) {
    unsafe {
        let func = (*Panels).set_named_variable_value;
        (func)(id, value)
    }
}
<commit_msg>Bug fixing: failed to write LVARs when sim is still launching<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

pub mod ffi;

use std::collections::VecDeque;
use std::ffi::CString;
use std::io;

use domain::*;
use types::*;

use self::ffi::*;

pub struct LVar {
    subscriptions: Vec<Subscription>,
    writes: VecDeque<WriteOp>,
}

impl LVar {
    pub fn new() -> LVar {
        LVar {
            subscriptions: Vec::new(),
            writes: VecDeque::with_capacity(32)
        }
    }

    fn poll_writes(&mut self) {
        let mut next_writes = VecDeque::with_capacity(32);
        loop {
            match self.writes.pop_front() {
                Some(op) => {
			        debug!("processing a write operation for {:?} <- {}", op.lvar, op.value);
                    match check_named_variable(&op.lvar) {
                        Some(id) => { set_named_variable_value(id, op.value); }
                        None => {
                            error!("there is no such lvar named {}", op.lvar);
                            next_writes.push_back(op);
                        }
                    }
                }
                None => break,
            }
        }
        self.writes = next_writes;
    }

    fn poll_events(&mut self, events: &mut Vec<Event>) -> io::Result<()> {
        for sub in self.subscriptions.iter_mut() {
            sub.trigger_event(events);
        }
        Ok(())
    }
}

impl Domain for LVar {
    fn write(&mut self, variable: &Var, value: &Value) -> io::Result<()> {
        debug!("queueing write operation for {:?} <- {}", variable, value);
        match variable {
            &Var::Named(ref lvar) => {
                let op = WriteOp {
                    lvar: lvar.clone(),
                    value: f64::from(value)
                };
                self.writes.push_back(op);
                Ok(())
            }
            _ => {
                let error = io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("lvar domain does not support variable {:?}", variable));
                Err(error)
            }
        }
    }

    fn subscribe(&mut self, device: DeviceId, variable: &Var) -> io::Result<()> {
        info!("receiving a subscription from device {} for {:?}", device, variable);
        match variable {
            &Var::Named(ref lvar) => {
                let subs = Subscription {
                    device: device,
                    lvar: lvar.clone(),
                    retain: None,
                };
                self.subscriptions.push(subs);
                Ok(())
            }
            _ => {
                let error = io::Error::new(
                    io::ErrorKind::InvalidInput,
                    format!("lvar domain does not support variable {:?}", variable));
                Err(error)
            }
        }
    }

    fn unsubscribe_all(&mut self, device: DeviceId) -> io::Result<()> {
        debug!("removing all subscriptions for device ID {}", device);
        self.subscriptions.retain(|s| s.device != device);
        Ok(())
    }

    fn poll(&mut self, events: &mut Vec<Event>) -> io::Result<()> {
        self.poll_writes();
        try!(self.poll_events(events));
        Ok(())
    }
}

struct Subscription {
    device: DeviceId,
    lvar: String,
    retain: Option<Value>,
}

impl Subscription {
    fn trigger_event(&mut self, events: &mut Vec<Event>) {
        let id = match check_named_variable(&self.lvar) {
            Some(id) => id,
            None => {
                error!("cannot obtain LVAR ID for variable {}", self.lvar);
                return;
            }
        };
        let val = Value::Number(get_named_variable_value(id) as isize);
        let must_trigger = self.retain.as_ref().map(|v| *v != val).unwrap_or(true);
        if must_trigger {
            let var = Var::Named(self.lvar.clone());
            let event = Event::new(self.device, "lvar", var, val);
            events.push(event);
            self.retain = Some(val);
        }
    }
}

struct WriteOp {
    lvar: String,
    value: f64,
}

fn check_named_variable(name: &str) -> Option<Id> {
    unsafe {
        let func = (*Panels).check_named_variable;
        let name = match CString::new(name) {
            Ok(raw) => raw,
            Err(e) => {
                error!("cannot convert {} to a valid C-like string: {:?}", name, e);
                return None;
            }
        };
        let id = (func)(name.as_ptr());
        if id != -1 { Some(id) } else { None }
    }
}

fn get_named_variable_value(id: Id) -> f64 {
    unsafe {
        let func = (*Panels).get_named_variable_value;
        (func)(id)
    }
}

fn set_named_variable_value(id: Id, value: f64) {
    unsafe {
        let func = (*Panels).set_named_variable_value;
        (func)(id, value)
    }
}
<|endoftext|>


<commit_before>use std::convert::TryInto;
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::ops::Deref;

use crate::backend::allocator::{Allocator, Buffer, Format};

pub const SLOT_CAP: usize = 3;

pub struct Swapchain<A: Allocator<B>, B: Buffer + TryInto<B>, D: Buffer = B> {
    allocator: A,
    _original_buffer_format: std::marker::PhantomData<B>,

    width: u32,
    height: u32,
    format: Format,

    slots: [Slot<D>; SLOT_CAP],
}

pub struct Slot<B: Buffer> {
    buffer: Arc<Option<B>>,
    acquired: Arc<AtomicBool>,
}

impl<B: Buffer> Default for Slot<B> {
    fn default() -> Self {
        Slot {
            buffer: Arc::new(None),
            acquired: Arc::new(AtomicBool::new(false)),
        }
    }
}

impl<B: Buffer> Clone for Slot<B> {
    fn clone(&self) -> Self {
        Slot {
            buffer: self.buffer.clone(),
            acquired: self.acquired.clone(),
        }
    }
}

impl<B: Buffer> Deref for Slot<B> {
    type Target = B;
    fn deref(&self) -> &B {
        Option::as_ref(&*self.buffer).unwrap()
    }
}

impl<B: Buffer> Drop for Slot<B> {
    fn drop(&mut self) {
        self.acquired.store(false, Ordering::AcqRel);
    }
}

#[derive(Debug, thiserror::Error)]
pub enum SwapchainError<E1, E2>
where
    E1: std::error::Error + 'static,
    E2: std::error::Error + 'static,
{
    #[error("Failed to allocate a new buffer: {0}")]
    AllocationError(#[source] E1),
    #[error("Failed to convert a new buffer: {0}")]
    ConversionError(#[source] E2),
}

impl<A, B, D, E1, E2> Swapchain<A, B, D>
where
    A: Allocator<B, Error=E1>,
    B: Buffer + TryInto<D, Error=E2>,
    D: Buffer,
    E1: std::error::Error + 'static,
    E2: std::error::Error + 'static,
{
    pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B, D> {
        Swapchain {
            allocator,
            _original_buffer_format: std::marker::PhantomData,
            width,
            height,
            format,
            slots: Default::default(),
        }
    }

    pub fn acquire(&mut self) -> Result<Option<Slot<D>>, SwapchainError<E1, E2>> {
        if let Some(free_slot) = self.slots.iter_mut().filter(|s| !s.acquired.load(Ordering::SeqCst)).next() {
            if free_slot.buffer.is_none() {
                free_slot.buffer = Arc::new(Some(
                    self.allocator
                    .create_buffer(self.width, self.height, self.format).map_err(SwapchainError::AllocationError)?
                    .try_into().map_err(SwapchainError::ConversionError)?
                ));
            }
            assert!(!free_slot.buffer.is_some());

            if !free_slot.acquired.swap(true, Ordering::AcqRel) {
                return Ok(Some(free_slot.clone()));
            }

        }

        // no free slots
        Ok(None)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        if self.width == width && self.height == height {
            return;
        }

        self.width = width;
        self.height = height;
        self.slots = Default::default();
    }
}<commit_msg>swapchain: increase cap for additional queuing (e.g. explicit synchronization)<commit_after>use std::convert::TryInto;
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::ops::Deref;

use crate::backend::allocator::{Allocator, Buffer, Format};

pub const SLOT_CAP: usize = 4;

pub struct Swapchain<A: Allocator<B>, B: Buffer + TryInto<B>, D: Buffer = B> {
    allocator: A,
    _original_buffer_format: std::marker::PhantomData<B>,

    width: u32,
    height: u32,
    format: Format,

    slots: [Slot<D>; SLOT_CAP],
}

pub struct Slot<B: Buffer> {
    buffer: Arc<Option<B>>,
    acquired: Arc<AtomicBool>,
}

impl<B: Buffer> Default for Slot<B> {
    fn default() -> Self {
        Slot {
            buffer: Arc::new(None),
            acquired: Arc::new(AtomicBool::new(false)),
        }
    }
}

impl<B: Buffer> Clone for Slot<B> {
    fn clone(&self) -> Self {
        Slot {
            buffer: self.buffer.clone(),
            acquired: self.acquired.clone(),
        }
    }
}

impl<B: Buffer> Deref for Slot<B> {
    type Target = B;
    fn deref(&self) -> &B {
        Option::as_ref(&*self.buffer).unwrap()
    }
}

impl<B: Buffer> Drop for Slot<B> {
    fn drop(&mut self) {
        self.acquired.store(false, Ordering::AcqRel);
    }
}

#[derive(Debug, thiserror::Error)]
pub enum SwapchainError<E1, E2>
where
    E1: std::error::Error + 'static,
    E2: std::error::Error + 'static,
{
    #[error("Failed to allocate a new buffer: {0}")]
    AllocationError(#[source] E1),
    #[error("Failed to convert a new buffer: {0}")]
    ConversionError(#[source] E2),
}

impl<A, B, D, E1, E2> Swapchain<A, B, D>
where
    A: Allocator<B, Error=E1>,
    B: Buffer + TryInto<D, Error=E2>,
    D: Buffer,
    E1: std::error::Error + 'static,
    E2: std::error::Error + 'static,
{
    pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B, D> {
        Swapchain {
            allocator,
            _original_buffer_format: std::marker::PhantomData,
            width,
            height,
            format,
            slots: Default::default(),
        }
    }

    pub fn acquire(&mut self) -> Result<Option<Slot<D>>, SwapchainError<E1, E2>> {
        if let Some(free_slot) = self.slots.iter_mut().filter(|s| !s.acquired.load(Ordering::SeqCst)).next() {
            if free_slot.buffer.is_none() {
                free_slot.buffer = Arc::new(Some(
                    self.allocator
                    .create_buffer(self.width, self.height, self.format).map_err(SwapchainError::AllocationError)?
                    .try_into().map_err(SwapchainError::ConversionError)?
                ));
            }
            assert!(!free_slot.buffer.is_some());

            if !free_slot.acquired.swap(true, Ordering::AcqRel) {
                return Ok(Some(free_slot.clone()));
            }

        }

        // no free slots
        Ok(None)
    }

    pub fn resize(&mut self, width: u32, height: u32) {
        if self.width == width && self.height == height {
            return;
        }

        self.width = width;
        self.height = height;
        self.slots = Default::default();
    }
}<|endoftext|>


<commit_before>import base::{ext_ctxt, mac_result, mr_expr, mr_def, expr_tt};
import codemap::span;
import ast::{ident, matcher_, matcher, match_tok,
             match_nonterminal, match_seq, tt_delim};
import parse::lexer::{new_tt_reader, reader};
import parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt};
import parse::parser::{parser, SOURCE_FILE};
import earley_parser::{parse, parse_or_else, success, failure, named_match,
                       matched_seq, matched_nonterminal, error};
import std::map::hashmap;

fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                     arg: ~[ast::token_tree]) -> base::mac_result {
    // these spans won't matter, anyways
    fn ms(m: matcher_) -> matcher {
        {node: m, span: {lo: 0u, hi: 0u, expn_info: none}}
    }

    // The grammar for macro_rules! is:
    // $( $lhs:mtcs => $rhs:tt );+
    // ...quasiquoting this would be nice.
    let argument_gram = ~[
        ms(match_seq(~[
            ms(match_nonterminal(@~"lhs",@~"matchers", 0u)),
            ms(match_tok(FAT_ARROW)),
            ms(match_nonterminal(@~"rhs",@~"tt", 1u)),
        ], some(SEMI), false, 0u, 2u)),
        //to phase into semicolon-termination instead of
        //semicolon-separation
        ms(match_seq(~[ms(match_tok(SEMI))], none, true, 2u, 2u))];

    // Parse the macro_rules! invocation (`none` is for no interpolations):
    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                   cx.parse_sess().interner, none, arg);
    let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(),
                                     arg_reader as reader, argument_gram);

    // Extract the arguments:
    let lhses:~[@named_match] = match argument_map.get(@~"lhs") {
      @matched_seq(s, sp) => s,
      _ => cx.span_bug(sp, ~"wrong-structured lhs")
    };
    let rhses:~[@named_match] = match argument_map.get(@~"rhs") {
      @matched_seq(s, sp) => s,
      _ => cx.span_bug(sp, ~"wrong-structured rhs")
    };

    // Given `lhses` and `rhses`, this is the new macro we create
    fn generic_extension(cx: ext_ctxt, sp: span, name: ident,
                         arg: ~[ast::token_tree],
                         lhses: ~[@named_match], rhses: ~[@named_match])
    -> mac_result {

        //io::println(fmt!("%s! { %s }", *name,
        //                 print::pprust::unexpanded_tt_to_str(
        //                     ast::tt_delim(arg),
        //                     cx.parse_sess().interner)));

        // Which arm's failure should we report? (the one furthest along)
        let mut best_fail_spot = {lo: 0u, hi: 0u, expn_info: none};
        let mut best_fail_msg = ~"internal error: ran no matchers";

        let s_d = cx.parse_sess().span_diagnostic;
        let itr = cx.parse_sess().interner;

        for lhses.eachi() |i, lhs| { // try each arm's matchers
            match lhs {
              @matched_nonterminal(nt_matchers(mtcs)) => {
                // `none` is because we're not interpolating
                let arg_rdr = new_tt_reader(s_d, itr, none, arg) as reader;
                match parse(cx.parse_sess(), cx.cfg(), arg_rdr, mtcs) {
                  success(named_matches) => {
                    let rhs = match rhses[i] {
                        // okay, what's your transcriber?
                      @matched_nonterminal(nt_tt(@tt)) => tt,
                      _ => cx.span_bug(sp, ~"bad thing in rhs")
                    };
                    // rhs has holes ( `$id` and `$(...)` that need filled)
                    let trncbr = new_tt_reader(s_d, itr, some(named_matches),
                                               ~[rhs]);
                    let p = parser(cx.parse_sess(), cx.cfg(),
                                   trncbr as reader, SOURCE_FILE);
                    let e = p.parse_expr();
                    return mr_expr(e);
                  }
                  failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
                    best_fail_spot = sp;
                    best_fail_msg = msg;
                  },
                  error(sp, msg) => cx.span_fatal(sp, msg)
                }
              }
              _ => cx.bug(~"non-matcher found in parsed lhses")
            }
        }
        cx.span_fatal(best_fail_spot, best_fail_msg);
    }

    let exp = |cx, sp, arg| generic_extension(cx, sp, name,
                                              arg, lhses, rhses);

    return mr_def({
        ident: name,
        ext: expr_tt({expander: exp, span: some(sp)})
    });
}<commit_msg>Silence unused-variable warning.<commit_after>import base::{ext_ctxt, mac_result, mr_expr, mr_def, expr_tt};
import codemap::span;
import ast::{ident, matcher_, matcher, match_tok,
             match_nonterminal, match_seq, tt_delim};
import parse::lexer::{new_tt_reader, reader};
import parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt};
import parse::parser::{parser, SOURCE_FILE};
import earley_parser::{parse, parse_or_else, success, failure, named_match,
                       matched_seq, matched_nonterminal, error};
import std::map::hashmap;

fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
                     arg: ~[ast::token_tree]) -> base::mac_result {
    // these spans won't matter, anyways
    fn ms(m: matcher_) -> matcher {
        {node: m, span: {lo: 0u, hi: 0u, expn_info: none}}
    }

    // The grammar for macro_rules! is:
    // $( $lhs:mtcs => $rhs:tt );+
    // ...quasiquoting this would be nice.
    let argument_gram = ~[
        ms(match_seq(~[
            ms(match_nonterminal(@~"lhs",@~"matchers", 0u)),
            ms(match_tok(FAT_ARROW)),
            ms(match_nonterminal(@~"rhs",@~"tt", 1u)),
        ], some(SEMI), false, 0u, 2u)),
        //to phase into semicolon-termination instead of
        //semicolon-separation
        ms(match_seq(~[ms(match_tok(SEMI))], none, true, 2u, 2u))];

    // Parse the macro_rules! invocation (`none` is for no interpolations):
    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
                                   cx.parse_sess().interner, none, arg);
    let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(),
                                     arg_reader as reader, argument_gram);

    // Extract the arguments:
    let lhses:~[@named_match] = match argument_map.get(@~"lhs") {
      @matched_seq(s, sp) => s,
      _ => cx.span_bug(sp, ~"wrong-structured lhs")
    };
    let rhses:~[@named_match] = match argument_map.get(@~"rhs") {
      @matched_seq(s, sp) => s,
      _ => cx.span_bug(sp, ~"wrong-structured rhs")
    };

    // Given `lhses` and `rhses`, this is the new macro we create
    fn generic_extension(cx: ext_ctxt, sp: span, _name: ident,
                         arg: ~[ast::token_tree],
                         lhses: ~[@named_match], rhses: ~[@named_match])
    -> mac_result {

        //io::println(fmt!("%s! { %s }", *name,
        //                 print::pprust::unexpanded_tt_to_str(
        //                     ast::tt_delim(arg),
        //                     cx.parse_sess().interner)));

        // Which arm's failure should we report? (the one furthest along)
        let mut best_fail_spot = {lo: 0u, hi: 0u, expn_info: none};
        let mut best_fail_msg = ~"internal error: ran no matchers";

        let s_d = cx.parse_sess().span_diagnostic;
        let itr = cx.parse_sess().interner;

        for lhses.eachi() |i, lhs| { // try each arm's matchers
            match lhs {
              @matched_nonterminal(nt_matchers(mtcs)) => {
                // `none` is because we're not interpolating
                let arg_rdr = new_tt_reader(s_d, itr, none, arg) as reader;
                match parse(cx.parse_sess(), cx.cfg(), arg_rdr, mtcs) {
                  success(named_matches) => {
                    let rhs = match rhses[i] {
                        // okay, what's your transcriber?
                      @matched_nonterminal(nt_tt(@tt)) => tt,
                      _ => cx.span_bug(sp, ~"bad thing in rhs")
                    };
                    // rhs has holes ( `$id` and `$(...)` that need filled)
                    let trncbr = new_tt_reader(s_d, itr, some(named_matches),
                                               ~[rhs]);
                    let p = parser(cx.parse_sess(), cx.cfg(),
                                   trncbr as reader, SOURCE_FILE);
                    let e = p.parse_expr();
                    return mr_expr(e);
                  }
                  failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
                    best_fail_spot = sp;
                    best_fail_msg = msg;
                  },
                  error(sp, msg) => cx.span_fatal(sp, msg)
                }
              }
              _ => cx.bug(~"non-matcher found in parsed lhses")
            }
        }
        cx.span_fatal(best_fail_spot, best_fail_msg);
    }

    let exp = |cx, sp, arg| generic_extension(cx, sp, name,
                                              arg, lhses, rhses);

    return mr_def({
        ident: name,
        ext: expr_tt({expander: exp, span: some(sp)})
    });
}<|endoftext|>


<commit_before>// Copyright 2014 Rich Lane.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let base_height = 15.0;
                let base_variance = 10.0;
                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ) as int,
                    1, CHUNK_SIZE - 1);

                for y in range(0, height) {
                    let block = t.get_mut(block_x, y, block_z);

                    let dirt_height = (4.0 + noise2 * 8.0) as int;
                    if (height <= 20) && (y + dirt_height >= height) {
                        if y < height - 2 {
                            block.blocktype = BlockDirt;
                        } else {
                            block.blocktype = BlockGrass;
                        }
                    } else {
                        block.blocktype = BlockStone;
                    }
                }

                let water_height = 10;
                for y in range(height, water_height) {
                    let block = t.get_mut(block_x, y, block_z);
                    block.blocktype = BlockWater;
                }

                for block_y in std::iter::range(0, CHUNK_SIZE) {
                    let block = t.get_mut(block_x, block_y, block_z);

                    if (p.y + block_y as f64) <= 1.0 ||
                       block.blocktype == BlockAir {
                        continue;
                    }

                    let cave = perlin1.gen([
                        (p.x + block_x as f64) * 0.05,
                        (p.y + block_y as f64) * 0.1,
                        (p.z + block_z as f64) * 0.05]);

                    if cave > 0.5 {
                        block.blocktype = BlockAir;
                    }
                }

            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> Option<&'a Block> {
        if x < -1 || x >= CHUNK_SIZE+1 || y < -1 || y >= CHUNK_SIZE+1 || z < -1 || z >= CHUNK_SIZE+1 {
            None
        } else {
            Some(&self.blocks[x+1][y+1][z+1])
        }
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }

}
<commit_msg>terrain: generate all neighbor blocks<commit_after>// Copyright 2014 Rich Lane.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern mod extra;
extern mod cgmath;
extern mod noise;

use std;
use std::num::clamp;

use extra::time::precise_time_ns;

use cgmath::vector::Vec3;

use noise::Perlin;

use CHUNK_SIZE;

#[repr(u8)]
#[deriving(Eq)]
pub enum BlockType {
    BlockAir = 0,
    BlockGrass = 1,
    BlockStone = 2,
    BlockDirt = 3,
    BlockWater = 4,
}

pub struct Block {
    blocktype: BlockType,
}

impl Block {
    pub fn is_opaque(&self) -> bool {
        self.blocktype != BlockAir
    }
}

pub struct Terrain {
    priv blocks: [[[Block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
}

impl Terrain {
    pub fn gen(seed: u32, p: Vec3<f64>) -> ~Terrain {
        let def_block = Block { blocktype: BlockAir };
        let mut t = ~Terrain {
            blocks: [[[def_block, ..CHUNK_SIZE+2], ..CHUNK_SIZE+2], ..CHUNK_SIZE+2],
        };

        let start_time = precise_time_ns();

        let perlin1 = Perlin::from_seed([seed as uint]);
        let perlin2 = Perlin::from_seed([seed as uint * 7]);
        let perlin3 = Perlin::from_seed([seed as uint * 13]);
        let perlin4 = Perlin::from_seed([seed as uint * 17]);

        for block_x in std::iter::range(-1, CHUNK_SIZE+1) {
            for block_z in std::iter::range(-1, CHUNK_SIZE+1) {
                let noise1 = perlin1.gen([
                    (p.x + block_x as f64) * 0.07,
                    (p.z + block_z as f64) * 0.04
                ]);
                let noise2 = perlin2.gen([
                    (p.x + block_x as f64) * 0.05,
                    (p.z + block_z as f64) * 0.05
                ]);
                let noise3 = perlin3.gen([
                    (p.x + block_x as f64) * 0.005,
                    (p.z + block_z as f64) * 0.005
                ]);
                let noise4 = perlin4.gen([
                    (p.x + block_x as f64) * 0.001,
                    (p.z + block_z as f64) * 0.001
                ]);

                let base_height = 15.0;
                let base_variance = 10.0;
                let height = clamp(
                    (
                        base_height +
                        noise4 * 10.0 +
                        base_variance *
                            std::num::pow(noise3 + 1.0, 2.5) *
                            noise1
                    ) as int,
                    1, CHUNK_SIZE - 1);

                for y in range(-1, height) {
                    let block = t.get_mut(block_x, y, block_z);

                    let dirt_height = (4.0 + noise2 * 8.0) as int;
                    if (height <= 20) && (y + dirt_height >= height) {
                        if y < height - 2 {
                            block.blocktype = BlockDirt;
                        } else {
                            block.blocktype = BlockGrass;
                        }
                    } else {
                        block.blocktype = BlockStone;
                    }
                }

                let water_height = 10;
                for y in range(height, water_height) {
                    let block = t.get_mut(block_x, y, block_z);
                    block.blocktype = BlockWater;
                }

                for block_y in std::iter::range(-1, CHUNK_SIZE+1) {
                    let block = t.get_mut(block_x, block_y, block_z);

                    if (p.y + block_y as f64) <= 1.0 ||
                       block.blocktype == BlockAir {
                        continue;
                    }

                    let cave = perlin1.gen([
                        (p.x + block_x as f64) * 0.05,
                        (p.y + block_y as f64) * 0.1,
                        (p.z + block_z as f64) * 0.05]);

                    if cave > 0.5 {
                        block.blocktype = BlockAir;
                    }
                }

            }
        }

        let end_time = precise_time_ns();

        println!("terrain gen : {}us",
                (end_time - start_time)/1000);

        return t;
    }

    pub fn get<'a>(&'a self, x: int, y: int, z: int) -> Option<&'a Block> {
        if x < -1 || x >= CHUNK_SIZE+1 || y < -1 || y >= CHUNK_SIZE+1 || z < -1 || z >= CHUNK_SIZE+1 {
            None
        } else {
            Some(&self.blocks[x+1][y+1][z+1])
        }
    }

    pub fn get_mut<'a>(&'a mut self, x: int, y: int, z: int) -> &'a mut Block {
        &mut self.blocks[x+1][y+1][z+1]
    }

}
<|endoftext|>