<commit_before>// 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/.

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate loopdev;
extern crate tempdir;

mod util;

use std::fs::OpenOptions;
use std::io::{Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};

use loopdev::{LoopControl, LoopDevice};
use tempdir::TempDir;

use devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::blockdev_tests::test_blockdevmgr_used;
use util::blockdev_tests::test_force_flag_dirty;
use util::blockdev_tests::test_force_flag_stratis;
use util::blockdev_tests::test_pool_blockdevs;
use util::dm_tests::test_thinpool_device;
use util::dm_tests::test_linear_device;
use util::filesystem_tests::test_xfs_expand;
use util::pool_tests::test_filesystem_rename;
use util::pool_tests::test_thinpool_expand;
use util::pool_tests::test_thinpool_thindev_destroy;
use util::setup_tests::test_basic_metadata;
use util::setup_tests::test_initialize;
use util::setup_tests::test_pool_rename;
use util::setup_tests::test_pool_setup;
use util::setup_tests::test_setup;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_teardown;

pub struct LoopTestDev {
    ld: LoopDevice,
}

impl LoopTestDev {
    pub fn new(lc: &LoopControl, path: &Path) -> LoopTestDev {
        OpenOptions::new()
            .read(true)
            .write(true)
            .open(path)
            .unwrap();

        let ld = lc.next_free().unwrap();
        ld.attach(path, 0).unwrap();
        // Wipe 1 MiB at the beginning, as data sits around on the files.
        wipe_sectors(&ld.get_path().unwrap(),
                     Sectors(0),
                     Bytes(IEC::Mi).sectors())
                .unwrap();

        LoopTestDev { ld: ld }
    }

    fn get_path(&self) -> PathBuf {
        self.ld.get_path().unwrap()
    }

    pub fn detach(&self) {
        self.ld.detach().unwrap()
    }
}

impl Drop for LoopTestDev {
    fn drop(&mut self) {
        self.detach()
    }
}

/// Setup count loop backed devices in dir.
/// Make sure each loop device is backed by a 1 GiB file.
/// Wipe the first 1 MiB of the file.
fn get_devices(count: u8, dir: &TempDir) -> Vec<LoopTestDev> {
    let lc = LoopControl::open().unwrap();
    let mut loop_devices = Vec::new();

    for index in 0..count {
        let path = dir.path().join(format!("store{}", &index));
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();

        // the proper way to do this is fallocate, but nix doesn't implement yet.
        // TODO: see https://github.com/nix-rust/nix/issues/596
        f.seek(SeekFrom::Start(IEC::Gi)).unwrap();
        f.write(&[0]).unwrap();
        f.flush().unwrap();

        let ltd = LoopTestDev::new(&lc, &path);

        loop_devices.push(ltd);
    }
    loop_devices
}

/// Set up count loopbacked devices.
/// Then, run the designated test.
/// Then, take down the loop devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let tmpdir = TempDir::new("stratis").unwrap();
    let loop_devices: Vec<LoopTestDev> = get_devices(count, &tmpdir);
    let device_paths: Vec<PathBuf> = loop_devices.iter().map(|x| x.get_path()).collect();
    let device_paths: Vec<&Path> = device_paths.iter().map(|x| x.as_path()).collect();

    test(&device_paths);

}

#[test]
pub fn loop_test_force_flag_stratis() {
    test_with_spec(1, test_force_flag_stratis);
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn loop_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn loop_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn loop_test_thinpool_expand() {
    test_with_spec(3, test_thinpool_expand);
}

#[test]
pub fn loop_test_thinpool_thindev_destroy() {
    test_with_spec(3, test_thinpool_thindev_destroy);
}

#[test]
pub fn loop_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn loop_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn loop_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn loop_test_initialize() {
    test_with_spec(4, test_initialize);
}

#[test]
pub fn loop_test_empty_pool() {
    test_with_spec(0, test_empty_pool);
}

#[test]
pub fn loop_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}

#[test]
pub fn loop_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn loop_test_pool_rename() {
    test_with_spec(2, test_pool_rename);
}

#[test]
pub fn loop_test_blockdevmgr_used() {
    test_with_spec(2, test_blockdevmgr_used);
}

#[test]
pub fn loop_test_filesystem_rename() {
    test_with_spec(2, test_filesystem_rename);
}

#[test]
pub fn loop_test_pool_setup() {
    test_with_spec(2, test_pool_setup);
}

#[test]
pub fn loop_test_xfs_expand() {
    test_with_spec(3, test_xfs_expand);
}
<commit_msg>Move the maintenance of the backing store into new()<commit_after>// 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/.

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate loopdev;
extern crate tempdir;

mod util;

use std::fs::OpenOptions;
use std::io::{Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};

use loopdev::{LoopControl, LoopDevice};
use tempdir::TempDir;

use devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::blockdev_tests::test_blockdevmgr_used;
use util::blockdev_tests::test_force_flag_dirty;
use util::blockdev_tests::test_force_flag_stratis;
use util::blockdev_tests::test_pool_blockdevs;
use util::dm_tests::test_thinpool_device;
use util::dm_tests::test_linear_device;
use util::filesystem_tests::test_xfs_expand;
use util::pool_tests::test_filesystem_rename;
use util::pool_tests::test_thinpool_expand;
use util::pool_tests::test_thinpool_thindev_destroy;
use util::setup_tests::test_basic_metadata;
use util::setup_tests::test_initialize;
use util::setup_tests::test_pool_rename;
use util::setup_tests::test_pool_setup;
use util::setup_tests::test_setup;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_teardown;

pub struct LoopTestDev {
    ld: LoopDevice,
}

impl LoopTestDev {
    pub fn new(lc: &LoopControl, path: &Path) -> LoopTestDev {
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)
            .unwrap();

        // the proper way to do this is fallocate, but nix doesn't implement yet.
        // TODO: see https://github.com/nix-rust/nix/issues/596
        f.seek(SeekFrom::Start(IEC::Gi)).unwrap();
        f.write(&[0]).unwrap();
        f.flush().unwrap();

        let ld = lc.next_free().unwrap();
        ld.attach(path, 0).unwrap();
        // Wipe 1 MiB at the beginning, as data sits around on the files.
        wipe_sectors(&ld.get_path().unwrap(),
                     Sectors(0),
                     Bytes(IEC::Mi).sectors())
                .unwrap();

        LoopTestDev { ld: ld }
    }

    fn get_path(&self) -> PathBuf {
        self.ld.get_path().unwrap()
    }

    pub fn detach(&self) {
        self.ld.detach().unwrap()
    }
}

impl Drop for LoopTestDev {
    fn drop(&mut self) {
        self.detach()
    }
}

/// Setup count loop backed devices in dir.
/// Make sure each loop device is backed by a 1 GiB file.
/// Wipe the first 1 MiB of the file.
fn get_devices(count: u8, dir: &TempDir) -> Vec<LoopTestDev> {
    let lc = LoopControl::open().unwrap();
    let mut loop_devices = Vec::new();

    for index in 0..count {
        let path = dir.path().join(format!("store{}", &index));
        loop_devices.push(LoopTestDev::new(&lc, &path));
    }
    loop_devices
}

/// Set up count loopbacked devices.
/// Then, run the designated test.
/// Then, take down the loop devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let tmpdir = TempDir::new("stratis").unwrap();
    let loop_devices: Vec<LoopTestDev> = get_devices(count, &tmpdir);
    let device_paths: Vec<PathBuf> = loop_devices.iter().map(|x| x.get_path()).collect();
    let device_paths: Vec<&Path> = device_paths.iter().map(|x| x.as_path()).collect();

    test(&device_paths);

}

#[test]
pub fn loop_test_force_flag_stratis() {
    test_with_spec(1, test_force_flag_stratis);
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn loop_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn loop_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn loop_test_thinpool_expand() {
    test_with_spec(3, test_thinpool_expand);
}

#[test]
pub fn loop_test_thinpool_thindev_destroy() {
    test_with_spec(3, test_thinpool_thindev_destroy);
}

#[test]
pub fn loop_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn loop_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn loop_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn loop_test_initialize() {
    test_with_spec(4, test_initialize);
}

#[test]
pub fn loop_test_empty_pool() {
    test_with_spec(0, test_empty_pool);
}

#[test]
pub fn loop_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}

#[test]
pub fn loop_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn loop_test_pool_rename() {
    test_with_spec(2, test_pool_rename);
}

#[test]
pub fn loop_test_blockdevmgr_used() {
    test_with_spec(2, test_blockdevmgr_used);
}

#[test]
pub fn loop_test_filesystem_rename() {
    test_with_spec(2, test_filesystem_rename);
}

#[test]
pub fn loop_test_pool_setup() {
    test_with_spec(2, test_pool_setup);
}

#[test]
pub fn loop_test_xfs_expand() {
    test_with_spec(3, test_xfs_expand);
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/FASTA_format
// Fasta reader in Rust 0.11-pre
// Ported and adapted from rosettacode D example

use std::path::Path;
use std::io::fs::File;
use std::io::BufferedReader;
use std::string::String;

// Best to use type parameter <T: Buffer> to accept all kinds of buffers
fn format_fasta<T: Buffer>(reader: &mut T) -> String {
    let mut result = String::new();

    for line in reader.lines() {
        // Using the same name for the next variable will just shadow the previous one
        let ln = line.unwrap();

        // We need to trim new lines
        let ln = ln.as_slice().trim();

        // Lines that begin with '>' require special treatment
        if ln.slice(0,1) == ">" {
            if result.len() > 0 {
                result.push_char('\n');
            }

            // Push skipping the '>'
            result.push_str(ln.slice_from(1));
            result.push_str(": ");
        } else {
            // Other lines are just pushed
            result.push_str(ln);
        }
    }

    result
}

fn read_file() -> String {
    let file = File::open(&Path::new("src/resources/test_data.fasta"));
    format_fasta(&mut BufferedReader::new(file))
}

#[cfg(not(test))]
fn main() {
    let s = read_file();
    println!("{}", s);
}

#[test]
fn test_format_fasta() {
    let s = read_file();
    assert_eq!(s.as_slice(), "Rosetta_Example_1: THERECANBENOSPACE
Rosetta_Example_2: THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED");
}
<commit_msg>fasta: Simplify<commit_after>// http://rosettacode.org/wiki/FASTA_format
// Fasta reader in Rust 0.11-pre
// Ported and adapted from rosettacode D example

use std::io::fs::File;
use std::io::BufferedReader;

// We use a type parameter bound `<T: Buffer>` to accept all kinds of buffers
fn format_fasta<T: Buffer>(reader: &mut T) -> String {
    reader.lines().map(|l| l.unwrap()).fold(String::new(), |mut out, line| {
        // We need to trim new lines
        let ln = line.as_slice().trim();

        // Lines that begin with '>' require special treatment
        match ln.slice_to(1) {
            ">" => {
                if out.len() > 0 {
                    out.push_char('\n');
                }

                // Push skipping the '>'
                out.append(ln.slice_from(1))
                   .append(": ")
            }
            // Other lines are just pushed
            _ => out.append(ln)
        }
    })
}

fn read_file() -> String {
    let file = File::open(&Path::new("src/resources/test_data.fasta"));
    format_fasta(&mut BufferedReader::new(file))
}

#[cfg(not(test))]
fn main() {
    let s = read_file();
    println!("{}", s);
}

#[test]
fn test_format_fasta() {
    let s = read_file();
    assert_eq!(s.as_slice(), "Rosetta_Example_1: THERECANBENOSPACE
Rosetta_Example_2: THERECANBESEVERALLINESBUTTHEYALLMUSTBECONCATENATED");
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use perlin_core::index::Index;

pub type Field<T> = Index<T>;

pub type FacetField<T> = Index<Arc<T>>;
<commit_msg>impl PipelineBucket for Field<commit_after>use std::sync::Arc;
use std::hash::Hash;

use perlin_core::index::Index;
use perlin_core::index::posting::DocId;

use language::PipelineBucket;

pub type Field<T> = Index<T>;

pub type FacetField<T> = Index<Arc<T>>;

impl<TTerm> PipelineBucket<TTerm> for Field<TTerm>
    where TTerm: Hash + Eq + Ord
{
    fn put(&mut self, doc_id: DocId, term: TTerm) {
        self.index_term(doc_id, term)
    }
}
<|endoftext|>


<commit_before>//! An optional path based text engine is provided that allows you to create
//! fonts and manage text labels that are based on paths. That way the
//! underlying renderer doesn't by itself need to be able to render text, as all
//! the text gets turned into paths.

use std::{fs, sync::Arc};

#[cfg(feature = "font-loading")]
use font_kit::{
    family_name::FamilyName,
    handle::Handle,
    properties::{Properties, Stretch, Style, Weight},
    source::SystemSource,
};
use hashbrown::HashMap;
use parking_lot::{const_rwlock, RwLock};
use rustybuzz::{Face, Feature, Tag, UnicodeBuffer, Variation};
use ttf_parser::{GlyphId, OutlineBuilder};

use super::{
    font::{TEXT_FONT, TIMER_FONT},
    FontKind, PathBuilder, Rgba, SharedOwnership,
};
use crate::settings::{self, FontStretch, FontStyle, FontWeight};

use self::color_font::{iter_colored_glyphs, ColorTables};

mod color_font;

/// The path based text engine allows you to create fonts and manage text labels
/// that are based on paths. That way the underlying renderer doesn't by itself
/// need to be able to render text, as all the text gets turned into paths.
pub struct TextEngine {
    #[cfg(feature = "font-loading")]
    source: SystemSource,
    buffer: Option<UnicodeBuffer>,
}

impl Default for TextEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl TextEngine {
    /// Creates a new path based text engine.
    pub fn new() -> Self {
        Self {
            #[cfg(feature = "font-loading")]
            source: SystemSource::new(),
            buffer: None,
        }
    }

    /// Creates a new font. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn create_font<P>(&mut self, font: Option<&settings::Font>, kind: FontKind) -> Font<P> {
        #[cfg(feature = "font-loading")]
        if let Some(font) = font {
            if let Some(font) = Font::try_load_font(&mut self.source, font, kind) {
                return font;
            }
        }
        let (font_data, style, weight, stretch) = match kind {
            FontKind::Timer => (
                TIMER_FONT,
                FontStyle::Normal,
                FontWeight::Bold,
                FontStretch::Normal,
            ),
            FontKind::Times => (
                TEXT_FONT,
                FontStyle::Normal,
                FontWeight::Bold,
                FontStretch::Normal,
            ),
            FontKind::Text => (
                TEXT_FONT,
                FontStyle::Normal,
                FontWeight::Normal,
                FontStretch::Normal,
            ),
        };
        Font::from_slice(font_data, 0, style, weight, stretch, kind).unwrap()
    }

    /// Creates a new text label. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn create_label<PB: PathBuilder>(
        &mut self,
        path_builder: impl FnMut() -> PB,
        text: &str,
        font: &mut Font<PB::Path>,
        max_width: Option<f32>,
    ) -> Label<PB::Path> {
        let mut label = Arc::new(const_rwlock(LockedLabel {
            width: 0.0,
            width_without_max_width: 0.0,
            scale: 0.0,
            glyphs: Vec::new(),
        }));

        self.update_label(path_builder, &mut label, text, font, max_width);

        label
    }

    /// Updates a text label. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn update_label<PB: PathBuilder>(
        &mut self,
        mut path_builder: impl FnMut() -> PB,
        label: &mut Label<PB::Path>,
        text: &str,
        font: &mut Font<PB::Path>,
        max_width: Option<f32>,
    ) {
        let mut label = label.write();
        let label = &mut *label;

        let mut buffer = self.buffer.take().unwrap_or_else(UnicodeBuffer::new);
        buffer.push_str(text);

        let features = font
            .monotonic
            .as_ref()
            .map(|m| &m.features[..])
            .unwrap_or_default();

        let buffer = rustybuzz::shape(&font.face, features, buffer);

        let iter = Iterator::zip(buffer.glyph_infos().iter(), buffer.glyph_positions().iter());

        let (mut x, mut y) = (0.0, 0.0);

        label.glyphs.clear();

        if let Some(monotonic) = &font.monotonic {
            iter.for_each(|(info, pos)| {
                let glyph = GlyphId(info.glyph_id as _);
                let layer_glyphs = font.glyph_cache.entry(glyph).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, glyph, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                let (x_advance, x_offset) =
                    if monotonic.digit_glyphs.contains(&(info.glyph_id as u16)) {
                        (
                            monotonic.digit_width,
                            0.5 * (monotonic.digit_width - pos.x_advance as f32)
                                + pos.x_offset as f32,
                        )
                    } else {
                        (pos.x_advance as f32, pos.x_offset as f32)
                    };
                let (glyph_x, glyph_y) = (x + x_offset, y + pos.y_offset as f32);
                x += x_advance;
                y += pos.y_advance as f32;
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x: glyph_x,
                        y: glyph_y,
                        path: path.share(),
                    }));
            });
        } else {
            iter.for_each(|(info, pos)| {
                let glyph = GlyphId(info.glyph_id as _);
                let layer_glyphs = font.glyph_cache.entry(glyph).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, glyph, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                let (glyph_x, glyph_y) = (x + pos.x_offset as f32, y + pos.y_offset as f32);
                x += pos.x_advance as f32;
                y += pos.y_advance as f32;
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x: glyph_x,
                        y: glyph_y,
                        path: path.share(),
                    }));
            });
        };

        label.width_without_max_width = x * font.scale_factor;

        if let Some(max_width) = max_width {
            let max_width = max_width / font.scale_factor;
            if x > max_width {
                let ellipsis = font.face.glyph_index('…').unwrap_or_default();
                let ellipsis_width =
                    font.face.glyph_hor_advance(ellipsis).unwrap_or_default() as f32;

                let x_to_look_for = max_width - ellipsis_width;

                let last_index = label
                    .glyphs
                    .iter()
                    .enumerate()
                    .rev()
                    .find(|(_, g)| {
                        x = g.x;
                        y = g.y;
                        g.x <= x_to_look_for
                    })
                    .map(|(i, _)| i)
                    .unwrap_or_default();
                label.glyphs.drain(last_index..);
                let layer_glyphs = font.glyph_cache.entry(ellipsis).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, ellipsis, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x,
                        y,
                        path: path.share(),
                    }));
                x += ellipsis_width;
            }
        }

        self.buffer = Some(buffer.clear());

        label.width = x * font.scale_factor;
        label.scale = font.scale_factor;
    }
}

struct MonotonicInfo {
    digit_glyphs: [u16; 10],
    digit_width: f32,
    features: [Feature; 1],
}

/// The font to use in the [`ResourceAllocator`](super::ResourceAllocator).
pub struct Font<P> {
    face: Face<'static>,
    color_tables: Option<ColorTables<'static>>,
    scale_factor: f32,
    monotonic: Option<MonotonicInfo>,
    glyph_cache: HashMap<GlyphId, Vec<(Option<Rgba>, P)>>,
    #[cfg(feature = "font-loading")]
    _buf: Option<Box<[u8]>>,
}

impl<P> Font<P> {
    #[cfg(feature = "font-loading")]
    fn try_load_font(
        source: &mut SystemSource,
        font: &settings::Font,
        kind: FontKind,
    ) -> Option<Self> {
        let handle = source
            .select_best_match(
                &[FamilyName::Title(font.family.clone())],
                &Properties {
                    style: match font.style {
                        FontStyle::Normal => Style::Normal,
                        FontStyle::Italic => Style::Italic,
                    },
                    weight: Weight(font.weight.value()),
                    stretch: Stretch(font.stretch.factor()),
                },
            )
            .ok()?;

        let (buf, font_index) = match handle {
            Handle::Path { path, font_index } => (fs::read(path).ok()?, font_index),
            Handle::Memory { bytes, font_index } => (
                Arc::try_unwrap(bytes).unwrap_or_else(|bytes| (*bytes).clone()),
                font_index,
            ),
        };
        let buf = buf.into_boxed_slice();

        // Safety: We store our own buffer. If we never modify it and drop it
        // last, this is fine. It also needs to be heap allocated, so it's a
        // stable pointer. This is guaranteed by the boxed slice.
        unsafe {
            let slice: *const [u8] = &*buf;
            let mut font = Font::from_slice(
                &*slice,
                font_index,
                font.style,
                font.weight,
                font.stretch,
                kind,
            )?;
            font._buf = Some(buf);
            Some(font)
        }
    }

    fn from_slice(
        data: &'static [u8],
        index: u32,
        style: FontStyle,
        weight: FontWeight,
        stretch: FontStretch,
        kind: FontKind,
    ) -> Option<Self> {
        let mut face = Face::from_slice(data, index)?;

        let italic = style.value_for_italic();
        let weight = weight.value();
        let stretch = stretch.percentage();

        face.set_variations(&[
            Variation {
                tag: Tag::from_bytes(b"ital"),
                value: italic,
            },
            Variation {
                tag: Tag::from_bytes(b"wght"),
                value: weight,
            },
            Variation {
                tag: Tag::from_bytes(b"wdth"),
                value: stretch,
            },
        ]);

        let monotonic = kind.is_monospaced().then(|| {
            let mut digit_glyphs = [0; 10];
            let mut digit_width = 0;
            for (digit, glyph) in digit_glyphs.iter_mut().enumerate() {
                *glyph = face
                    .glyph_index(char::from(digit as u8 + b'0'))
                    .unwrap_or_default()
                    .0;

                let width = face.glyph_hor_advance(GlyphId(*glyph)).unwrap_or_default();
                if width > digit_width {
                    digit_width = width;
                }
            }
            MonotonicInfo {
                digit_glyphs,
                digit_width: digit_width as f32,
                features: [
                    // If the font has support for tabular numbers, we want to
                    // use it, so we don't have to fix up much. Though we still
                    // attempt to do so anyway, as we can neither query if tnum
                    // support is even available, nor can we really trust it all
                    // too much.
                    Feature::new(Tag::from_bytes(b"tnum"), 1, ..),
                    // FIXME: We may or may not want to disable kerning and
                    // possibly ligatures too. If the font doesn't support tnum,
                    // then kerning for e.g. `.1` may cause inconsistent
                    // positioning.
                    // Feature::new(Tag::from_bytes(b"kern"), 0, ..),
                ],
            }
        });

        Some(Self {
            scale_factor: 1.0 / face.height() as f32,
            color_tables: ColorTables::new(&face),
            face,
            #[cfg(feature = "font-loading")]
            _buf: None,
            monotonic,
            glyph_cache: HashMap::new(),
        })
    }
}

struct GlyphBuilder<PB>(PB);

impl<PB: PathBuilder> OutlineBuilder for GlyphBuilder<PB> {
    fn move_to(&mut self, x: f32, y: f32) {
        self.0.move_to(x, -y);
    }
    fn line_to(&mut self, x: f32, y: f32) {
        self.0.line_to(x, -y);
    }
    fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
        self.0.quad_to(x1, -y1, x, -y);
    }
    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
        self.0.curve_to(x1, -y1, x2, -y2, x, -y);
    }
    fn close(&mut self) {
        self.0.close();
    }
}

/// The label to use in the [`ResourceAllocator`](super::ResourceAllocator).
pub type Label<P> = Arc<RwLock<LockedLabel<P>>>;

/// You need to lock the [`Label`] to use it. This is the locked type that
/// provides all the methods you need to use the label.
pub struct LockedLabel<P> {
    width: f32,
    width_without_max_width: f32,
    scale: f32,
    glyphs: Vec<Glyph<P>>,
}

impl<P> LockedLabel<P> {
    /// Apply this scale to the transform of the [`Entity`](super::Entity) with
    /// [`Transform::pre_scale`](super::Transform::pre_scale).
    pub const fn scale(&self) -> f32 {
        self.scale
    }

    /// The glyphs to render.
    pub fn glyphs(&self) -> &[Glyph<P>] {
        &self.glyphs
    }
}

impl<P> super::Label for Label<P> {
    fn width(&self, scale: f32) -> f32 {
        self.read().width * scale
    }

    fn width_without_max_width(&self, scale: f32) -> f32 {
        self.read().width_without_max_width * scale
    }
}

/// A glyph to render.
pub struct Glyph<P> {
    /// A glyph may provide its own color that overrides the fill shader of the
    /// [`Entity`](super::Entity).
    pub color: Option<Rgba>,
    /// The x-coordinate of the glyph.
    pub x: f32,
    /// The y-coordinate of the glyph.
    pub y: f32,
    /// The path to render.
    pub path: P,
}
<commit_msg>Remember ellipsis width<commit_after>//! An optional path based text engine is provided that allows you to create
//! fonts and manage text labels that are based on paths. That way the
//! underlying renderer doesn't by itself need to be able to render text, as all
//! the text gets turned into paths.

use std::{fs, sync::Arc};

#[cfg(feature = "font-loading")]
use font_kit::{
    family_name::FamilyName,
    handle::Handle,
    properties::{Properties, Stretch, Style, Weight},
    source::SystemSource,
};
use hashbrown::HashMap;
use parking_lot::{const_rwlock, RwLock};
use rustybuzz::{Face, Feature, Tag, UnicodeBuffer, Variation};
use ttf_parser::{GlyphId, OutlineBuilder};

use super::{
    font::{TEXT_FONT, TIMER_FONT},
    FontKind, PathBuilder, Rgba, SharedOwnership,
};
use crate::settings::{self, FontStretch, FontStyle, FontWeight};

use self::color_font::{iter_colored_glyphs, ColorTables};

mod color_font;

/// The path based text engine allows you to create fonts and manage text labels
/// that are based on paths. That way the underlying renderer doesn't by itself
/// need to be able to render text, as all the text gets turned into paths.
pub struct TextEngine {
    #[cfg(feature = "font-loading")]
    source: SystemSource,
    buffer: Option<UnicodeBuffer>,
}

impl Default for TextEngine {
    fn default() -> Self {
        Self::new()
    }
}

impl TextEngine {
    /// Creates a new path based text engine.
    pub fn new() -> Self {
        Self {
            #[cfg(feature = "font-loading")]
            source: SystemSource::new(),
            buffer: None,
        }
    }

    /// Creates a new font. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn create_font<P>(&mut self, font: Option<&settings::Font>, kind: FontKind) -> Font<P> {
        #[cfg(feature = "font-loading")]
        if let Some(font) = font {
            if let Some(font) = Font::try_load_font(&mut self.source, font, kind) {
                return font;
            }
        }
        let (font_data, style, weight, stretch) = match kind {
            FontKind::Timer => (
                TIMER_FONT,
                FontStyle::Normal,
                FontWeight::Bold,
                FontStretch::Normal,
            ),
            FontKind::Times => (
                TEXT_FONT,
                FontStyle::Normal,
                FontWeight::Bold,
                FontStretch::Normal,
            ),
            FontKind::Text => (
                TEXT_FONT,
                FontStyle::Normal,
                FontWeight::Normal,
                FontStretch::Normal,
            ),
        };
        Font::from_slice(font_data, 0, style, weight, stretch, kind).unwrap()
    }

    /// Creates a new text label. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn create_label<PB: PathBuilder>(
        &mut self,
        path_builder: impl FnMut() -> PB,
        text: &str,
        font: &mut Font<PB::Path>,
        max_width: Option<f32>,
    ) -> Label<PB::Path> {
        let mut label = Arc::new(const_rwlock(LockedLabel {
            width: 0.0,
            width_without_max_width: 0.0,
            scale: 0.0,
            glyphs: Vec::new(),
        }));

        self.update_label(path_builder, &mut label, text, font, max_width);

        label
    }

    /// Updates a text label. You can call this directly from a
    /// [`ResourceAllocator`](super::ResourceAllocator).
    pub fn update_label<PB: PathBuilder>(
        &mut self,
        mut path_builder: impl FnMut() -> PB,
        label: &mut Label<PB::Path>,
        text: &str,
        font: &mut Font<PB::Path>,
        max_width: Option<f32>,
    ) {
        let mut label = label.write();
        let label = &mut *label;

        let mut buffer = self.buffer.take().unwrap_or_else(UnicodeBuffer::new);
        buffer.push_str(text);

        let features = font
            .monotonic
            .as_ref()
            .map(|m| &m.features[..])
            .unwrap_or_default();

        let buffer = rustybuzz::shape(&font.face, features, buffer);

        let iter = Iterator::zip(buffer.glyph_infos().iter(), buffer.glyph_positions().iter());

        let (mut x, mut y) = (0.0, 0.0);

        label.glyphs.clear();

        if let Some(monotonic) = &font.monotonic {
            iter.for_each(|(info, pos)| {
                let glyph = GlyphId(info.glyph_id as _);
                let layer_glyphs = font.glyph_cache.entry(glyph).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, glyph, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                let (x_advance, x_offset) = if monotonic.digit_glyphs.contains(&glyph) {
                    (
                        monotonic.digit_width,
                        0.5 * (monotonic.digit_width - pos.x_advance as f32) + pos.x_offset as f32,
                    )
                } else {
                    (pos.x_advance as f32, pos.x_offset as f32)
                };
                let (glyph_x, glyph_y) = (x + x_offset, y + pos.y_offset as f32);
                x += x_advance;
                y += pos.y_advance as f32;
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x: glyph_x,
                        y: glyph_y,
                        path: path.share(),
                    }));
            });
        } else {
            iter.for_each(|(info, pos)| {
                let glyph = GlyphId(info.glyph_id as _);
                let layer_glyphs = font.glyph_cache.entry(glyph).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, glyph, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                let (glyph_x, glyph_y) = (x + pos.x_offset as f32, y + pos.y_offset as f32);
                x += pos.x_advance as f32;
                y += pos.y_advance as f32;
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x: glyph_x,
                        y: glyph_y,
                        path: path.share(),
                    }));
            });
        };

        label.width_without_max_width = x * font.scale_factor;

        if let Some(max_width) = max_width {
            let max_width = max_width / font.scale_factor;
            if x > max_width {
                let (ellipsis, ellipsis_width) = font.ellipsis;

                let x_to_look_for = max_width - ellipsis_width;

                let last_index = label
                    .glyphs
                    .iter()
                    .enumerate()
                    .rfind(|(_, g)| {
                        x = g.x;
                        y = g.y;
                        g.x <= x_to_look_for
                    })
                    .map(|(i, _)| i)
                    .unwrap_or_default();
                label.glyphs.drain(last_index..);
                let layer_glyphs = font.glyph_cache.entry(ellipsis).or_insert_with(|| {
                    let mut glyphs = Vec::new();
                    iter_colored_glyphs(&font.color_tables, 0, ellipsis, |glyph, color| {
                        let mut builder = GlyphBuilder(path_builder());
                        font.face.outline_glyph(glyph, &mut builder);
                        let path = builder.0.finish();
                        glyphs.push((color.map(|c| c.to_array()), path));
                    });
                    glyphs
                });
                label
                    .glyphs
                    .extend(layer_glyphs.iter().map(|(color, path)| Glyph {
                        color: *color,
                        x,
                        y,
                        path: path.share(),
                    }));
                x += ellipsis_width;
            }
        }

        self.buffer = Some(buffer.clear());

        label.width = x * font.scale_factor;
        label.scale = font.scale_factor;
    }
}

struct MonotonicInfo {
    digit_glyphs: [GlyphId; 10],
    digit_width: f32,
    features: [Feature; 1],
}

/// The font to use in the [`ResourceAllocator`](super::ResourceAllocator).
pub struct Font<P> {
    face: Face<'static>,
    color_tables: Option<ColorTables<'static>>,
    scale_factor: f32,
    monotonic: Option<MonotonicInfo>,
    /// The `GlyphId` and width of `…`.
    ellipsis: (GlyphId, f32),
    glyph_cache: HashMap<GlyphId, Vec<(Option<Rgba>, P)>>,
    #[cfg(feature = "font-loading")]
    _buf: Option<Box<[u8]>>,
}

impl<P> Font<P> {
    #[cfg(feature = "font-loading")]
    fn try_load_font(
        source: &mut SystemSource,
        font: &settings::Font,
        kind: FontKind,
    ) -> Option<Self> {
        let handle = source
            .select_best_match(
                &[FamilyName::Title(font.family.clone())],
                &Properties {
                    style: match font.style {
                        FontStyle::Normal => Style::Normal,
                        FontStyle::Italic => Style::Italic,
                    },
                    weight: Weight(font.weight.value()),
                    stretch: Stretch(font.stretch.factor()),
                },
            )
            .ok()?;

        let (buf, font_index) = match handle {
            Handle::Path { path, font_index } => (fs::read(path).ok()?, font_index),
            Handle::Memory { bytes, font_index } => (
                Arc::try_unwrap(bytes).unwrap_or_else(|bytes| (*bytes).clone()),
                font_index,
            ),
        };
        let buf = buf.into_boxed_slice();

        // Safety: We store our own buffer. If we never modify it and drop it
        // last, this is fine. It also needs to be heap allocated, so it's a
        // stable pointer. This is guaranteed by the boxed slice.
        unsafe {
            let slice: *const [u8] = &*buf;
            let mut font = Font::from_slice(
                &*slice,
                font_index,
                font.style,
                font.weight,
                font.stretch,
                kind,
            )?;
            font._buf = Some(buf);
            Some(font)
        }
    }

    fn from_slice(
        data: &'static [u8],
        index: u32,
        style: FontStyle,
        weight: FontWeight,
        stretch: FontStretch,
        kind: FontKind,
    ) -> Option<Self> {
        let mut face = Face::from_slice(data, index)?;

        let italic = style.value_for_italic();
        let weight = weight.value();
        let stretch = stretch.percentage();

        face.set_variations(&[
            Variation {
                tag: Tag::from_bytes(b"ital"),
                value: italic,
            },
            Variation {
                tag: Tag::from_bytes(b"wght"),
                value: weight,
            },
            Variation {
                tag: Tag::from_bytes(b"wdth"),
                value: stretch,
            },
        ]);

        let monotonic = kind.is_monospaced().then(|| {
            let mut digit_glyphs = [GlyphId(0); 10];
            let mut digit_width = 0;
            for (digit, glyph) in digit_glyphs.iter_mut().enumerate() {
                let (glyph_id, width) =
                    glyph_width(&face, char::from(digit as u8 + b'0')).unwrap_or_default();
                *glyph = glyph_id;
                if width > digit_width {
                    digit_width = width;
                }
            }
            MonotonicInfo {
                digit_glyphs,
                digit_width: digit_width as f32,
                features: [
                    // If the font has support for tabular numbers, we want to
                    // use it, so we don't have to fix up much. Though we still
                    // attempt to do so anyway, as we can neither query if tnum
                    // support is even available, nor can we really trust it all
                    // too much.
                    Feature::new(Tag::from_bytes(b"tnum"), 1, ..),
                    // FIXME: We may or may not want to disable kerning and
                    // possibly ligatures too. If the font doesn't support tnum,
                    // then kerning for e.g. `.1` may cause inconsistent
                    // positioning.
                    // Feature::new(Tag::from_bytes(b"kern"), 0, ..),
                ],
            }
        });

        let (ellipsis, ellipsis_width) = glyph_width(&face, '…').unwrap_or_default();

        Some(Self {
            scale_factor: 1.0 / face.height() as f32,
            color_tables: ColorTables::new(&face),
            face,
            #[cfg(feature = "font-loading")]
            _buf: None,
            monotonic,
            ellipsis: (ellipsis, ellipsis_width as f32),
            glyph_cache: HashMap::new(),
        })
    }
}

struct GlyphBuilder<PB>(PB);

impl<PB: PathBuilder> OutlineBuilder for GlyphBuilder<PB> {
    fn move_to(&mut self, x: f32, y: f32) {
        self.0.move_to(x, -y);
    }
    fn line_to(&mut self, x: f32, y: f32) {
        self.0.line_to(x, -y);
    }
    fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
        self.0.quad_to(x1, -y1, x, -y);
    }
    fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
        self.0.curve_to(x1, -y1, x2, -y2, x, -y);
    }
    fn close(&mut self) {
        self.0.close();
    }
}

/// The label to use in the [`ResourceAllocator`](super::ResourceAllocator).
pub type Label<P> = Arc<RwLock<LockedLabel<P>>>;

/// You need to lock the [`Label`] to use it. This is the locked type that
/// provides all the methods you need to use the label.
pub struct LockedLabel<P> {
    width: f32,
    width_without_max_width: f32,
    scale: f32,
    glyphs: Vec<Glyph<P>>,
}

impl<P> LockedLabel<P> {
    /// Apply this scale to the transform of the [`Entity`](super::Entity) with
    /// [`Transform::pre_scale`](super::Transform::pre_scale).
    pub const fn scale(&self) -> f32 {
        self.scale
    }

    /// The glyphs to render.
    pub fn glyphs(&self) -> &[Glyph<P>] {
        &self.glyphs
    }
}

impl<P> super::Label for Label<P> {
    fn width(&self, scale: f32) -> f32 {
        self.read().width * scale
    }

    fn width_without_max_width(&self, scale: f32) -> f32 {
        self.read().width_without_max_width * scale
    }
}

/// A glyph to render.
pub struct Glyph<P> {
    /// A glyph may provide its own color that overrides the fill shader of the
    /// [`Entity`](super::Entity).
    pub color: Option<Rgba>,
    /// The x-coordinate of the glyph.
    pub x: f32,
    /// The y-coordinate of the glyph.
    pub y: f32,
    /// The path to render.
    pub path: P,
}

fn glyph_width(face: &Face<'_>, c: char) -> Option<(GlyphId, u16)> {
    let glyph_id = face.glyph_index(c)?;
    Some((glyph_id, face.glyph_hor_advance(glyph_id)?))
}
<|endoftext|>


<commit_before>use serde::Deserialize;
use serde_json::{Result, Value};

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}
#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}
#[derive(Deserialize)]
struct BottleStable {
    rebuild: u8,
    files: Value,
}
#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn main() -> Result<()> {
    let f: Formulae = serde_json::from_reader(std::io::stdin())?;
    for f in f.0 {
        if f.versions.bottle {
            let name = f.name;
            let ver = f.versions.stable.unwrap();
            let bs = f.bottle.stable.as_ref().unwrap();
            let rebuild = bs.rebuild;
            for (platform, v) in bs
                .files
                .as_object()
                .unwrap()
                .iter()
            {
                let v: BottleInfo = serde_json::from_value(v.clone()).unwrap();
                //a2ps-4.14.arm64_big_sur.bottle.4.tar.gz
                println!(
                    "{} {} bottles/{}-{}.{}.bottle.{}.tar.gz",
                    v.sha256, v.url, name, ver, platform, rebuild
                );
            }
        }
    }
    Ok(())
}
<commit_msg>homebrew-bottles: cargo fmt<commit_after>use serde::Deserialize;
use serde_json::{Result, Value};

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}
#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}
#[derive(Deserialize)]
struct BottleStable {
    rebuild: u8,
    files: Value,
}
#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn main() -> Result<()> {
    let f: Formulae = serde_json::from_reader(std::io::stdin())?;
    for f in f.0 {
        if f.versions.bottle {
            let name = f.name;
            let ver = f.versions.stable.unwrap();
            let bs = f.bottle.stable.as_ref().unwrap();
            let rebuild = bs.rebuild;
            for (platform, v) in bs.files.as_object().unwrap().iter() {
                let v: BottleInfo = serde_json::from_value(v.clone()).unwrap();
                //a2ps-4.14.arm64_big_sur.bottle.4.tar.gz
                println!(
                    "{} {} bottles/{}-{}.{}.bottle.{}.tar.gz",
                    v.sha256, v.url, name, ver, platform, rebuild
                );
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::cell::{RefCell, Ref};
use std::collections::HashMap;
use std::hash::Hash;
use std::mem::transmute;

//A mapping between K and V where once a value has been inserted it cannot be changed
//Through this and the fact the all values are stored as pointers it is possible to safely
//insert new values without invalidating pointers retrieved from it
pub struct FixedMap<K, V> {
    map: RefCell<HashMap<K, Box<V>>>
}

impl <K: Eq + Hash, V> Collection for FixedMap<K, V> {
    fn len(&self) -> uint {
        self.map.borrow().len()
    }
}

impl <K: Eq + Hash, V> Map<K, V> for FixedMap<K, V> {
    fn find(&self, k: &K) -> Option<&V> {
        self.map.borrow()
            .find(k)
            .map(|x| unsafe { transmute::<&V, &V>(&**x) })
    }
}

impl <K: Eq + Hash, V> FixedMap<K, V> {
    pub fn new() -> FixedMap<K, V> {
        FixedMap { map: RefCell::new(HashMap::new()) }
    }
    pub fn try_insert(&self, key: K, value: V) -> Result<(), (K, V)> {
        if self.contains_key(&key) {
            Err((key, value))
        }
        else {
            self.map.borrow_mut().insert(key, box value);
            Ok(())
        }
    }
}

pub struct FixedVec<T> {
    vec: RefCell<Vec<Box<T>>>
}

impl <T> FixedVec<T> {
    pub fn new() -> FixedVec<T> {
        FixedVec { vec: RefCell::new(Vec::new()) }
    }

    pub fn push(&self, value: T) {
        self.vec.borrow_mut().push(box value)
    }
    pub fn extend<I: Iterator<T>>(&self, iter: I) {
        self.vec.borrow_mut().extend(iter.map(|v| box v))
    }

    pub fn borrow(&self) -> Ref<Vec<Box<T>>> {
        self.vec.borrow()
    }

    pub fn find(&self, test: |&T| -> bool) -> Option<(uint, &T)> {
        self.vec.try_borrow()
            .and_then(|vec| {
                vec.iter()
                    .enumerate()
                    .find(|&(_, boxed)| test(&**boxed))
                    .map(|(i, boxed)| (i, unsafe { transmute::<&T, &T>(&**boxed) }))
            })
    }
}

impl <T> Index<uint, T> for FixedVec<T> {
    fn index(&self, index: &uint) -> &T {
        let vec = self.vec.borrow();
        let result = &*(*vec)[*index];
        unsafe { transmute::<&T, &T>(result) }
    }
}

impl <A> FromIterator<A> for FixedVec<A> {
    fn from_iter<T: Iterator<A>>(iterator: T) -> FixedVec<A> {
        let vec: Vec<_> = iterator.map(|x| box x).collect();
        FixedVec { vec: RefCell::new(vec) }
    }
}
<commit_msg>Added fn len to FixedVec<commit_after>use std::cell::{RefCell, Ref};
use std::collections::HashMap;
use std::hash::Hash;
use std::mem::transmute;

//A mapping between K and V where once a value has been inserted it cannot be changed
//Through this and the fact the all values are stored as pointers it is possible to safely
//insert new values without invalidating pointers retrieved from it
pub struct FixedMap<K, V> {
    map: RefCell<HashMap<K, Box<V>>>
}

impl <K: Eq + Hash, V> Collection for FixedMap<K, V> {
    fn len(&self) -> uint {
        self.map.borrow().len()
    }
}

impl <K: Eq + Hash, V> Map<K, V> for FixedMap<K, V> {
    fn find(&self, k: &K) -> Option<&V> {
        self.map.borrow()
            .find(k)
            .map(|x| unsafe { transmute::<&V, &V>(&**x) })
    }
}

impl <K: Eq + Hash, V> FixedMap<K, V> {
    pub fn new() -> FixedMap<K, V> {
        FixedMap { map: RefCell::new(HashMap::new()) }
    }
    pub fn try_insert(&self, key: K, value: V) -> Result<(), (K, V)> {
        if self.contains_key(&key) {
            Err((key, value))
        }
        else {
            self.map.borrow_mut().insert(key, box value);
            Ok(())
        }
    }
}

pub struct FixedVec<T> {
    vec: RefCell<Vec<Box<T>>>
}

impl <T> FixedVec<T> {
    pub fn new() -> FixedVec<T> {
        FixedVec { vec: RefCell::new(Vec::new()) }
    }

    pub fn push(&self, value: T) {
        self.vec.borrow_mut().push(box value)
    }
    pub fn extend<I: Iterator<T>>(&self, iter: I) {
        self.vec.borrow_mut().extend(iter.map(|v| box v))
    }

    pub fn borrow(&self) -> Ref<Vec<Box<T>>> {
        self.vec.borrow()
    }

    pub fn find(&self, test: |&T| -> bool) -> Option<(uint, &T)> {
        self.vec.try_borrow()
            .and_then(|vec| {
                vec.iter()
                    .enumerate()
                    .find(|&(_, boxed)| test(&**boxed))
                    .map(|(i, boxed)| (i, unsafe { transmute::<&T, &T>(&**boxed) }))
            })
    }
}

impl <V> Collection for FixedVec<V> {
    fn len(&self) -> uint {
        self.vec.borrow().len()
    }
}

impl <T> Index<uint, T> for FixedVec<T> {
    fn index(&self, index: &uint) -> &T {
        let vec = self.vec.borrow();
        let result = &*(*vec)[*index];
        unsafe { transmute::<&T, &T>(result) }
    }
}

impl <A> FromIterator<A> for FixedVec<A> {
    fn from_iter<T: Iterator<A>>(iterator: T) -> FixedVec<A> {
        let vec: Vec<_> = iterator.map(|x| box x).collect();
        FixedVec { vec: RefCell::new(vec) }
    }
}
<|endoftext|>


<commit_before>extern crate num;

use std::f64;

/// The default epsilon value used for floating point comparisons.
pub static EPSILON:f64 = 1.0E-8;

pub trait Float: num::Float{
    /// Tells if the two floating-point values `self` and `y` are considered equal
    /// within the specified `absolute == relative` tolerence value.
    ///
    /// The method of comparison used is described at:
    ///
    /// http://realtimecollisiondetection.net/blog/?p=89
    ///
    /// Also consider using the `equal` method.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert!(0.9.almost_equal(1.0, 0.1000001));
    /// assert!(0.9.almost_equal(1.0, 0.1));
    /// ```
    fn almost_equal(self, y: Self, abs_tol: Self) -> bool;

    /// equal is short-hand for `self.almost_equal(y, fiz_math::EPSILON)`.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert!(1.00000001.equal(1.0));
    /// assert!(1.0.equal(1.0));
    /// assert!(!0.9.equal(1.0));
    /// ```
    fn equal(self, y: Self) -> bool;

    /// clamp returns the value v clamped to the range of [min, max].
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!(1.1.clamp(0.0, 1.0), 1.0);
    /// assert_eq!(2.0.clamp(0.0, 1.5), 1.5);
    /// ```
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!((-1.0).clamp(0.0, 1.0), 0.0);
    /// assert_eq!(0.0.clamp(0.1, 1.0), 0.1);
    /// ```
    fn clamp(self, min: Self, max: Self) -> Self;

    /// radians converts the value `self` (presumed to be in degrees) to radians.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    /// use std::f64::consts::PI;
    ///
    /// assert_eq!(180.0.radians(), PI);
    /// assert_eq!(360.0.radians(), PI * 2.0);
    /// ```
    fn radians(self) -> Self;

    /// degrees converts the value `self` (presumed to be in radians) to degrees.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    /// use std::f64::consts::PI;
    ///
    /// assert_eq!(PI.degrees(), 180.0);
    /// assert_eq!((PI*2.0).degrees(), 360.0);
    /// ```
    fn degrees(self) -> Self;

    /// lerp performs a linear interpolation between `self` and `b`. The `t`
    /// parameter is a number in the range 0.0 - 1.0.
    ///
    /// The interpolation method is precise, as such it is guaranteed that
    /// `a.lerp(b, 1.0) == a`.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!(0.0.lerp(10.0, 0.0), 0.0);
    /// assert_eq!(0.0.lerp(10.0, 0.5), 5.0);
    /// assert_eq!(0.0.lerp(10.0, 1.0), 10.0);
    /// ```
    fn lerp(self, b: Self, t: Self) -> Self;
}

impl<T: num::Float> Float for T {
    fn almost_equal(self, y: T, abs_tol: T) -> bool {
        let r = T::from(1.0).unwrap().max(self.abs().max(y.abs()));
        self == y || ((self-y).abs() <= abs_tol * r)
    }

    fn equal(self, y: T) -> bool {
        self.almost_equal(y, T::from(EPSILON).unwrap())
    }

    fn clamp(self, min: Self, max: Self) -> Self {
        self.min(max).max(min)
    }

    fn radians(self) -> Self {
        T::from(f64::consts::PI).unwrap() * self / T::from(180.0).unwrap()
    }

    fn degrees(self) -> Self {
        self * T::from(180.0 / f64::consts::PI).unwrap()
    }

    fn lerp(self, b: Self, t: Self) -> Self {
        (T::one()-t)*self + t*b
    }
}
<commit_msg>fix style issue<commit_after>extern crate num;

use std::f64;

/// The default epsilon value used for floating point comparisons.
pub static EPSILON:f64 = 1.0E-8;

pub trait Float: num::Float{
    /// Tells if the two floating-point values `self` and `y` are considered equal
    /// within the specified `absolute == relative` tolerence value.
    ///
    /// The method of comparison used is described at:
    ///
    /// http://realtimecollisiondetection.net/blog/?p=89
    ///
    /// Also consider using the `equal` method.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert!(0.9.almost_equal(1.0, 0.1000001));
    /// assert!(0.9.almost_equal(1.0, 0.1));
    /// ```
    fn almost_equal(self, y: Self, abs_tol: Self) -> bool;

    /// equal is short-hand for `self.almost_equal(y, fiz_math::EPSILON)`.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert!(1.00000001.equal(1.0));
    /// assert!(1.0.equal(1.0));
    /// assert!(!0.9.equal(1.0));
    /// ```
    fn equal(self, y: Self) -> bool;

    /// clamp returns the value v clamped to the range of [min, max].
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!(1.1.clamp(0.0, 1.0), 1.0);
    /// assert_eq!(2.0.clamp(0.0, 1.5), 1.5);
    /// ```
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!((-1.0).clamp(0.0, 1.0), 0.0);
    /// assert_eq!(0.0.clamp(0.1, 1.0), 0.1);
    /// ```
    fn clamp(self, min: Self, max: Self) -> Self;

    /// radians converts the value `self` (presumed to be in degrees) to radians.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    /// use std::f64::consts::PI;
    ///
    /// assert_eq!(180.0.radians(), PI);
    /// assert_eq!(360.0.radians(), PI * 2.0);
    /// ```
    fn radians(self) -> Self;

    /// degrees converts the value `self` (presumed to be in radians) to degrees.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    /// use std::f64::consts::PI;
    ///
    /// assert_eq!(PI.degrees(), 180.0);
    /// assert_eq!((PI*2.0).degrees(), 360.0);
    /// ```
    fn degrees(self) -> Self;

    /// lerp performs a linear interpolation between `self` and `b`. The `t`
    /// parameter is a number in the range 0.0 - 1.0.
    ///
    /// The interpolation method is precise, as such it is guaranteed that
    /// `a.lerp(b, 1.0) == a`.
    ///
    /// # Examples
    ///
    /// ```
    /// use fiz_math::Float;
    ///
    /// assert_eq!(0.0.lerp(10.0, 0.0), 0.0);
    /// assert_eq!(0.0.lerp(10.0, 0.5), 5.0);
    /// assert_eq!(0.0.lerp(10.0, 1.0), 10.0);
    /// ```
    fn lerp(self, b: Self, t: Self) -> Self;
}

impl<T: num::Float> Float for T {
    fn almost_equal(self, y: T, abs_tol: T) -> bool {
        let r = T::from(1.0).unwrap().max(self.abs().max(y.abs()));
        self == y || ((self-y).abs() <= abs_tol * r)
    }

    fn equal(self, y: T) -> bool {
        self.almost_equal(y, T::from(EPSILON).unwrap())
    }

    fn clamp(self, min: Self, max: Self) -> Self {
        self.min(max).max(min)
    }

    fn radians(self) -> Self {
        T::from(f64::consts::PI).unwrap() * self / T::from(180.0).unwrap()
    }

    fn degrees(self) -> Self {
        self * T::from(180.0 / f64::consts::PI).unwrap()
    }

    fn lerp(self, b: Self, t: Self) -> Self {
        (T::one()-t)*self + t*b
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufRead, BufReader};
mod node;
use node::*;
use std::cmp;

type Pyramid = Vec<Vec<usize>>;

fn main() {
    // let mut pyramid = get_pyramid("pyramid.txt");
    let mut pyramid = get_pyramid("mini.txt");
    // let mut root = Node { val: pyramid[0][0], l: None, r: None };

    // populate_binary_tree(&mut root, 1, 0, 1, &pyramid, pyramid.len());

    // print_node(root, 0);
    // let max_sum = max_path_tree(root);
    let max_sum = max_path_vec(pyramid[0][0], 1, 0, 1, &pyramid, pyramid.len());

    println!("max sum: {}", max_sum);
}

fn max_path_tree( root: Node ) -> usize {

    let r_max: usize;
    match root.r {
        Some(node) => {
            r_max = max_path_tree(*node);
        }
        None => { r_max = 0; }
    }

    let l_max: usize;
    match root.l {
        Some(node) => {
            l_max = max_path_tree(*node);
        }
        None => { l_max = 0; }
    }

    root.val + cmp::max(l_max, r_max)
}

fn max_path_vec(root: usize, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) -> usize {

    if depth == max_depth {
        return root
    }

    let l_max = max_path_vec(pyramid[depth][lidx], depth+1, lidx, ridx, pyramid, max_depth);
    let r_max = max_path_vec(pyramid[depth][ridx], depth+1, ridx, ridx + 1, pyramid, max_depth);

    root + cmp::max(l_max, r_max)
}

fn populate_binary_tree(root: &mut Node, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) {

    if depth == max_depth {
        return
    }

    let mut l = Node { val: pyramid[depth][lidx], l: None, r: None };
    let mut r = Node { val: pyramid[depth][ridx], l: None, r: None };

    populate_binary_tree(&mut l, depth+1, lidx, ridx, pyramid, max_depth);
    populate_binary_tree(&mut r, depth+1, ridx, ridx + 1, pyramid, max_depth);

    root.l = Some(Box::new(l));
    root.r = Some(Box::new(r));
}

fn print_node( root: Node, depth: usize ) {

    match root.r {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }

    println!("{}:{}", std::iter::repeat(" ").take(depth*4).collect::<String>(), root.val );

    match root.l {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }
}

pub fn get_pyramid(fname: &str) -> Pyramid {

    let file = BufReader::new(File::open(fname).unwrap());

    file.lines()
        .map( |l| l.unwrap().split(char::is_whitespace)
             .map(|g| g.chars().collect::<String>().parse::<usize>().unwrap())
             .collect() )
        .collect()
}<commit_msg>updated with feasible solution strategy<commit_after>use std::fs::File;
use std::io::{BufRead, BufReader};
mod node;
use node::*;
use std::cmp;

type Pyramid = Vec<Vec<usize>>;

fn main() {
    let mut pyramid = get_pyramid("pyramid.txt");
    // let mut pyramid = get_pyramid("mini.txt");
    // let mut root = Node { val: pyramid[0][0], l: None, r: None };

    // populate_binary_tree(&mut root, 1, 0, 1, &pyramid, pyramid.len());

    // print_node(root, 0);
    // let max_sum = max_path_tree(root);
    // let max_sum = max_path_vec(pyramid[0][0], 1, 0, 1, &pyramid, pyramid.len());

    // println!("max sum: {}", max_sum);
    let depth = pyramid.len() - 2;
    max_path_dynamic(&mut pyramid, depth);
    println!("max sum: {}", pyramid[0][0]);
}

fn max_path_dynamic( pyramid: &mut Pyramid, depth: usize ) {

    if depth == 0 {

        let l_max = pyramid[depth][0] + pyramid[depth+1][0];
        let r_max = pyramid[depth][0] + pyramid[depth+1][1];

        pyramid[depth][0] = cmp::max(l_max, r_max);

        return
    }

    for i in 0..pyramid[depth].len() {
        let l_max = pyramid[depth][i] + pyramid[depth+1][i];
        let r_max = pyramid[depth][i] + pyramid[depth+1][i+1];

        pyramid[depth][i] = cmp::max(l_max, r_max);
    }

    max_path_dynamic(pyramid, depth - 1);
}

fn max_path_tree( root: Node ) -> usize {

    let r_max: usize;
    match root.r {
        Some(node) => {
            r_max = max_path_tree(*node);
        }
        None => { r_max = 0; }
    }

    let l_max: usize;
    match root.l {
        Some(node) => {
            l_max = max_path_tree(*node);
        }
        None => { l_max = 0; }
    }

    root.val + cmp::max(l_max, r_max)
}

fn max_path_vec(root: usize, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) -> usize {

    if depth == max_depth {
        return root
    }

    let l_max = max_path_vec(pyramid[depth][lidx], depth+1, lidx, ridx, pyramid, max_depth);
    let r_max = max_path_vec(pyramid[depth][ridx], depth+1, ridx, ridx + 1, pyramid, max_depth);

    root + cmp::max(l_max, r_max)
}

fn populate_binary_tree(root: &mut Node, depth: usize, lidx: usize, ridx: usize, pyramid: &Pyramid, max_depth: usize) {

    if depth == max_depth {
        return
    }

    let mut l = Node { val: pyramid[depth][lidx], l: None, r: None };
    let mut r = Node { val: pyramid[depth][ridx], l: None, r: None };

    populate_binary_tree(&mut l, depth+1, lidx, ridx, pyramid, max_depth);
    populate_binary_tree(&mut r, depth+1, ridx, ridx + 1, pyramid, max_depth);

    root.l = Some(Box::new(l));
    root.r = Some(Box::new(r));
}

fn print_node( root: Node, depth: usize ) {

    match root.r {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }

    println!("{}:{}", std::iter::repeat(" ").take(depth*4).collect::<String>(), root.val );

    match root.l {
        Some(node) => {
            print_node(*node, depth + 1);
        }
        None => {}
    }
}

pub fn get_pyramid(fname: &str) -> Pyramid {

    let file = BufReader::new(File::open(fname).unwrap());

    file.lines()
        .map( |l| l.unwrap().split(char::is_whitespace)
             .map(|g| g.chars().collect::<String>().parse::<usize>().unwrap())
             .collect() )
        .collect()
}<|endoftext|>


<commit_before>//! Value module.

use std::cmp::{Eq, Ordering};
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};

use serde::de::{DeserializeSeed, Deserializer, MapAccess, SeqAccess, Visitor};

use de::{Error as RonError, Result};

/// A wrapper for `f64` which guarantees that the inner value
/// is finite and thus implements `Eq`, `Hash` and `Ord`.
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct Number(f64);

impl Number {
    /// Panics if `v` is not a real number
    /// (infinity, NaN, ..).
    pub fn new(v: f64) -> Self {
        if !v.is_finite() {
            panic!("Tried to create Number with a NaN / infinity");
        }

        Number(v)
    }

    /// Returns the wrapped float.
    pub fn get(&self) -> f64 {
        self.0
    }
}

impl Eq for Number {}

impl Hash for Number {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u64(self.0 as u64);
    }
}

impl Ord for Number {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("Bug: Contract violation")
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Map(BTreeMap<Value, Value>),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

/// Deserializer implementation for RON `Value`.
/// This does not support enums (because `Value` doesn't store them).
impl<'de> Deserializer<'de> for Value {
    type Error = RonError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Bool(b) => visitor.visit_bool(b),
            Value::Char(c) => visitor.visit_char(c),
            Value::Map(m) => visitor.visit_map(Map {
                keys: m.keys().cloned().rev().collect(),
                values: m.values().cloned().rev().collect(),
            }),
            Value::Number(n) => visitor.visit_f64(n.get()),
            Value::Option(Some(o)) => visitor.visit_some(*o),
            Value::Option(None) => visitor.visit_none(),
            Value::String(s) => visitor.visit_string(s),
            Value::Seq(mut seq) => {
                seq.reverse();

                visitor.visit_seq(Seq { seq })
            }
            Value::Unit => visitor.visit_unit(),
        }
    }

    forward_to_deserialize_any! {
        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
        byte_buf option unit unit_struct newtype_struct seq tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct Map {
    keys: Vec<Value>,
    values: Vec<Value>,
}

impl<'de> MapAccess<'de> for Map {
    type Error = RonError;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
    where
        K: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.keys
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
    where
        V: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.values
            .pop()
            .map(|v| seed.deserialize(v))
            .expect("Contract violation")
    }
}

struct Seq {
    seq: Vec<Value>,
}

impl<'de> SeqAccess<'de> for Seq {
    type Error = RonError;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.seq
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }
}

#[cfg(test)]
mod tests {
    use std::fmt::Debug;
    use serde::Deserialize;
    use super::*;

    fn assert_same<'de, T>(s: &'de str)
    where
        T: Debug + Deserialize<'de> + PartialEq,
    {
        use de::from_str;

        let direct: T = from_str(s).unwrap();
        let value: Value = from_str(s).unwrap();
        let value = T::deserialize(value).unwrap();

        assert_eq!(direct, value, "Deserialization for {:?} is not the same", s);
    }

    #[test]
    fn boolean() {
        assert_same::<bool>("true");
        assert_same::<bool>("false");
    }

    #[test]
    fn float() {
        assert_same::<f64>("0.123");
        assert_same::<f64>("-4.19");
    }

    #[test]
    fn char() {
        assert_same::<char>("'4'");
        assert_same::<char>("'c'");
    }

    #[test]
    fn map() {
        assert_same::<BTreeMap<char, String>>(
            "{
'a': \"Hello\",
'b': \"Bye\",
        }",
        );
    }

    #[test]
    fn option() {
        assert_same::<Option<char>>("Some('a')");
        assert_same::<Option<char>>("None");
    }

    #[test]
    fn seq() {
        assert_same::<Vec<f64>>("[1.0, 2.0, 3.0, 4.0]");
    }

    #[test]
    fn unit() {
        assert_same::<()>("()");
    }
}
<commit_msg>Add support for integers<commit_after>//! Value module.

use std::cmp::{Eq, Ordering};
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};

use serde::de::{DeserializeSeed, Deserializer, Error as SerdeErr, MapAccess, SeqAccess, Visitor};

use de::{Error as RonError, Result};

/// A wrapper for `f64` which guarantees that the inner value
/// is finite and thus implements `Eq`, `Hash` and `Ord`.
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub struct Number(f64);

impl Number {
    /// Panics if `v` is not a real number
    /// (infinity, NaN, ..).
    pub fn new(v: f64) -> Self {
        if !v.is_finite() {
            panic!("Tried to create Number with a NaN / infinity");
        }

        Number(v)
    }

    /// Returns the wrapped float.
    pub fn get(&self) -> f64 {
        self.0
    }
}

impl Eq for Number {}

impl Hash for Number {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_u64(self.0 as u64);
    }
}

impl Ord for Number {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).expect("Bug: Contract violation")
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Map(BTreeMap<Value, Value>),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

/// Deserializer implementation for RON `Value`.
/// This does not support enums (because `Value` doesn't store them).
impl<'de> Deserializer<'de> for Value {
    type Error = RonError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Bool(b) => visitor.visit_bool(b),
            Value::Char(c) => visitor.visit_char(c),
            Value::Map(m) => visitor.visit_map(Map {
                keys: m.keys().cloned().rev().collect(),
                values: m.values().cloned().rev().collect(),
            }),
            Value::Number(n) => visitor.visit_f64(n.get()),
            Value::Option(Some(o)) => visitor.visit_some(*o),
            Value::Option(None) => visitor.visit_none(),
            Value::String(s) => visitor.visit_string(s),
            Value::Seq(mut seq) => {
                seq.reverse();

                visitor.visit_seq(Seq { seq })
            }
            Value::Unit => visitor.visit_unit(),
        }
    }

    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_i64(visitor)
    }

    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_i64(n.get() as i64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        self.deserialize_u64(visitor)
    }

    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self {
            Value::Number(n) => visitor.visit_u64(n.get() as u64),
            v => Err(RonError::custom(format!("Expected a number, got {:?}", v))),
        }
    }

    forward_to_deserialize_any! {
        bool f32 f64 char str string bytes
        byte_buf option unit unit_struct newtype_struct seq tuple
        tuple_struct map struct enum identifier ignored_any
    }
}

struct Map {
    keys: Vec<Value>,
    values: Vec<Value>,
}

impl<'de> MapAccess<'de> for Map {
    type Error = RonError;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
    where
        K: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.keys
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
    where
        V: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.values
            .pop()
            .map(|v| seed.deserialize(v))
            .expect("Contract violation")
    }
}

struct Seq {
    seq: Vec<Value>,
}

impl<'de> SeqAccess<'de> for Seq {
    type Error = RonError;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: DeserializeSeed<'de>,
    {
        // The `Vec` is reversed, so we can pop to get the originally first element
        self.seq
            .pop()
            .map_or(Ok(None), |v| seed.deserialize(v).map(Some))
    }
}

#[cfg(test)]
mod tests {
    use std::fmt::Debug;
    use serde::Deserialize;
    use super::*;

    fn assert_same<'de, T>(s: &'de str)
    where
        T: Debug + Deserialize<'de> + PartialEq,
    {
        use de::from_str;

        let direct: T = from_str(s).unwrap();
        let value: Value = from_str(s).unwrap();
        let value = T::deserialize(value).unwrap();

        assert_eq!(direct, value, "Deserialization for {:?} is not the same", s);
    }

    #[test]
    fn boolean() {
        assert_same::<bool>("true");
        assert_same::<bool>("false");
    }

    #[test]
    fn float() {
        assert_same::<f64>("0.123");
        assert_same::<f64>("-4.19");
    }

    #[test]
    fn int() {
        assert_same::<u32>("626");
        assert_same::<i32>("-50");
    }

    #[test]
    fn char() {
        assert_same::<char>("'4'");
        assert_same::<char>("'c'");
    }

    #[test]
    fn map() {
        assert_same::<BTreeMap<char, String>>(
            "{
'a': \"Hello\",
'b': \"Bye\",
        }",
        );
    }

    #[test]
    fn option() {
        assert_same::<Option<char>>("Some('a')");
        assert_same::<Option<char>>("None");
    }

    #[test]
    fn seq() {
        assert_same::<Vec<f64>>("[1.0, 2.0, 3.0, 4.0]");
    }

    #[test]
    fn unit() {
        assert_same::<()>("()");
    }
}
<|endoftext|>


<commit_before>use error::MemcacheError;

pub enum Flags {
    Bytes = 0,
    JSON = 1,
}

pub trait ToMemcacheValue {
    fn get_flags(&self) -> u16;
    fn get_bytes(&self) -> &[u8];
}

pub struct Raw<'a> {
    pub bytes: &'a [u8],
    pub flags: u16,
}

impl<'a> ToMemcacheValue for (&'a [u8], u16) {
    fn get_flags(&self) -> u16 {
        return self.1;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.0;
    }
}

impl<'a> ToMemcacheValue for &'a Raw<'a> {
    fn get_flags(&self) -> u16 {
        return self.flags;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.bytes;
    }
}

impl<'a> ToMemcacheValue for &'a [u8] {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self;
    }
}

impl ToMemcacheValue for String {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

impl<'a> ToMemcacheValue for &'a str {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

type MemcacheValue<T> = Result<T, MemcacheError>;

pub trait FromMemcacheValue: Sized {
    fn from_memcache_value(Vec<u8>, u16) -> MemcacheValue<Self>;
}

impl FromMemcacheValue for (Vec<u8>, u16) {
    fn from_memcache_value(value: Vec<u8>, flags: u16) -> MemcacheValue<Self> {
        return Ok((value, flags));
    }
}

impl FromMemcacheValue for Vec<u8> {
    fn from_memcache_value(value: Vec<u8>, _: u16) -> MemcacheValue<Self> {
        return Ok(value);
    }
}
<commit_msg>feat: implement FromMemcacheValue for String<commit_after>use error::MemcacheError;

pub enum Flags {
    Bytes = 0,
    JSON = 1,
}

pub trait ToMemcacheValue {
    fn get_flags(&self) -> u16;
    fn get_bytes(&self) -> &[u8];
}

pub struct Raw<'a> {
    pub bytes: &'a [u8],
    pub flags: u16,
}

impl<'a> ToMemcacheValue for (&'a [u8], u16) {
    fn get_flags(&self) -> u16 {
        return self.1;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.0;
    }
}

impl<'a> ToMemcacheValue for &'a Raw<'a> {
    fn get_flags(&self) -> u16 {
        return self.flags;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.bytes;
    }
}

impl<'a> ToMemcacheValue for &'a [u8] {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self;
    }
}

impl ToMemcacheValue for String {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

impl<'a> ToMemcacheValue for &'a str {
    fn get_flags(&self) -> u16 {
        return Flags::Bytes as u16;
    }

    fn get_bytes(&self) -> &[u8] {
        return self.as_bytes();
    }
}

type MemcacheValue<T> = Result<T, MemcacheError>;

pub trait FromMemcacheValue: Sized {
    fn from_memcache_value(Vec<u8>, u16) -> MemcacheValue<Self>;
}

impl FromMemcacheValue for (Vec<u8>, u16) {
    fn from_memcache_value(value: Vec<u8>, flags: u16) -> MemcacheValue<Self> {
        return Ok((value, flags));
    }
}

impl FromMemcacheValue for Vec<u8> {
    fn from_memcache_value(value: Vec<u8>, _: u16) -> MemcacheValue<Self> {
        return Ok(value);
    }
}

impl FromMemcacheValue for String {
    fn from_memcache_value(value: Vec<u8>, _: u16) -> MemcacheValue<Self> {
        // TODO
        match String::from_utf8(value) {
            Ok(v) => Ok(v),
            Err(_) =>Err(MemcacheError::Error),
        }
    }
}
<|endoftext|>


<commit_before>use std::{mem, slice};
use allocator::*;

use super::entry_location::*;

#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum EntryType {
    Alias = 0xA,
    Entry,
    Deleted,
}

/// If the entry is an alias, contents_size is the number
/// of segments in the alias. If it's an entry, contents_size
/// represents the number of bytes in the entry.
#[derive(Clone, PartialEq, Debug)]
#[repr(C)]
pub struct ByteStringEntry {
    entry_type: EntryType,
    contents_size: usize,
    // contents_size bytes of data
}

/// Decrement the ref count for the given byte string
/// Follow aliases to release all their byte strings
pub fn release_byte_string(entry: &EntryLocation, pool: &Pool) {
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            pool.release(entry.page_index);
        },
        EntryType::Deleted => {},
        EntryType::Alias => {
            for e in get_aliased_entries(entry, pool) {
                release_byte_string(e, pool);
            }
            // Once we've followed and release all the aliased
            // strings, release this alias.
            pool.release(entry.page_index);
        }
    }
}

/// Get the type of the entry pointed to by the location
fn get_entry_type(entry: &EntryLocation, pool: &Pool) -> EntryType {
    pool[entry.page_index]
        .transmute_segment::<EntryType>(entry.offset)
        .clone()
}

/// Returns a slice of the entries which are aliased by the given entry
pub fn get_aliased_entries<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[EntryLocation] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Alias, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    let start_ptr: *const u8 = &pool[entry.page_index][start];

    unsafe {
        let start_ptr: *const EntryLocation = mem::transmute(start_ptr);
        slice::from_raw_parts(start_ptr, header.contents_size)
    }
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    &pool[entry.page_index][start..start+header.contents_size]
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice_mut<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a mut [u8] {
    let header: &ByteStringEntry = pool[entry.page_index]
        .transmute_segment(entry.offset);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();

    let page: &mut Page = pool[entry.page_index].borrow_mut();
    &mut page[start..start+header.contents_size]
}

/// Get the iter over the memory represented by the bytestring
pub fn get_iter<'a>(entry: &'a EntryLocation, pool: &'a Pool) -> ByteStringIter<'a> {
    let page = &pool[entry.page_index];
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: false,
                current_page: page,
                current_entry: entry,
                current_string: pool[entry.page_index].transmute_segment(entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Alias => {
            let first_entry = &get_aliased_entries(entry, pool)[0];
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: true,
                current_page: page,
                current_entry: first_entry,
                current_string:  pool[first_entry.page_index].transmute_segment(first_entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Deleted => {
            panic!("get_iter called on a deleted entry");
        },
    }
}

/// ITERATION
/// Provides byte string iters

pub struct ByteStringIter<'a> {
    entry: &'a EntryLocation,
    pool: &'a Pool,

    is_aliased: bool,
    current_page: &'a Page,
    current_entry: &'a EntryLocation,
    current_string: &'a ByteStringEntry,
    alias_index: usize,
    byte_index: usize,
}

impl <'a> Iterator for ByteStringIter<'a> {
    type Item = &'a u8;

    fn next(&mut self) -> Option<&'a u8> {
        let current_byte = &self.current_page
            [self.current_entry.offset+mem::size_of::<ByteStringEntry>()+self.byte_index];

        // Increment our count, and roll over if necessary
        self.byte_index += 1;
        println!("{}/{}", self.byte_index, self.current_string.contents_size);
        if self.byte_index >= self.current_string.contents_size {
            if self.is_aliased {
                self.alias_index += 1;
                let entries = get_aliased_entries(self.entry, self.pool);
                if self.alias_index >= entries.len() {
                    return None
                }
                self.current_entry = &entries[self.alias_index];
                self.current_string = self.pool[self.current_entry.page_index]
                    .transmute_segment(self.current_entry.offset);
                self.byte_index = 0;
                self.current_page = &self.pool[self.current_entry.page_index];
            } else {
                return None
            }
        }
        Some(current_byte)
    }
}

#[test]
fn test_get_slice_mut() {
    let mut buf = [0u8; 0x2000];
    let pool = Pool::new(&mut buf);

    let page_index = pool.alloc().unwrap();
    let mut p: &Page = &pool[page_index];
    let loc = EntryLocation {
        page_index: page_index,
        offset: 0,
    };

    let mut entry = p.transmute_page_mut::<ByteStringEntry>();
    entry.entry_type = EntryType::Entry;
    entry.contents_size = 10;

    // Init the data as a slice
    for iv in get_slice_mut(&loc, &pool).iter_mut().enumerate() {
        *iv.1 = iv.0 as u8;
    }

    // check the data via iterator
    get_iter(&loc, &pool).zip((0u8..)).fold(true, |b, actual_exp| {
        assert_eq!(*actual_exp.0, actual_exp.1);
        b && *actual_exp.0 == actual_exp.1
    });
}
<commit_msg>Added tests for iteration over aliased data<commit_after>use std::{mem, slice};
use allocator::*;

use super::entry_location::*;

#[derive(Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum EntryType {
    Alias = 0xA,
    Entry,
    Deleted,
}

/// If the entry is an alias, contents_size is the number
/// of segments in the alias. If it's an entry, contents_size
/// represents the number of bytes in the entry.
#[derive(Clone, PartialEq, Debug)]
#[repr(C)]
pub struct ByteStringEntry {
    entry_type: EntryType,
    contents_size: usize,
    // contents_size bytes of data
}

/// Decrement the ref count for the given byte string
/// Follow aliases to release all their byte strings
pub fn release_byte_string(entry: &EntryLocation, pool: &Pool) {
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            pool.release(entry.page_index);
        },
        EntryType::Deleted => {},
        EntryType::Alias => {
            for e in get_aliased_entries(entry, pool) {
                release_byte_string(e, pool);
            }
            // Once we've followed and release all the aliased
            // strings, release this alias.
            pool.release(entry.page_index);
        }
    }
}

/// Get the type of the entry pointed to by the location
fn get_entry_type(entry: &EntryLocation, pool: &Pool) -> EntryType {
    pool[entry.page_index]
        .transmute_segment::<EntryType>(entry.offset)
        .clone()
}

fn get_entry_header<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a mut ByteStringEntry {
    pool[entry.page_index].transmute_segment_mut::<ByteStringEntry>(entry.offset)
}

/// Returns a slice of the entries which are aliased by the given entry
pub fn get_aliased_entries<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[EntryLocation] {
    let header = get_entry_header(entry, pool);
    assert_eq!(EntryType::Alias, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    let start_ptr: *const u8 = &pool[entry.page_index][start];

    unsafe {
        let start_ptr: *const EntryLocation = mem::transmute(start_ptr);
        slice::from_raw_parts(start_ptr, header.contents_size)
    }
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a[u8] {
    let header = get_entry_header(entry, pool);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();
    &pool[entry.page_index][start..start+header.contents_size]
}

/// Treates the entry location as a ByteStringEntry
/// Panics if not given the correct entry
pub fn get_slice_mut<'a>(entry: &EntryLocation, pool: &'a Pool) -> &'a mut [u8] {
    let header = get_entry_header(entry, pool);
    assert_eq!(EntryType::Entry, header.entry_type);

    let start = entry.offset + mem::size_of::<ByteStringEntry>();

    let page: &mut Page = pool[entry.page_index].borrow_mut();
    &mut page[start..start+header.contents_size]
}

/// Get the iter over the memory represented by the bytestring
pub fn get_iter<'a>(entry: &'a EntryLocation, pool: &'a Pool) -> ByteStringIter<'a> {
    let page = &pool[entry.page_index];
    match get_entry_type(entry, pool) {
        EntryType::Entry => {
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: false,
                current_page: page,
                current_entry: entry,
                current_string: pool[entry.page_index].transmute_segment(entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Alias => {
            let first_entry = &get_aliased_entries(entry, pool)[0];
            ByteStringIter {
                entry: entry,
                pool: pool,

                is_aliased: true,
                current_page: page,
                current_entry: first_entry,
                current_string:  pool[first_entry.page_index].transmute_segment(first_entry.offset),
                alias_index: 0,
                byte_index: 0,
            }
        },
        EntryType::Deleted => {
            panic!("get_iter called on a deleted entry");
        },
    }
}

/// ITERATION
/// Provides byte string iters

pub struct ByteStringIter<'a> {
    entry: &'a EntryLocation,
    pool: &'a Pool,

    is_aliased: bool,
    current_page: &'a Page,
    current_entry: &'a EntryLocation,
    current_string: &'a ByteStringEntry,
    alias_index: usize,
    byte_index: usize,
}

impl <'a> Iterator for ByteStringIter<'a> {
    type Item = &'a u8;

    fn next(&mut self) -> Option<&'a u8> {
        let current_byte = &self.current_page
            [self.current_entry.offset+mem::size_of::<ByteStringEntry>()+self.byte_index];

        // Increment our count, and roll over if necessary
        self.byte_index += 1;
        println!("{}/{}", self.byte_index, self.current_string.contents_size);
        if self.byte_index >= self.current_string.contents_size {
            if self.is_aliased {
                self.alias_index += 1;
                let entries = get_aliased_entries(self.entry, self.pool);
                if self.alias_index >= entries.len() {
                    return None
                }
                self.current_entry = &entries[self.alias_index];
                self.current_string = self.pool[self.current_entry.page_index]
                    .transmute_segment(self.current_entry.offset);
                self.byte_index = 0;
                self.current_page = &self.pool[self.current_entry.page_index];
            } else {
                return None
            }
        }
        Some(current_byte)
    }
}

#[test]
fn get_aliased_string() {
    let mut buf = [0u8; 0x2000];
    let pool = Pool::new(&mut buf);

    let page_index = pool.alloc().unwrap();
    let mut p: &Page = &pool[page_index];

    let alias_loc = EntryLocation {
        page_index: page_index,
        offset: 0,
    };

    let mut alias = get_entry_header(&alias_loc, &pool);
    alias.entry_type = EntryType::Alias;
    alias.contents_size = 2;

    let loc_size = mem::size_of::<EntryLocation>();
    let header_size = mem::size_of::<EntryLocation>();

    let mut entry1_loc = p.transmute_segment_mut::<EntryLocation>(header_size);
    entry1_loc.page_index = page_index;
    entry1_loc.offset = header_size+2*loc_size;
    let mut entry1 = get_entry_header(entry1_loc, &pool);
    entry1.entry_type = EntryType::Entry;
    entry1.contents_size = 10;

    let mut entry2_loc = p.transmute_segment_mut::<EntryLocation>(header_size+loc_size);
    entry2_loc.page_index = page_index;
    entry2_loc.offset = 2*header_size+2*loc_size+10;
    let mut entry2 = get_entry_header(entry2_loc, &pool);
    entry2.entry_type = EntryType::Entry;
    entry2.contents_size = 10;

    // Init the data as a slice
    for iv in get_slice_mut(&entry1_loc, &pool).iter_mut().enumerate() {
        *iv.1 = iv.0 as u8;
    }
    for iv in get_slice_mut(&entry2_loc, &pool).iter_mut().enumerate() {
        *iv.1 = (iv.0 as u8) + 10u8;
    }

    // check the data via iterator
    get_iter(&alias_loc, &pool).zip((0u8..)).fold(true, |b, actual_exp| {
        assert_eq!(*actual_exp.0, actual_exp.1);
        b && *actual_exp.0 == actual_exp.1
    });
}

#[test]
fn test_get_slice_mut_and_iter() {
    let mut buf = [0u8; 0x2000];
    let pool = Pool::new(&mut buf);

    let page_index = pool.alloc().unwrap();
    let mut p: &Page = &pool[page_index];
    let loc = EntryLocation {
        page_index: page_index,
        offset: 0,
    };

    let mut entry = get_entry_header(&loc, &pool);
    entry.entry_type = EntryType::Entry;
    entry.contents_size = 10;

    // Init the data as a slice
    for iv in get_slice_mut(&loc, &pool).iter_mut().enumerate() {
        *iv.1 = iv.0 as u8;
    }

    // check the data via iterator
    get_iter(&loc, &pool).zip((0u8..)).fold(true, |b, actual_exp| {
        assert_eq!(*actual_exp.0, actual_exp.1);
        b && *actual_exp.0 == actual_exp.1
    });
}
<|endoftext|>


<commit_before>// #47295: We used to have a hack of special-casing adjacent amtch
// arms whose patterns were composed solely of constants to not have
// them linked in the cfg.
//
// THis was broken for various reasons. In particular, that hack was
// originally authored under the assunption that other checks
// elsewhere would ensure that the two patterns did not overlap.  But
// that assumption did not hold, at least not in the long run (namely,
// overlapping patterns were turned into warnings rather than errors).

#![feature(box_syntax)]

fn main() {
    let x: Box<_> = box 1;

    let v = (1, 2);

    match v {
        (1, 2) if take(x) => (),
        (1, 2) if take(x) => (), //~ ERROR use of moved value: `x`
        _ => (),
    }
}

fn take<T>(_: T) -> bool { false }
<commit_msg>Rollup merge of #88661 - est31:typo_fix_in_test, r=joshtriplett<commit_after>// #47295: We used to have a hack of special-casing adjacent amtch
// arms whose patterns were composed solely of constants to not have
// them linked in the cfg.
//
// This was broken for various reasons. In particular, that hack was
// originally authored under the assunption that other checks
// elsewhere would ensure that the two patterns did not overlap.  But
// that assumption did not hold, at least not in the long run (namely,
// overlapping patterns were turned into warnings rather than errors).

#![feature(box_syntax)]

fn main() {
    let x: Box<_> = box 1;

    let v = (1, 2);

    match v {
        (1, 2) if take(x) => (),
        (1, 2) if take(x) => (), //~ ERROR use of moved value: `x`
        _ => (),
    }
}

fn take<T>(_: T) -> bool { false }
<|endoftext|>