<commit_before>//! Construct bitmap font using FreeType library.
//! Generates raw texture data for the given font and collects information
//! about available font characters to map them into texture.

use std::cmp::max;
use std::iter::{repeat, FromIterator};
use std::collections::{HashMap, HashSet};
use std::char::from_u32;
use ::freetype as ft;
use ::freetype::Face;

#[derive(Debug)]
pub struct BitmapFont {
    width: u16,
    height: u16,
    chars: HashMap<char, BitmapChar>,
    image: Vec<u8>,
}

#[derive(Debug)]
pub struct BitmapChar {
    // Real glyph's coordinates in pixels.
    pub x_offset: i32,
    pub y_offset: i32,
    pub x_advance: i32,
    pub width: i32,
    pub height: i32,
    // Precalculated scaled positions in texture.
    pub tex: [f32; 2],
    pub tex_width: f32,
    pub tex_height: f32,
    // This field is used only while building the texture.
    data: Option<Vec<u8>>,
}

/// Represents possible errors that may occur during the font loading.
#[derive(Debug)]
pub enum FontError {
    /// Character set is empty
    EmptyFont,
    /// FreeType library error
    FreetypeError(ft::Error),
}

impl From<ft::Error> for FontError {
    fn from(e: ft::Error) -> FontError { FontError::FreetypeError(e) }
}

pub type FontResult = Result<BitmapFont, FontError>;

impl BitmapFont {
    pub fn from_path(path: &str, font_size: u8, chars: Option<&[char]>) -> FontResult {
        let library = try!(ft::Library::init());
        let face = try!(library.new_face(path, 0));
        Self::new(face, font_size, chars)
    }

    pub fn from_bytes(data: &[u8], font_size: u8, chars: Option<&[char]>) -> FontResult {
        let library = try!(ft::Library::init());
        let face = try!(library.new_memory_face(data, 0));
        Self::new(face, font_size, chars)
    }

    fn get_all_face_chars<'a>(face: &mut Face<'a>) -> HashSet<char> {
        let mut result = HashSet::new();
        let mut index = 0;
        let mut face_ptr = face.raw_mut();
        unsafe {
            let mut code = ft::ffi::FT_Get_First_Char(face_ptr, &mut index);
            while index != 0 {
                from_u32(code as u32).map(|ch| result.insert(ch));
                code = ft::ffi::FT_Get_Next_Char(face_ptr, code, &mut index);
            }
        }
        result
    }

    // FIXME(Kagami): Profile and optimize this function!
    // TODO(Kagami): Limit too huge textures? We should keep it less than
    // 8k X 8k in general.
    // TODO(Kagami): Add bunch of asserts to check for negative values and
    // overflows.
    /// Construct new BitMap font using provided parameters (this is general
    /// method, called via `from_` helpers).
    fn new<'a>(mut face: ft::Face<'a>, font_size: u8, chars: Option<&[char]>) -> FontResult {
        let needed_chars = chars
            .map(|sl| HashSet::from_iter(sl.iter().cloned()))
            .unwrap_or_else(|| Self::get_all_face_chars(&mut face));
        // Short-circuit.
        if needed_chars.is_empty() {
            return Err(FontError::EmptyFont);
        }

        try!(face.set_pixel_sizes(0, font_size as u32));

        // FreeType representation of rendered glyph 'j':
        //
        // b_left   w
        // +-----+-----+-----+
        // |     |     |     | font_size - bitmap_top()
        // +-----+-----+-----+
        // |     |  x  |     |
        // |     |     |     |
        // |     |  x  |     | bitmap_top()
        // |     |  x  |     |
        // |     |  x  |     |
        // |     |  x  |     |
        // +-----+--x--+-----+
        // |     | x   |     | rows() - bitmap_top()
        // |     |x    |     |
        // +-----------+-----+
        //      advance.x
        //
        // (Read <http://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html>
        // for more details.)
        //
        // Notes:
        // * Width/height of the rendered glyph generally smaller than the the
        //   specified font size
        // * But if we add x/y offsets to the real glyph's dimensions it might
        //   go beyound that limits (e.g. chars like 'j', 'q')
        // * `bottom_left()` may be less than zero for some tight characters
        //   (too push it to the previous one)
        // * Theoretically `bitmap_top()` may be bigger than the `font_size`
        //
        // For simplicity we use fixed box height to store characters in the
        // texture (extended with blank pixels downwards), but width may vary:
        //
        //         width()
        //  +-----+-------+
        //  |  x  |   x   |
        //  |     |       |
        //  |  x  |   x   |
        //  |  x  |   x   | rows()
        //  |  x  |   x   |
        //  |  x  |   x   |
        //  +-----+  x    |
        //  |     | x     |
        //  |     +-------+
        //  |     |       | ch_box_height - rows()
        //  +-----+-------+
        //
        // To construct the optimal texture (i.e. square enought and with box
        // height of the highest character) we need to do several passes.

        // In first pass we collect information about the chars and store their
        // raw bitmap data. It gives us max character height and summary width
        // of all characters.

        let chars_len = needed_chars.len();
        let mut chars_info = HashMap::with_capacity(chars_len);
        let mut sum_image_width = 0;
        let mut max_ch_width = 0;
        let mut ch_box_height = 0;

        debug!("Start building the bitmap (chars: {})", chars_len);

        for ch in needed_chars {
            try!(face.load_char(ch as usize, ft::face::RENDER));
            let glyph = face.glyph();
            let bitmap = glyph.bitmap();
            let ch_width = bitmap.width();
            let ch_height = bitmap.rows();
            let ch_x_offset = glyph.bitmap_left();
            let ch_y_offset = font_size as i32 - glyph.bitmap_top();
            let ch_x_advance = (glyph.advance().x >> 6) as i32;
            let buffer = bitmap.buffer();
            let ch_data = Vec::from(buffer);

            chars_info.insert(ch, BitmapChar {
                x_offset: ch_x_offset,
                y_offset: ch_y_offset,
                x_advance: ch_x_advance,
                width: ch_width,
                height: ch_height,
                // We'll need to fix that fields later:
                tex: [0.0, 0.0],
                tex_width: 0.0,
                tex_height: 0.0,
                data: Some(ch_data),
            });

            sum_image_width += ch_width;
            max_ch_width = max(max_ch_width, ch_width);
            ch_box_height = max(ch_box_height, ch_height);
        }

        // In second pass we map character boxes with varying width onto the
        // fixed quad texture image and build the final texture image.
        //
        // We start with optimist (square) assumption about texture dimensions
        // and adjust the image's height and size while filling the rows.
        //
        // TODO(Kagami): We may try some cool CS algorithm to fit char boxes
        // into the quad texture space with the best level of compression.
        // Though current level of inefficiency is good enough.

        let ideal_image_size = sum_image_width * ch_box_height;
        let ideal_image_width = (ideal_image_size as f32).sqrt() as i32;
        let image_width = max(max_ch_width, ideal_image_width);
        let image_width = (image_width + 3) & !3; // aligning to 4
        let assumed_size = ideal_image_size as f32 * 1.5;
        let assumed_ch_in_row = image_width as f32 / max_ch_width as f32;
        let mut image = Vec::with_capacity(assumed_size as usize);
        let mut chars_row = Vec::with_capacity(assumed_ch_in_row as usize);
        let mut cursor_x = 0;
        let mut image_height = 0;

        let dump_row = |image: &mut Vec<u8>, chars_row: &Vec<(i32, i32, Vec<u8>)>| {
            // Copy character data into the image row by row:
            //
            //       image_width
            // +-------+---------+---+
            // |   x   |    x    |   |
            // |       |         |   |
            // |   x   |    x    |   | ch_box_height
            // |   x   |    x    |   |
            // |   x   |    x    |   |
            // |   x   |   x     |   |
            // |       |  x      |   |
            // +-------+---------+---+
            //                     ^--- image_width - width_ch_i - width_ch_j
            for i in 0..ch_box_height {
                let mut x = 0;
                for &(width, height, ref data) in chars_row {
                   if i >= height {
                       image.extend(repeat(0).take(width as usize));
                   } else {
                       let skip = i * width;
                       debug_assert!(data.len() >= (skip + width) as usize);
                       let line = data.iter().skip(skip as usize).take(width as usize);
                       image.extend(line.cloned());
                   };
                   x += width;
                }
                let cols_to_fill = image_width - x;
                image.extend(repeat(0).take(cols_to_fill as usize));
            }
        };

        debug!("Placing chars onto a plane");

        // Hashmap doesn't preserve the order but we don't need it anyway.
        for (_, ch_info) in chars_info.iter_mut() {
            if cursor_x + ch_info.width > image_width {
                dump_row(&mut image, &chars_row);
                chars_row.clear();
                cursor_x = 0;
                image_height += ch_box_height;
            }
            let ch_data = ch_info.data.take().unwrap();
            chars_row.push((ch_info.width, ch_info.height, ch_data));
            ch_info.tex = [cursor_x as f32, image_height as f32];
            cursor_x += ch_info.width;
        }
        dump_row(&mut image, &chars_row);
        image_height += ch_box_height;

        // Finally, we just precalculate some fields to make it easier to use
        // our font.

        for (_, ch_info) in chars_info.iter_mut() {
            ch_info.tex[0] /= image_width as f32;
            ch_info.tex[1] /= image_height as f32;
            ch_info.tex_width = ch_info.width as f32 / image_width as f32;
            ch_info.tex_height = ch_info.height as f32 / image_height as f32;
        }

        info!("Image width: {}, image height: {}, total size: {}",
            image_width, image_height, image.len());

        Ok(BitmapFont {
            width: image_width as u16,
            height: image_height as u16,
            chars: chars_info,
            image: image,
        })
    }

    pub fn get_width(&self) -> u16 {
        self.width
    }

    pub fn get_height(&self) -> u16 {
        self.height
    }

    /// Return 8-bit texture raw data (grayscale).
    pub fn get_image(&self) -> &[u8] {
        &self.image
    }

    pub fn find_char(&self, ch: char) -> Option<&BitmapChar> {
        self.chars.get(&ch)
    }
}
<commit_msg>Removed width alignment<commit_after>//! Construct bitmap font using FreeType library.
//! Generates raw texture data for the given font and collects information
//! about available font characters to map them into texture.

use std::cmp::max;
use std::iter::{repeat, FromIterator};
use std::collections::{HashMap, HashSet};
use std::char::from_u32;
use ::freetype as ft;
use ::freetype::Face;

#[derive(Debug)]
pub struct BitmapFont {
    width: u16,
    height: u16,
    chars: HashMap<char, BitmapChar>,
    image: Vec<u8>,
}

#[derive(Debug)]
pub struct BitmapChar {
    // Real glyph's coordinates in pixels.
    pub x_offset: i32,
    pub y_offset: i32,
    pub x_advance: i32,
    pub width: i32,
    pub height: i32,
    // Precalculated scaled positions in texture.
    pub tex: [f32; 2],
    pub tex_width: f32,
    pub tex_height: f32,
    // This field is used only while building the texture.
    data: Option<Vec<u8>>,
}

/// Represents possible errors that may occur during the font loading.
#[derive(Debug)]
pub enum FontError {
    /// Character set is empty
    EmptyFont,
    /// FreeType library error
    FreetypeError(ft::Error),
}

impl From<ft::Error> for FontError {
    fn from(e: ft::Error) -> FontError { FontError::FreetypeError(e) }
}

pub type FontResult = Result<BitmapFont, FontError>;

impl BitmapFont {
    pub fn from_path(path: &str, font_size: u8, chars: Option<&[char]>) -> FontResult {
        let library = try!(ft::Library::init());
        let face = try!(library.new_face(path, 0));
        Self::new(face, font_size, chars)
    }

    pub fn from_bytes(data: &[u8], font_size: u8, chars: Option<&[char]>) -> FontResult {
        let library = try!(ft::Library::init());
        let face = try!(library.new_memory_face(data, 0));
        Self::new(face, font_size, chars)
    }

    fn get_all_face_chars<'a>(face: &mut Face<'a>) -> HashSet<char> {
        let mut result = HashSet::new();
        let mut index = 0;
        let mut face_ptr = face.raw_mut();
        unsafe {
            let mut code = ft::ffi::FT_Get_First_Char(face_ptr, &mut index);
            while index != 0 {
                from_u32(code as u32).map(|ch| result.insert(ch));
                code = ft::ffi::FT_Get_Next_Char(face_ptr, code, &mut index);
            }
        }
        result
    }

    // FIXME(Kagami): Profile and optimize this function!
    // TODO(Kagami): Limit too huge textures? We should keep it less than
    // 8k X 8k in general.
    // TODO(Kagami): Add bunch of asserts to check for negative values and
    // overflows.
    /// Construct new BitMap font using provided parameters (this is general
    /// method, called via `from_` helpers).
    fn new<'a>(mut face: ft::Face<'a>, font_size: u8, chars: Option<&[char]>) -> FontResult {
        let needed_chars = chars
            .map(|sl| HashSet::from_iter(sl.iter().cloned()))
            .unwrap_or_else(|| Self::get_all_face_chars(&mut face));
        // Short-circuit.
        if needed_chars.is_empty() {
            return Err(FontError::EmptyFont);
        }

        try!(face.set_pixel_sizes(0, font_size as u32));

        // FreeType representation of rendered glyph 'j':
        //
        // b_left   w
        // +-----+-----+-----+
        // |     |     |     | font_size - bitmap_top()
        // +-----+-----+-----+
        // |     |  x  |     |
        // |     |     |     |
        // |     |  x  |     | bitmap_top()
        // |     |  x  |     |
        // |     |  x  |     |
        // |     |  x  |     |
        // +-----+--x--+-----+
        // |     | x   |     | rows() - bitmap_top()
        // |     |x    |     |
        // +-----------+-----+
        //      advance.x
        //
        // (Read <http://www.freetype.org/freetype2/docs/glyphs/glyphs-3.html>
        // for more details.)
        //
        // Notes:
        // * Width/height of the rendered glyph generally smaller than the the
        //   specified font size
        // * But if we add x/y offsets to the real glyph's dimensions it might
        //   go beyound that limits (e.g. chars like 'j', 'q')
        // * `bottom_left()` may be less than zero for some tight characters
        //   (too push it to the previous one)
        // * Theoretically `bitmap_top()` may be bigger than the `font_size`
        //
        // For simplicity we use fixed box height to store characters in the
        // texture (extended with blank pixels downwards), but width may vary:
        //
        //         width()
        //  +-----+-------+
        //  |  x  |   x   |
        //  |     |       |
        //  |  x  |   x   |
        //  |  x  |   x   | rows()
        //  |  x  |   x   |
        //  |  x  |   x   |
        //  +-----+  x    |
        //  |     | x     |
        //  |     +-------+
        //  |     |       | ch_box_height - rows()
        //  +-----+-------+
        //
        // To construct the optimal texture (i.e. square enought and with box
        // height of the highest character) we need to do several passes.

        // In first pass we collect information about the chars and store their
        // raw bitmap data. It gives us max character height and summary width
        // of all characters.

        let chars_len = needed_chars.len();
        let mut chars_info = HashMap::with_capacity(chars_len);
        let mut sum_image_width = 0;
        let mut max_ch_width = 0;
        let mut ch_box_height = 0;

        debug!("Start building the bitmap (chars: {})", chars_len);

        for ch in needed_chars {
            try!(face.load_char(ch as usize, ft::face::RENDER));
            let glyph = face.glyph();
            let bitmap = glyph.bitmap();
            let ch_width = bitmap.width();
            let ch_height = bitmap.rows();
            let ch_x_offset = glyph.bitmap_left();
            let ch_y_offset = font_size as i32 - glyph.bitmap_top();
            let ch_x_advance = (glyph.advance().x >> 6) as i32;
            let buffer = bitmap.buffer();
            let ch_data = Vec::from(buffer);

            chars_info.insert(ch, BitmapChar {
                x_offset: ch_x_offset,
                y_offset: ch_y_offset,
                x_advance: ch_x_advance,
                width: ch_width,
                height: ch_height,
                // We'll need to fix that fields later:
                tex: [0.0, 0.0],
                tex_width: 0.0,
                tex_height: 0.0,
                data: Some(ch_data),
            });

            sum_image_width += ch_width;
            max_ch_width = max(max_ch_width, ch_width);
            ch_box_height = max(ch_box_height, ch_height);
        }

        // In second pass we map character boxes with varying width onto the
        // fixed quad texture image and build the final texture image.
        //
        // We start with optimist (square) assumption about texture dimensions
        // and adjust the image's height and size while filling the rows.
        //
        // TODO(Kagami): We may try some cool CS algorithm to fit char boxes
        // into the quad texture space with the best level of compression.
        // Though current level of inefficiency is good enough.

        let ideal_image_size = sum_image_width * ch_box_height;
        let ideal_image_width = (ideal_image_size as f32).sqrt() as i32;
        let image_width = max(max_ch_width, ideal_image_width);
        let assumed_size = ideal_image_size as f32 * 1.5;
        let assumed_ch_in_row = image_width as f32 / max_ch_width as f32;
        let mut image = Vec::with_capacity(assumed_size as usize);
        let mut chars_row = Vec::with_capacity(assumed_ch_in_row as usize);
        let mut cursor_x = 0;
        let mut image_height = 0;

        let dump_row = |image: &mut Vec<u8>, chars_row: &Vec<(i32, i32, Vec<u8>)>| {
            // Copy character data into the image row by row:
            //
            //       image_width
            // +-------+---------+---+
            // |   x   |    x    |   |
            // |       |         |   |
            // |   x   |    x    |   | ch_box_height
            // |   x   |    x    |   |
            // |   x   |    x    |   |
            // |   x   |   x     |   |
            // |       |  x      |   |
            // +-------+---------+---+
            //                     ^--- image_width - width_ch_i - width_ch_j
            for i in 0..ch_box_height {
                let mut x = 0;
                for &(width, height, ref data) in chars_row {
                   if i >= height {
                       image.extend(repeat(0).take(width as usize));
                   } else {
                       let skip = i * width;
                       debug_assert!(data.len() >= (skip + width) as usize);
                       let line = data.iter().skip(skip as usize).take(width as usize);
                       image.extend(line.cloned());
                   };
                   x += width;
                }
                let cols_to_fill = image_width - x;
                image.extend(repeat(0).take(cols_to_fill as usize));
            }
        };

        debug!("Placing chars onto a plane");

        // Hashmap doesn't preserve the order but we don't need it anyway.
        for (_, ch_info) in chars_info.iter_mut() {
            if cursor_x + ch_info.width > image_width {
                dump_row(&mut image, &chars_row);
                chars_row.clear();
                cursor_x = 0;
                image_height += ch_box_height;
            }
            let ch_data = ch_info.data.take().unwrap();
            chars_row.push((ch_info.width, ch_info.height, ch_data));
            ch_info.tex = [cursor_x as f32, image_height as f32];
            cursor_x += ch_info.width;
        }
        dump_row(&mut image, &chars_row);
        image_height += ch_box_height;

        // Finally, we just precalculate some fields to make it easier to use
        // our font.

        for (_, ch_info) in chars_info.iter_mut() {
            ch_info.tex[0] /= image_width as f32;
            ch_info.tex[1] /= image_height as f32;
            ch_info.tex_width = ch_info.width as f32 / image_width as f32;
            ch_info.tex_height = ch_info.height as f32 / image_height as f32;
        }

        info!("Image width: {}, image height: {}, total size: {}",
            image_width, image_height, image.len());

        Ok(BitmapFont {
            width: image_width as u16,
            height: image_height as u16,
            chars: chars_info,
            image: image,
        })
    }

    pub fn get_width(&self) -> u16 {
        self.width
    }

    pub fn get_height(&self) -> u16 {
        self.height
    }

    /// Return 8-bit texture raw data (grayscale).
    pub fn get_image(&self) -> &[u8] {
        &self.image
    }

    pub fn find_char(&self, ch: char) -> Option<&BitmapChar> {
        self.chars.get(&ch)
    }
}
<|endoftext|>


<commit_before>use std::io::{Read, Seek};
use std::mem;

use Result;
use truetype::{Tape, Value};
use truetype::compound::*;

/// A font.
#[derive(Default)]
pub struct Font {
    pub offset_table: OffsetTable,
    pub char_mapping: Option<CharMapping>,
    pub font_header: Option<FontHeader>,
    pub horizontal_header: Option<HorizontalHeader>,
    pub horizontal_metrics: Option<HorizontalMetrics>,
    pub maximum_profile: Option<MaximumProfile>,
    pub naming_table: Option<NamingTable>,
    pub postscript: Option<PostScript>,
    pub windows_metrics: Option<WindowsMetrics>,
}

macro_rules! checksum_and_jump(
    ($record:ident, $tape:ident, $process:expr) => ({
        if !try!($record.checksum($tape, $process)) {
            raise!("found a corrupted font table");
        }
        try!($tape.jump($record.offset as u64));
    });
    ($record:ident, $tape:ident) => (
        checksum_and_jump!($record, $tape, |_, word| word);
    );
);

impl Font {
    #[inline]
    pub fn read<T: Read + Seek>(tape: &mut T) -> Result<Font> {
        macro_rules! sort(
            ($records:expr) => ({
                let mut records = $records.iter().collect::<Vec<_>>();
                records.sort_by(|one, two| {
                    priority(Tag(one.tag)).cmp(&priority(Tag(two.tag)))
                });
                records
            });
        );

        let mut font = Font { offset_table: try!(Value::read(tape)), .. Font::default() };
        if Tag::from(font.offset_table.header.version) != Tag::from(b"OTTO") {
            raise!("the font format is invalid");
        }

        for record in sort!(font.offset_table.records) {
            macro_rules! set(
                ($field:ident, $value:expr) => ({
                    checksum_and_jump!(record, tape);
                    font.$field = Some(try!($value));
                });
                ($field:ident) => (set!($field, Value::read(tape)));
            );
            match &Tag(record.tag).into() {
                b"cmap" => set!(char_mapping),
                b"head" => {
                    checksum_and_jump!(record, tape, |i, word| if i == 2 { 0 } else { word });
                    font.font_header = Some(try!(Value::read(tape)));
                },
                b"hhea" => set!(horizontal_header),
                b"hmtx" => {
                    let header = match font.horizontal_header {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    let profile = match font.maximum_profile {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    set!(horizontal_metrics, HorizontalMetrics::read(tape, header, profile));
                },
                b"maxp" => set!(maximum_profile),
                b"name" => set!(naming_table),
                b"post" => set!(postscript),
                b"OS/2" => set!(windows_metrics),
                _ => {},
            }
        }

        Ok(font)
    }
}

fn priority(tag: Tag) -> usize {
    use std::collections::HashMap;
    use std::sync::{Once, ONCE_INIT};

    unsafe {
        static mut PRIORITY: *const HashMap<Tag, usize> = 0 as *const _;
        static ONCE: Once = ONCE_INIT;
        ONCE.call_once(|| {
            let mut map: HashMap<Tag, usize> = HashMap::new();
            map.insert(Tag::from(b"hmtx"), 42);
            PRIORITY = mem::transmute(Box::new(map));
        });
        *(&*PRIORITY).get(&tag).unwrap_or(&0)
    }
}
<commit_msg>Add a missing use<commit_after>use std::io::{Read, Seek};
use std::mem;

use Result;
use truetype::compound::*;
use truetype::primitive::Tag;
use truetype::{Tape, Value};

/// A font.
#[derive(Default)]
pub struct Font {
    pub offset_table: OffsetTable,
    pub char_mapping: Option<CharMapping>,
    pub font_header: Option<FontHeader>,
    pub horizontal_header: Option<HorizontalHeader>,
    pub horizontal_metrics: Option<HorizontalMetrics>,
    pub maximum_profile: Option<MaximumProfile>,
    pub naming_table: Option<NamingTable>,
    pub postscript: Option<PostScript>,
    pub windows_metrics: Option<WindowsMetrics>,
}

macro_rules! checksum_and_jump(
    ($record:ident, $tape:ident, $process:expr) => ({
        if !try!($record.checksum($tape, $process)) {
            raise!("found a corrupted font table");
        }
        try!($tape.jump($record.offset as u64));
    });
    ($record:ident, $tape:ident) => (
        checksum_and_jump!($record, $tape, |_, word| word);
    );
);

impl Font {
    #[inline]
    pub fn read<T: Read + Seek>(tape: &mut T) -> Result<Font> {
        macro_rules! sort(
            ($records:expr) => ({
                let mut records = $records.iter().collect::<Vec<_>>();
                records.sort_by(|one, two| {
                    priority(Tag(one.tag)).cmp(&priority(Tag(two.tag)))
                });
                records
            });
        );

        let mut font = Font { offset_table: try!(Value::read(tape)), .. Font::default() };
        if Tag::from(font.offset_table.header.version) != Tag::from(b"OTTO") {
            raise!("the font format is invalid");
        }

        for record in sort!(font.offset_table.records) {
            macro_rules! set(
                ($field:ident, $value:expr) => ({
                    checksum_and_jump!(record, tape);
                    font.$field = Some(try!($value));
                });
                ($field:ident) => (set!($field, Value::read(tape)));
            );
            match &Tag(record.tag).into() {
                b"cmap" => set!(char_mapping),
                b"head" => {
                    checksum_and_jump!(record, tape, |i, word| if i == 2 { 0 } else { word });
                    font.font_header = Some(try!(Value::read(tape)));
                },
                b"hhea" => set!(horizontal_header),
                b"hmtx" => {
                    let header = match font.horizontal_header {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    let profile = match font.maximum_profile {
                        Some(ref table) => table,
                        _ => continue,
                    };
                    set!(horizontal_metrics, HorizontalMetrics::read(tape, header, profile));
                },
                b"maxp" => set!(maximum_profile),
                b"name" => set!(naming_table),
                b"post" => set!(postscript),
                b"OS/2" => set!(windows_metrics),
                _ => {},
            }
        }

        Ok(font)
    }
}

fn priority(tag: Tag) -> usize {
    use std::collections::HashMap;
    use std::sync::{Once, ONCE_INIT};

    unsafe {
        static mut PRIORITY: *const HashMap<Tag, usize> = 0 as *const _;
        static ONCE: Once = ONCE_INIT;
        ONCE.call_once(|| {
            let mut map: HashMap<Tag, usize> = HashMap::new();
            map.insert(Tag::from(b"hmtx"), 42);
            PRIORITY = mem::transmute(Box::new(map));
        });
        *(&*PRIORITY).get(&tag).unwrap_or(&0)
    }
}
<|endoftext|>


<commit_before>// {
//   Derived from : Bjoern Hoehrmann work
//   Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
//   See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.

pub const UTF8_ACCEPT: u32 = 0;
pub const UTF8_REJECT: u32 = 1;

static UTF8D: &'static [u8] = &[
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
  8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
  0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
  0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
  0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
  1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
  1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
  1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
];

/*
    state UTF8_ACCEPT => initial state or decoding successful
    state UTF8_REJECT => error
    state other => intermediate states need more inputs
*/
#[inline]
pub fn decode_byte(state: &mut u32, byte: u8, codep: &mut u32) -> u32 {

    let cp_type = UTF8D[byte as usize] as u32;

    *codep = if *state != UTF8_ACCEPT {
        (byte & 0x3f) as u32 | (*codep << 6)
    } else {
        (0xff >> cp_type) as u32 & (byte as u32)
    };

    *state = UTF8D[256 + (*state * 16) as usize + cp_type as usize] as u32;
    *state
}

// }

#[inline]
pub fn is_codepoint_start(byte: u8) -> bool {

    if byte < 0x80 {
        return true;
    }

    if byte >= 0xC2 && byte <= 0xDF {
        return true;
    }

    if byte >= 0xC2 && byte <= 0xDF {
        return true;
    }

    if byte >= 0xE0 && byte <= 0xEC {
        return true;
    }

    if byte >= 0xED && byte <= 0xEF {
        return true;
    }

    if byte >= 0xF0 && byte <= 0xF4 {
        return true;
    }

    false
}

// return 0 on error, or the number of written bytes
pub fn encode(codepoint: u32, out: &mut [u8; 4]) -> usize {
    if codepoint < 0x80 {
        out[0] = (codepoint & 0x7F) as u8;
        return 1;
    }

    if codepoint < 0x800 {
        out[0] = 0xC0 | (codepoint >> 6) as u8;
        out[1] = 0x80 | (codepoint & 0x3F) as u8;
        return 2;
    }

    if codepoint < 0xFFFF {
        out[0] = 0xE0 | (codepoint >> 12) as u8;
        out[1] = 0x80 | (codepoint >> 6) as u8;
        out[2] = 0x80 | (codepoint & 0x3F) as u8;
        return 3;
    }

    if codepoint < 0x10FFFF {
        out[0] = 0xF0 | (codepoint >> 18) as u8;
        out[1] = 0x80 | (codepoint >> 12) as u8;
        out[2] = 0x80 | (codepoint >> 6) as u8;
        out[3] = 0x80 | (codepoint & 0x3F) as u8;
        return 4;
    }

    0
}

// TODO: change this with temporary (cp, offset, size) until from_offset
pub fn get_previous_codepoint_start(data: &[u8], from_offset: u64) -> u64 {

    //                 cp    size   offset
    let mut cp_info: [(char, usize, u64); 8] = [('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0)];
    let mut nr_cpinfo = 0;

    // rewind upto 4 bytes
    // and decode forward / save offset
    let mut off = if from_offset > 4 { from_offset - 4 } else { 0 };
    while off < from_offset {
        let (cp, _, size) = get_codepoint(data, off);

        cp_info[nr_cpinfo] = (cp, size, off);
        nr_cpinfo += 1;

        off += size as u64;
    }

    if nr_cpinfo != 0 {
        cp_info[nr_cpinfo - 1].2
    } else {
        from_offset
    }
}

pub fn get_next_codepoint_start(data: &[u8], from_offset: u64) -> u64 {
    let (_, _, size) = get_codepoint(data, from_offset);
    from_offset + size as u64
}

pub fn get_codepoint(data: &[u8], from_offset: u64) -> (char, u64, usize) {

    let mut state = 0;
    let mut codep = 0;
    let mut size = 0;

    for b in data.iter().skip(from_offset as usize) {

        size += 1;
        state = decode_byte(&mut state, *b, &mut codep);
        match state {
            0 => {
                break;
            }
            1 => {
                // decode error : invalid sequence
                codep = 0xfffd;
                size = 1; // force restart @ next byte
                break;
            }
            _ => {}
        }
    }

    // TODO return Result<(char, usize), status> -> state != 1|0 -> need mode data
    (::core::codec::text::u32_to_char(codep), from_offset, size)
}

pub fn get_prev_codepoint(data: &[u8], from_offset: u64) -> (char, u64, usize) {
    let offset = get_previous_codepoint_start(data, from_offset);
    get_codepoint(data, offset)
}

#[test]
fn test_codec_encode() {

    let expect_cp: [u8; 4] = [0xe2, 0x82, 0xac, 0x00];
    let mut mut_cp: [u8; 4] = [0x00, 0x00, 0x00, 0x00];

    let n = encode(0x20ac as u32, &mut mut_cp);
    assert_eq!(n, 3);
    assert_eq!(mut_cp, expect_cp);

}

#[test]
fn test_codec_decode() {

    use core::codec::text::u32_to_char;

    let mut state: u32 = 0;
    let mut codep: u32 = 0;

    let sequence: [u8; 4] = [0xe2, 0x82, 0xac, 0x00];
    for b in &sequence {
        println!("decode byte '{:x}'", *b);
        state = decode_byte(&mut state, *b, &mut codep);
        match state {
            UTF8_ACCEPT => {
                break;
            }
            UTF8_REJECT => {
                println!("invalid utf8 sequence");
                break;
            }
            _ => {
                continue;
            }
        }
    }

    println!("decoded codepoint value {:x}", codep);
    let c = u32_to_char(codep);
    println!("decoded codepoint char {}", c);

    assert_eq!(codep, 0x20ac);
}

#[test]
fn test2_codec_decode() {

    let data: [u8; 27] = [0xe2, 0x82, 0xac, 0xe2, 0x82, 0x61, 0x0a, 0x82, 0xac, 0xe2, 0x82, 0x61,
                          0x0a, 0xac, 0xe2, 0x82, 0x61, 0x0a, 0xe2, 0x82, 0x61, 0x0a, 0x82, 0x61,
                          0x0a, 0x61, 0x0a];

    let mut state: u32 = 0;
    let mut codep: u32 = 0;

    for b in &data {
        println!("decode byte '{:x}'", *b);
        state = decode_byte(&mut state, *b, &mut codep);
        println!("state  '{}'", state);
        match state {
            UTF8_ACCEPT => {
                println!("decoded cp = '{:?}'", codep);
                state = 0;
                codep = 0;
            }
            UTF8_REJECT => {
                println!("invalid utf8 sequence, restart");
                state = 0;
                codep = 0;
                state = decode_byte(&mut state, *b, &mut codep);
                match state {
                    UTF8_ACCEPT => {
                        println!("decoded cp = '{:?}'", codep);
                        state = 0;
                        codep = 0;
                    }
                    UTF8_REJECT => {
                        println!("invalid utf8 sequence, restart");
                        state = 0;
                        codep = 0;
                    }
                    _ => {}

                }
            }

            _ => {
                continue;
            }
        }
    }
}
<commit_msg>remove useless mask<commit_after>// {
//   Derived from : Bjoern Hoehrmann work
//   Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
//   See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.

pub const UTF8_ACCEPT: u32 = 0;
pub const UTF8_REJECT: u32 = 1;

static UTF8D: &'static [u8] = &[
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
  8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
  0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
  0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
  0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
  1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
  1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
  1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
];

/*
    state UTF8_ACCEPT => initial state or decoding successful
    state UTF8_REJECT => error
    state other => intermediate states need more inputs
*/
#[inline]
pub fn decode_byte(state: &mut u32, byte: u8, codep: &mut u32) -> u32 {

    let cp_type = UTF8D[byte as usize] as u32;

    *codep = if *state != UTF8_ACCEPT {
        (byte & 0x3f) as u32 | (*codep << 6)
    } else {
        (0xff >> cp_type) as u32 & (byte as u32)
    };

    *state = UTF8D[256 + (*state * 16) as usize + cp_type as usize] as u32;
    *state
}

// }

#[inline]
pub fn is_codepoint_start(byte: u8) -> bool {

    if byte < 0x80 {
        return true;
    }

    if byte >= 0xC2 && byte <= 0xDF {
        return true;
    }

    if byte >= 0xC2 && byte <= 0xDF {
        return true;
    }

    if byte >= 0xE0 && byte <= 0xEC {
        return true;
    }

    if byte >= 0xED && byte <= 0xEF {
        return true;
    }

    if byte >= 0xF0 && byte <= 0xF4 {
        return true;
    }

    false
}

// return 0 on error, or the number of written bytes
pub fn encode(codepoint: u32, out: &mut [u8; 4]) -> usize {
    if codepoint < 0x80 {
        out[0] = codepoint as u8;
        return 1;
    }

    if codepoint < 0x800 {
        out[0] = 0xC0 | (codepoint >> 6) as u8;
        out[1] = 0x80 | (codepoint & 0x3F) as u8;
        return 2;
    }

    if codepoint < 0xFFFF {
        out[0] = 0xE0 | (codepoint >> 12) as u8;
        out[1] = 0x80 | (codepoint >> 6) as u8;
        out[2] = 0x80 | (codepoint & 0x3F) as u8;
        return 3;
    }

    if codepoint < 0x10FFFF {
        out[0] = 0xF0 | (codepoint >> 18) as u8;
        out[1] = 0x80 | (codepoint >> 12) as u8;
        out[2] = 0x80 | (codepoint >> 6) as u8;
        out[3] = 0x80 | (codepoint & 0x3F) as u8;
        return 4;
    }

    0
}

// TODO: change this with temporary (cp, offset, size) until from_offset
pub fn get_previous_codepoint_start(data: &[u8], from_offset: u64) -> u64 {

    //                 cp    size   offset
    let mut cp_info: [(char, usize, u64); 8] = [('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0),
                                                ('\0', 0, 0)];
    let mut nr_cpinfo = 0;

    // rewind upto 4 bytes
    // and decode forward / save offset
    let mut off = if from_offset > 4 { from_offset - 4 } else { 0 };
    while off < from_offset {
        let (cp, _, size) = get_codepoint(data, off);

        cp_info[nr_cpinfo] = (cp, size, off);
        nr_cpinfo += 1;

        off += size as u64;
    }

    if nr_cpinfo != 0 {
        cp_info[nr_cpinfo - 1].2
    } else {
        from_offset
    }
}

pub fn get_next_codepoint_start(data: &[u8], from_offset: u64) -> u64 {
    let (_, _, size) = get_codepoint(data, from_offset);
    from_offset + size as u64
}

pub fn get_codepoint(data: &[u8], from_offset: u64) -> (char, u64, usize) {

    let mut state = 0;
    let mut codep = 0;
    let mut size = 0;

    for b in data.iter().skip(from_offset as usize) {

        size += 1;
        state = decode_byte(&mut state, *b, &mut codep);
        match state {
            0 => {
                break;
            }
            1 => {
                // decode error : invalid sequence
                codep = 0xfffd;
                size = 1; // force restart @ next byte
                break;
            }
            _ => {}
        }
    }

    // TODO return Result<(char, usize), status> -> state != 1|0 -> need mode data
    (::core::codec::text::u32_to_char(codep), from_offset, size)
}

pub fn get_prev_codepoint(data: &[u8], from_offset: u64) -> (char, u64, usize) {
    let offset = get_previous_codepoint_start(data, from_offset);
    get_codepoint(data, offset)
}

#[test]
fn test_codec_encode() {

    let expect_cp: [u8; 4] = [0xe2, 0x82, 0xac, 0x00];
    let mut mut_cp: [u8; 4] = [0x00, 0x00, 0x00, 0x00];

    let n = encode(0x20ac as u32, &mut mut_cp);
    assert_eq!(n, 3);
    assert_eq!(mut_cp, expect_cp);

}

#[test]
fn test_codec_decode() {

    use core::codec::text::u32_to_char;

    let mut state: u32 = 0;
    let mut codep: u32 = 0;

    let sequence: [u8; 4] = [0xe2, 0x82, 0xac, 0x00];
    for b in &sequence {
        println!("decode byte '{:x}'", *b);
        state = decode_byte(&mut state, *b, &mut codep);
        match state {
            UTF8_ACCEPT => {
                break;
            }
            UTF8_REJECT => {
                println!("invalid utf8 sequence");
                break;
            }
            _ => {
                continue;
            }
        }
    }

    println!("decoded codepoint value {:x}", codep);
    let c = u32_to_char(codep);
    println!("decoded codepoint char {}", c);

    assert_eq!(codep, 0x20ac);
}

#[test]
fn test2_codec_decode() {

    let data: [u8; 27] = [0xe2, 0x82, 0xac, 0xe2, 0x82, 0x61, 0x0a, 0x82, 0xac, 0xe2, 0x82, 0x61,
                          0x0a, 0xac, 0xe2, 0x82, 0x61, 0x0a, 0xe2, 0x82, 0x61, 0x0a, 0x82, 0x61,
                          0x0a, 0x61, 0x0a];

    let mut state: u32 = 0;
    let mut codep: u32 = 0;

    for b in &data {
        println!("decode byte '{:x}'", *b);
        state = decode_byte(&mut state, *b, &mut codep);
        println!("state  '{}'", state);
        match state {
            UTF8_ACCEPT => {
                println!("decoded cp = '{:?}'", codep);
                state = 0;
                codep = 0;
            }
            UTF8_REJECT => {
                println!("invalid utf8 sequence, restart");
                state = 0;
                codep = 0;
                state = decode_byte(&mut state, *b, &mut codep);
                match state {
                    UTF8_ACCEPT => {
                        println!("decoded cp = '{:?}'", codep);
                        state = 0;
                        codep = 0;
                    }
                    UTF8_REJECT => {
                        println!("invalid utf8 sequence, restart");
                        state = 0;
                        codep = 0;
                    }
                    _ => {}

                }
            }

            _ => {
                continue;
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint,RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float};
use rand::task_rng;
use std::vec::Vec;
use std::iter;

fn to_biguint (i : u64) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result
}

/* Since we use Miller-Rabin, this function technically finds if a number is
 * *probably* correct.
 */
fn is_prime(n : &BigUint) -> bool {
    let zero : BigUint = Zero::zero();
    let one : BigUint = One::one();
    let two = one + one;
    assert!(n >= &two);
    let mut s = zero.clone();
    let mut d = n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {
        let one = to_biguint(1);
        let two = to_biguint(2);
        if mod_exp(a, d, n) == one {
            return false
        }
        let mut i : uint = 0;
        loop {
            if &i.to_biguint().unwrap() == s {
                break
            }
            if mod_exp(a, &(pow(two.clone(), i) * *d), n) == n-one {
                return false
            }
            i += 1;
        }
        true
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in Vec::from_slice([0, 4, 6, 10, 12, 16]).iter().map(
        |&i| i.to_biguint().unwrap()) {
        if !is_prime(&(prime + offset)) {
            return false;
        }
    }
    true
}

fn gen_prime(max_val : uint, verbose : bool) -> uint {
    //http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Rust
    fn simple_sieve(limit: uint) -> ~[uint] {
        #[inline]
        fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

        if limit < 2 {
            return ~[];
        }

        let mut primes = Vec::from_elem(limit + 1, true);

        for prime in iter::range_inclusive(2, int_sqrt(limit) + 1) {
            if *primes.get(prime) {
                for multiple in iter::range_step(prime * prime, limit + 1, prime) {
                    *primes.get_mut(multiple) = false
                }
            }
        }
        iter::range_inclusive(2, limit).filter(|&n| *primes.get(n)).collect()
    }

    fn candidate_killed_by (candidate : uint, prime : uint) -> bool {
        let offsets : Vec<uint> = Vec::from_slice([0u, 4u, 6u, 10u, 12u, 16u]);
        for offset in offsets.iter() {
            if (candidate + *offset) % prime == 0 {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : uint, offsets : Vec<uint>, prime : uint, primorial : uint) -> Vec<uint> {
        let mut base : uint = 0u;
        let mut new_offsets : Vec<uint> = Vec::new();
        for _ in range(0u, prime) {
            if base > max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > max_val {
                        break
                    }
                    if !candidate_killed_by(val, prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
        }
        return new_offsets
    }
    let primorial_max : uint = 29u;
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<uint> = Vec::from_slice([97u]);
    for i in simple_sieve(primorial_max).iter() {
        if *i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, *i, primorial);
        primorial = primorial * *i;
    }
    let mut count : uint = 0;
    for o in offsets.iter() {
        if is_valid_pow(&o.to_biguint().unwrap()) {
            count = count + 1;
            if verbose { println!("prime: {}", o) }
        }
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::gen_prime;

    #[test]
    fn gen_prime_is_correct() {
        let v = gen_prime(100000000, false);
        println!("{}", v);
        assert!(v == 81u);
    }
}

fn main() {
    println!("{}", gen_prime(100000000, true));
}<commit_msg>Fast correct POW<commit_after>extern crate num;
extern crate rand;
extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint,RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float};
use rand::task_rng;
use std::vec::Vec;
use std::iter;
use std::clone::Clone;
use std::ops::{Shr, BitAnd};

fn to_biguint (i : u64) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint, T> + BitAnd<T,T>>(base: &T, exponent: &T, modulus: &T) -> T {
    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result
}

/* Since we use Miller-Rabin, this function technically finds if a number is
 * *probably* correct.
 */
fn is_prime(n : &BigUint) -> bool {
    let zero : BigUint = Zero::zero();
    let one : BigUint = One::one();
    let two = one + one;
    assert!(n >= &two);
    let mut s = zero.clone();
    let mut d = n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {
        let one = to_biguint(1);
        let two = to_biguint(2);
        if mod_exp(a, d, n) == one {
            return false
        }
        let mut i : uint = 0;
        loop {
            if &i.to_biguint().unwrap() == s {
                break
            }
            if mod_exp(a, &(pow(two.clone(), i) * *d), n) == n-one {
                return false
            }
            i += 1;
        }
        true
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true
}

fn is_valid_pow(prime : uint) -> bool {
    for &offset in [0u, 4u, 6u, 10u, 12u, 16u].iter() {
        if !fermat_is_prime(prime + offset) {
            return false;
        }
    }
    true
}

fn fermat_is_prime(n : uint) -> bool {
    if n == 2 {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&2, &(n-1), &n) == 1 {
        true
    } else {
        false
    }
}

fn gen_prime(max_val : uint, verbose : bool) -> uint {
    //http://rosettacode.org/wiki/Sieve_of_Eratosthenes#Rust
    fn simple_sieve(limit: uint) -> ~[uint] {
        #[inline]
        fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

        if limit < 2 {
            return ~[];
        }

        let mut primes = Vec::from_elem(limit + 1, true);

        for prime in iter::range_inclusive(2, int_sqrt(limit) + 1) {
            if *primes.get(prime) {
                for multiple in iter::range_step(prime * prime, limit + 1, prime) {
                    *primes.get_mut(multiple) = false
                }
            }
        }
        iter::range_inclusive(2, limit).filter(|&n| *primes.get(n)).collect()
    }

    fn candidate_killed_by (candidate : uint, prime : uint) -> bool {
        let offsets : Vec<uint> = Vec::from_slice([0u, 4u, 6u, 10u, 12u, 16u]);
        for offset in offsets.iter() {
            if (candidate + *offset) % prime == 0 {
                return true;
            }
        }
        false
    }

    fn add_next_prime (max_val : uint, offsets : Vec<uint>, prime : uint, primorial : uint) -> Vec<uint> {
        let mut base : uint = 0u;
        let mut new_offsets : Vec<uint> = Vec::new();
        for _ in range(0u, prime) {
            if base > max_val {
                break
            }
            for o in offsets.iter() {
                    let val = base + *o;
                    if val > max_val {
                        break
                    }
                    if !candidate_killed_by(val, prime) {
                        new_offsets.push(val);
                    }
            }
            base = base + primorial;
        }
        return new_offsets
    }
    let primorial_max : uint = 29u;
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<uint> = Vec::from_slice([97u]);
    for i in simple_sieve(primorial_max).iter() {
        if *i <= primorial_start {
            continue
        }
        offsets = add_next_prime(max_val, offsets, *i, primorial);
        primorial = primorial * *i;
    }
    let mut count : uint = 0;
    for &o in offsets.iter() {
        if is_valid_pow(o) {
            count = count + 1;
            if verbose { println!("prime: {}", o) }
        }
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::gen_prime;

    #[test]
    fn gen_prime_is_correct() {
        let v = gen_prime(1000000000, true);
        println!("{}", v);
        assert!(v == 81u);
    }
}

fn main() {
    println!("{}", gen_prime(1000000000, true));
}<|endoftext|>


<commit_before>use crate::utils::{add_extra_generic_param, MultiFieldData, State, AttrParams};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse::Result, DeriveInput};

/// Provides the hook to expand `#[derive(Into)]` into an implementation of `Into`
pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
    let state = State::with_attr_params(
        input,
        trait_name,
        quote!(::core::convert),
        trait_name.to_lowercase(),
        AttrParams {
            enum_: vec!["ignore", "owned", "ref", "ref_mut"],
            variant: vec!["ignore", "owned", "ref", "ref_mut"],
            struct_: vec!["ignore", "owned", "ref", "ref_mut"],
            field: vec!["ignore"],
        },
    )?;
    let MultiFieldData {
        variant_info,
        field_types,
        field_idents,
        input_type,
        ..
    } = state.enabled_fields_data();

    let mut tokens = TokenStream::new();

    for ref_type in variant_info.ref_types() {
        let reference = ref_type.reference();
        let lifetime = ref_type.lifetime();
        let reference_with_lifetime = ref_type.reference_with_lifetime();

        let generics_impl;
        let (_, ty_generics, where_clause) = input.generics.split_for_impl();
        let (impl_generics, _, _) = if ref_type.is_ref() {
            generics_impl = add_extra_generic_param(&input.generics, lifetime);
            generics_impl.split_for_impl()
        } else {
            input.generics.split_for_impl()
        };

        let into = quote! {
            impl#impl_generics ::core::convert::From<#reference_with_lifetime #input_type#ty_generics> for
                (#(#reference_with_lifetime #field_types),*) #where_clause {

                #[allow(unused_variables)]
                #[inline]
                fn from(original: #reference_with_lifetime #input_type#ty_generics) -> (#(#reference_with_lifetime #field_types),*) {
                    (#(#reference original.#field_idents),*)
                }
            }
        };
        into.to_tokens(&mut tokens);
    }
    Ok(tokens)
}
<commit_msg>Rustfmt<commit_after>use crate::utils::{add_extra_generic_param, AttrParams, MultiFieldData, State};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse::Result, DeriveInput};

/// Provides the hook to expand `#[derive(Into)]` into an implementation of `Into`
pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
    let state = State::with_attr_params(
        input,
        trait_name,
        quote!(::core::convert),
        trait_name.to_lowercase(),
        AttrParams {
            enum_: vec!["ignore", "owned", "ref", "ref_mut"],
            variant: vec!["ignore", "owned", "ref", "ref_mut"],
            struct_: vec!["ignore", "owned", "ref", "ref_mut"],
            field: vec!["ignore"],
        },
    )?;
    let MultiFieldData {
        variant_info,
        field_types,
        field_idents,
        input_type,
        ..
    } = state.enabled_fields_data();

    let mut tokens = TokenStream::new();

    for ref_type in variant_info.ref_types() {
        let reference = ref_type.reference();
        let lifetime = ref_type.lifetime();
        let reference_with_lifetime = ref_type.reference_with_lifetime();

        let generics_impl;
        let (_, ty_generics, where_clause) = input.generics.split_for_impl();
        let (impl_generics, _, _) = if ref_type.is_ref() {
            generics_impl = add_extra_generic_param(&input.generics, lifetime);
            generics_impl.split_for_impl()
        } else {
            input.generics.split_for_impl()
        };

        let into = quote! {
            impl#impl_generics ::core::convert::From<#reference_with_lifetime #input_type#ty_generics> for
                (#(#reference_with_lifetime #field_types),*) #where_clause {

                #[allow(unused_variables)]
                #[inline]
                fn from(original: #reference_with_lifetime #input_type#ty_generics) -> (#(#reference_with_lifetime #field_types),*) {
                    (#(#reference original.#field_idents),*)
                }
            }
        };
        into.to_tokens(&mut tokens);
    }
    Ok(tokens)
}
<|endoftext|>


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

//! Values that should be shared across all modules, without necessarily
//! having to pass them all over the place, but aren't consensus values.
//! should be used sparingly.

/// An enum collecting sets of parameters used throughout the
/// code wherever mining is needed. This should allow for
/// different sets of parameters for different purposes,
/// e.g. CI, User testing, production values

use std::sync::RwLock;
use consensus::PROOFSIZE;
use consensus::DEFAULT_SIZESHIFT;
use consensus::COINBASE_MATURITY;
use consensus::{MEDIAN_TIME_WINDOW, INITIAL_DIFFICULTY,
	BLOCK_TIME_SEC, DIFFICULTY_ADJUST_WINDOW};
use core::target::Difficulty;
use consensus::TargetError;

/// Define these here, as they should be developer-set, not really tweakable
/// by users

/// Automated testing sizeshift
pub const AUTOMATED_TESTING_SIZESHIFT: u8 = 10;

/// Automated testing proof size
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 4;

/// User testing sizeshift
pub const USER_TESTING_SIZESHIFT: u8 = 16;

/// User testing proof size
pub const USER_TESTING_PROOF_SIZE: usize = 42;

/// Automated testing coinbase maturity
pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3;

/// User testing coinbase maturity
pub const USER_TESTING_COINBASE_MATURITY: u64 = 3;

/// Testing initial block difficulty
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;

/// Testing initial block difficulty, testnet 2
/// we want to overestimate here as well
/// Setting to 1 for development, but should be 1000 at T2 launch
pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1;

/// The target is the 32-bytes hash block hashes must be lower than.
pub const MAX_PROOF_TARGET: [u8; 8] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// We want to slow this right down for user testing at cuckoo 16, so pick a smaller max
pub const MAX_PROOF_TARGET_TESTING: [u8; 8] = [0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainTypes {
	/// For CI testing
	AutomatedTesting,

	/// For User testing
	UserTesting,

  /// First test network
	Testnet1,

	/// Second test network
	Testnet2,

  /// Main production network
	Mainnet,
}

impl Default for ChainTypes {
	fn default() -> ChainTypes {
		ChainTypes::UserTesting
	}
}

lazy_static!{
	/// The mining parameter mode
	pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
			RwLock::new(ChainTypes::Mainnet);
}

/// Set the mining mode
pub fn set_mining_mode(mode: ChainTypes) {
	let mut param_ref = CHAIN_TYPE.write().unwrap();
	*param_ref = mode;
}

/// The sizeshift
pub fn sizeshift() -> u8 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
		ChainTypes::UserTesting => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet1 => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet2 => DEFAULT_SIZESHIFT,
		ChainTypes::Mainnet => DEFAULT_SIZESHIFT,
	}
}

/// The proofsize
pub fn proofsize() -> usize {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
		ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
		ChainTypes::Testnet1 => PROOFSIZE,
		ChainTypes::Testnet2 => PROOFSIZE,
		ChainTypes::Mainnet => PROOFSIZE,
	}
}

/// Coinbase maturity
pub fn coinbase_maturity() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
		ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
		ChainTypes::Testnet1 => COINBASE_MATURITY,
		ChainTypes::Testnet2 => COINBASE_MATURITY,
		ChainTypes::Mainnet => COINBASE_MATURITY,
	}
}

/// Max Proof Target
pub fn max_proof_target() -> [u8; 8] {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::UserTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet1 => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet2 => MAX_PROOF_TARGET,
		ChainTypes::Mainnet => MAX_PROOF_TARGET,
	}
}

/// Initial mining difficulty
pub fn initial_block_difficulty() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet1 => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet2 => TESTNET2_INITIAL_DIFFICULTY,
		ChainTypes::Mainnet => INITIAL_DIFFICULTY,
	}
}

/// Are we in automated testing mode?
pub fn is_automated_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::AutomatedTesting == *param_ref
}

/// Are we in user testing mode?
pub fn is_user_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::UserTesting == *param_ref
}

/// Are we in production mode (a live public network)?
pub fn is_production_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::Testnet1 == *param_ref ||
    ChainTypes::Testnet2 == *param_ref ||
    ChainTypes::Mainnet == *param_ref
}

/// Helper function to get a nonce known to create a valid POW on
/// the genesis block, to prevent it taking ages. Should be fine for now
/// as the genesis block POW solution turns out to be the same for every new
/// block chain at the moment
pub fn get_genesis_nonce() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		// won't make a difference
		ChainTypes::AutomatedTesting => 0,
		// Magic nonce for current genesis block at cuckoo16
		ChainTypes::UserTesting => 27944,
		// Magic nonce for genesis block for testnet2 (cuckoo30)

		_ => panic!("Pre-set"),
	}
}

/// Converts an iterator of block difficulty data to more a more mangeable vector and pads
/// if needed (which will) only be needed for the first few blocks after genesis

pub fn difficulty_data_to_vector<T>(cursor: T) -> Vec<Result<(u64, Difficulty), TargetError>>
	where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>> {
	// Convert iterator to vector, so we can append to it if necessary
	let needed_block_count = (MEDIAN_TIME_WINDOW + DIFFICULTY_ADJUST_WINDOW) as usize;
	let mut last_n: Vec<Result<(u64, Difficulty), TargetError>> = cursor.into_iter()
		.take(needed_block_count)
		.collect();

	// Sort blocks from earliest to latest (to keep conceptually easier)
	last_n.reverse();
	// Only needed just after blockchain launch... basically ensures there's
	// always enough data by simulating perfectly timed pre-genesis
	// blocks at the genesis difficulty as needed.
	let block_count_difference = needed_block_count - last_n.len();
	if block_count_difference > 0 {
		// Collect any real data we have
		let mut live_intervals:Vec<(u64, Difficulty)> = last_n.iter()
			.map(|b| (b.clone().unwrap().0, b.clone().unwrap().1))
			.collect();
		for i in (1..live_intervals.len()).rev() {
			live_intervals[i].0=live_intervals[i].0-live_intervals[i-1].0;
		}
		//
		// Remove genesis "interval"
		if live_intervals.len() > 1 {
			live_intervals.remove(0);
		} else {
			//if it's just genesis, adjust the interval
			live_intervals[0].0 = BLOCK_TIME_SEC;
		}
		let mut interval_index = live_intervals.len() - 1;
		let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0;
		// fill in simulated blocks, repeating whatever pattern we've obtained from
		// real data
		// if we have, say, 15 blocks so far with intervals of I1..I15, then
		// the 71-15=56 pre genesis blocks will have
		// intervals/difficulties I1..I15 I1..I15 I1..I15 I1..I11
		for _ in 0..block_count_difference {
			last_ts = last_ts - live_intervals[interval_index].0;
			let last_diff = &live_intervals[interval_index].1;
			last_n.insert(0, Ok((last_ts, last_diff.clone())));
			interval_index = match interval_index {
				0 => live_intervals.len()-1,
				_ => interval_index - 1,
			};
		}
	}
	last_n
}
<commit_msg>minor test fix (#669)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Values that should be shared across all modules, without necessarily
//! having to pass them all over the place, but aren't consensus values.
//! should be used sparingly.

/// An enum collecting sets of parameters used throughout the
/// code wherever mining is needed. This should allow for
/// different sets of parameters for different purposes,
/// e.g. CI, User testing, production values

use std::sync::RwLock;
use consensus::PROOFSIZE;
use consensus::DEFAULT_SIZESHIFT;
use consensus::COINBASE_MATURITY;
use consensus::{MEDIAN_TIME_WINDOW, INITIAL_DIFFICULTY,
	BLOCK_TIME_SEC, DIFFICULTY_ADJUST_WINDOW};
use core::target::Difficulty;
use consensus::TargetError;

/// Define these here, as they should be developer-set, not really tweakable
/// by users

/// Automated testing sizeshift
pub const AUTOMATED_TESTING_SIZESHIFT: u8 = 10;

/// Automated testing proof size
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 4;

/// User testing sizeshift
pub const USER_TESTING_SIZESHIFT: u8 = 16;

/// User testing proof size
pub const USER_TESTING_PROOF_SIZE: usize = 42;

/// Automated testing coinbase maturity
pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3;

/// User testing coinbase maturity
pub const USER_TESTING_COINBASE_MATURITY: u64 = 3;

/// Testing initial block difficulty
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;

/// Testing initial block difficulty, testnet 2
/// we want to overestimate here as well
/// Setting to 1 for development, but should be 1000 at T2 launch
pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1;

/// The target is the 32-bytes hash block hashes must be lower than.
pub const MAX_PROOF_TARGET: [u8; 8] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// We want to slow this right down for user testing at cuckoo 16, so pick a smaller max
pub const MAX_PROOF_TARGET_TESTING: [u8; 8] = [0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];

/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainTypes {
	/// For CI testing
	AutomatedTesting,

	/// For User testing
	UserTesting,

  /// First test network
	Testnet1,

	/// Second test network
	Testnet2,

  /// Main production network
	Mainnet,
}

impl Default for ChainTypes {
	fn default() -> ChainTypes {
		ChainTypes::UserTesting
	}
}

lazy_static!{
	/// The mining parameter mode
	pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
			RwLock::new(ChainTypes::Mainnet);
}

/// Set the mining mode
pub fn set_mining_mode(mode: ChainTypes) {
	let mut param_ref = CHAIN_TYPE.write().unwrap();
	*param_ref = mode;
}

/// The sizeshift
pub fn sizeshift() -> u8 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
		ChainTypes::UserTesting => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet1 => USER_TESTING_SIZESHIFT,
		ChainTypes::Testnet2 => DEFAULT_SIZESHIFT,
		ChainTypes::Mainnet => DEFAULT_SIZESHIFT,
	}
}

/// The proofsize
pub fn proofsize() -> usize {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
		ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
		ChainTypes::Testnet1 => PROOFSIZE,
		ChainTypes::Testnet2 => PROOFSIZE,
		ChainTypes::Mainnet => PROOFSIZE,
	}
}

/// Coinbase maturity
pub fn coinbase_maturity() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
		ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
		ChainTypes::Testnet1 => COINBASE_MATURITY,
		ChainTypes::Testnet2 => COINBASE_MATURITY,
		ChainTypes::Mainnet => COINBASE_MATURITY,
	}
}

/// Max Proof Target
pub fn max_proof_target() -> [u8; 8] {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::UserTesting => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet1 => MAX_PROOF_TARGET_TESTING,
		ChainTypes::Testnet2 => MAX_PROOF_TARGET,
		ChainTypes::Mainnet => MAX_PROOF_TARGET,
	}
}

/// Initial mining difficulty
pub fn initial_block_difficulty() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet1 => TESTING_INITIAL_DIFFICULTY,
		ChainTypes::Testnet2 => TESTNET2_INITIAL_DIFFICULTY,
		ChainTypes::Mainnet => INITIAL_DIFFICULTY,
	}
}

/// Are we in automated testing mode?
pub fn is_automated_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::AutomatedTesting == *param_ref
}

/// Are we in user testing mode?
pub fn is_user_testing_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::UserTesting == *param_ref
}

/// Are we in production mode (a live public network)?
pub fn is_production_mode() -> bool {
	let param_ref = CHAIN_TYPE.read().unwrap();
	ChainTypes::Testnet1 == *param_ref ||
    ChainTypes::Testnet2 == *param_ref ||
    ChainTypes::Mainnet == *param_ref
}

/// Helper function to get a nonce known to create a valid POW on
/// the genesis block, to prevent it taking ages. Should be fine for now
/// as the genesis block POW solution turns out to be the same for every new
/// block chain at the moment
pub fn get_genesis_nonce() -> u64 {
	let param_ref = CHAIN_TYPE.read().unwrap();
	match *param_ref {
		// won't make a difference
		ChainTypes::AutomatedTesting => 0,
		// Magic nonce for current genesis block at cuckoo16
		ChainTypes::UserTesting => 27944,
		// Magic nonce for genesis block for testnet2 (cuckoo30)

		_ => panic!("Pre-set"),
	}
}

/// Converts an iterator of block difficulty data to more a more mangeable vector and pads
/// if needed (which will) only be needed for the first few blocks after genesis

pub fn difficulty_data_to_vector<T>(cursor: T) -> Vec<Result<(u64, Difficulty), TargetError>>
	where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>> {
	// Convert iterator to vector, so we can append to it if necessary
	let needed_block_count = (MEDIAN_TIME_WINDOW + DIFFICULTY_ADJUST_WINDOW) as usize;
	let mut last_n: Vec<Result<(u64, Difficulty), TargetError>> = cursor.into_iter()
		.take(needed_block_count)
		.collect();

	// Sort blocks from earliest to latest (to keep conceptually easier)
	last_n.reverse();
	// Only needed just after blockchain launch... basically ensures there's
	// always enough data by simulating perfectly timed pre-genesis
	// blocks at the genesis difficulty as needed.
	let block_count_difference = needed_block_count - last_n.len();
	if block_count_difference > 0 {
		// Collect any real data we have
		let mut live_intervals:Vec<(u64, Difficulty)> = last_n.iter()
			.map(|b| (b.clone().unwrap().0, b.clone().unwrap().1))
			.collect();
		for i in (1..live_intervals.len()).rev() {
			// prevents issues with very fast automated test chains
			if live_intervals[i-1].0 > live_intervals[i].0 {
				live_intervals[i].0 = 0;
			} else {
				live_intervals[i].0=live_intervals[i].0-live_intervals[i-1].0;
			}
		}
		//
		// Remove genesis "interval"
		if live_intervals.len() > 1 {
			live_intervals.remove(0);
		} else {
			//if it's just genesis, adjust the interval
			live_intervals[0].0 = BLOCK_TIME_SEC;
		}
		let mut interval_index = live_intervals.len() - 1;
		let mut last_ts = last_n.first().as_ref().unwrap().as_ref().unwrap().0;
		// fill in simulated blocks, repeating whatever pattern we've obtained from
		// real data
		// if we have, say, 15 blocks so far with intervals of I1..I15, then
		// the 71-15=56 pre genesis blocks will have
		// intervals/difficulties I1..I15 I1..I15 I1..I15 I1..I11
		for _ in 0..block_count_difference {
			last_ts = last_ts - live_intervals[interval_index].0;
			let last_diff = &live_intervals[interval_index].1;
			last_n.insert(0, Ok((last_ts, last_diff.clone())));
			interval_index = match interval_index {
				0 => live_intervals.len()-1,
				_ => interval_index - 1,
			};
		}
	}
	last_n
}
<|endoftext|>


<commit_before>#![deny(warnings)]
extern crate hyper;
extern crate pretty_env_logger;

use std::env;
use std::io::{self, Write};

use hyper::{Body, Client, Request};
use hyper::rt::{self, Future, Stream};

fn main() {
    pretty_env_logger::init();

    // Some simple CLI args requirements...
    let url = match env::args().nth(1) {
        Some(url) => url,
        None => {
            println!("Usage: client <url>");
            return;
        }
    };

    // HTTPS requires picking a TLS implementation, so give a better
    // warning if the user tries to request an 'https' URL.
    let url = url.parse::<hyper::Uri>().unwrap();
    if url.scheme_part().map(|s| s.as_ref()) != Some("http") {
        println!("This example only works with 'http' URLs.");
        return;
    }

    rt::run(rt::lazy(move || {
        let client = Client::new();

        client
            // Fetch the url...
            .get(url)
            // And then, if we get a response back...
            .and_then(|res| {
                println!("Response: {}", res.status());
                println!("Headers: {:#?}", res.headers());

                // The body is a stream, and for_each returns a new Future
                // when the stream is finished, and calls the closure on
                // each chunk of the body...
                res.into_body().for_each(|chunk| {
                    io::stdout().write_all(&chunk)
                        .map_err(|e| panic!("example expects stdout is open, error={}", e))
                })
            })
            // If all good, just tell the user...
            .map(|_| {
                println!("\n\nDone.");
            })
            // If there was an error, let the user know...
            .map_err(|err| {
                eprintln!("Error {}", err);
            })
    }));
}
<commit_msg>fix(examples): remove unused imports from examples/client.rs<commit_after>#![deny(warnings)]
extern crate hyper;
extern crate pretty_env_logger;

use std::env;
use std::io::{self, Write};

use hyper::Client;
use hyper::rt::{self, Future, Stream};

fn main() {
    pretty_env_logger::init();

    // Some simple CLI args requirements...
    let url = match env::args().nth(1) {
        Some(url) => url,
        None => {
            println!("Usage: client <url>");
            return;
        }
    };

    // HTTPS requires picking a TLS implementation, so give a better
    // warning if the user tries to request an 'https' URL.
    let url = url.parse::<hyper::Uri>().unwrap();
    if url.scheme_part().map(|s| s.as_ref()) != Some("http") {
        println!("This example only works with 'http' URLs.");
        return;
    }

    rt::run(rt::lazy(move || {
        let client = Client::new();

        client
            // Fetch the url...
            .get(url)
            // And then, if we get a response back...
            .and_then(|res| {
                println!("Response: {}", res.status());
                println!("Headers: {:#?}", res.headers());

                // The body is a stream, and for_each returns a new Future
                // when the stream is finished, and calls the closure on
                // each chunk of the body...
                res.into_body().for_each(|chunk| {
                    io::stdout().write_all(&chunk)
                        .map_err(|e| panic!("example expects stdout is open, error={}", e))
                })
            })
            // If all good, just tell the user...
            .map(|_| {
                println!("\n\nDone.");
            })
            // If there was an error, let the user know...
            .map_err(|err| {
                eprintln!("Error {}", err);
            })
    }));
}
<|endoftext|>


<commit_before>//! Futures task based helpers

#![allow(clippy::mutex_atomic)]

use std::future::Future;
use std::mem;
use std::ops;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use tokio_stream::Stream;

/// TODO: dox
pub fn spawn<T>(task: T) -> Spawn<T> {
    Spawn {
        task: MockTask::new(),
        future: Box::pin(task),
    }
}

/// Future spawned on a mock task
#[derive(Debug)]
pub struct Spawn<T> {
    task: MockTask,
    future: Pin<Box<T>>,
}

/// Mock task
///
/// A mock task is able to intercept and track wake notifications.
#[derive(Debug, Clone)]
struct MockTask {
    waker: Arc<ThreadWaker>,
}

#[derive(Debug)]
struct ThreadWaker {
    state: Mutex<usize>,
    condvar: Condvar,
}

const IDLE: usize = 0;
const WAKE: usize = 1;
const SLEEP: usize = 2;

impl<T> Spawn<T> {
    /// Consumes `self` returning the inner value
    pub fn into_inner(self) -> T
    where
        T: Unpin,
    {
        *Pin::into_inner(self.future)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    pub fn is_woken(&self) -> bool {
        self.task.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    pub fn waker_ref_count(&self) -> usize {
        self.task.waker_ref_count()
    }

    /// Enter the task context
    pub fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>, Pin<&mut T>) -> R,
    {
        let fut = self.future.as_mut();
        self.task.enter(|cx| f(cx, fut))
    }
}

impl<T: Unpin> ops::Deref for Spawn<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.future
    }
}

impl<T: Unpin> ops::DerefMut for Spawn<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.future
    }
}

impl<T: Future> Spawn<T> {
    /// Polls a future
    pub fn poll(&mut self) -> Poll<T::Output> {
        let fut = self.future.as_mut();
        self.task.enter(|cx| fut.poll(cx))
    }
}

impl<T: Stream> Spawn<T> {
    /// Polls a stream
    pub fn poll_next(&mut self) -> Poll<Option<T::Item>> {
        let stream = self.future.as_mut();
        self.task.enter(|cx| stream.poll_next(cx))
    }
}

impl<T: Future> Future for Spawn<T> {
    type Output = T::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.future.as_mut().poll(cx)
    }
}

impl<T: Stream> Stream for Spawn<T> {
    type Item = T::Item;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.future.as_mut().poll_next(cx)
    }
}

impl MockTask {
    /// Creates new mock task
    fn new() -> Self {
        MockTask {
            waker: Arc::new(ThreadWaker::new()),
        }
    }

    /// Runs a closure from the context of the task.
    ///
    /// Any wake notifications resulting from the execution of the closure are
    /// tracked.
    fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>) -> R,
    {
        self.waker.clear();
        let waker = self.waker();
        let mut cx = Context::from_waker(&waker);

        f(&mut cx)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    fn is_woken(&self) -> bool {
        self.waker.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    fn waker_ref_count(&self) -> usize {
        Arc::strong_count(&self.waker)
    }

    fn waker(&self) -> Waker {
        unsafe {
            let raw = to_raw(self.waker.clone());
            Waker::from_raw(raw)
        }
    }
}

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

impl ThreadWaker {
    fn new() -> Self {
        ThreadWaker {
            state: Mutex::new(IDLE),
            condvar: Condvar::new(),
        }
    }

    /// Clears any previously received wakes, avoiding potential spurious
    /// wake notifications. This should only be called immediately before running the
    /// task.
    fn clear(&self) {
        *self.state.lock().unwrap() = IDLE;
    }

    fn is_woken(&self) -> bool {
        match *self.state.lock().unwrap() {
            IDLE => false,
            WAKE => true,
            _ => unreachable!(),
        }
    }

    fn wake(&self) {
        // First, try transitioning from IDLE -> NOTIFY, this does not require a lock.
        let mut state = self.state.lock().unwrap();
        let prev = *state;

        if prev == WAKE {
            return;
        }

        *state = WAKE;

        if prev == IDLE {
            return;
        }

        // The other half is sleeping, so we wake it up.
        assert_eq!(prev, SLEEP);
        self.condvar.notify_one();
    }
}

static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop_waker);

unsafe fn to_raw(waker: Arc<ThreadWaker>) -> RawWaker {
    RawWaker::new(Arc::into_raw(waker) as *const (), &VTABLE)
}

unsafe fn from_raw(raw: *const ()) -> Arc<ThreadWaker> {
    Arc::from_raw(raw as *const ThreadWaker)
}

unsafe fn clone(raw: *const ()) -> RawWaker {
    let waker = from_raw(raw);

    // Increment the ref count
    mem::forget(waker.clone());

    to_raw(waker)
}

unsafe fn wake(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();
}

unsafe fn wake_by_ref(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();

    // We don't actually own a reference to the unparker
    mem::forget(waker);
}

unsafe fn drop_waker(raw: *const ()) {
    let _ = from_raw(raw);
}
<commit_msg>test: Improve `tokio_test::task` docs (#5132)<commit_after>//! Futures task based helpers to easily test futures and manually written futures.
//!
//! The [`Spawn`] type is used as a mock task harness that allows you to poll futures
//! without needing to setup pinning or context. Any future can be polled but if the
//! future requires the tokio async context you will need to ensure that you poll the
//! [`Spawn`] within a tokio context, this means that as long as you are inside the
//! runtime it will work and you can poll it via [`Spawn`].
//!
//! [`Spawn`] also supports [`Stream`] to call `poll_next` without pinning
//! or context.
//!
//! In addition to circumventing the need for pinning and context, [`Spawn`] also tracks
//! the amount of times the future/task was woken. This can be useful to track if some
//! leaf future notified the root task correctly.
//!
//! # Example
//!
//! ```
//! use tokio_test::task;
//!
//! let fut = async {};
//!
//! let mut task = task::spawn(fut);
//!
//! assert!(task.poll().is_ready(), "Task was not ready!");
//! ```

#![allow(clippy::mutex_atomic)]

use std::future::Future;
use std::mem;
use std::ops;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use tokio_stream::Stream;

/// Spawn a future into a [`Spawn`] which wraps the future in a mocked executor.
///
/// This can be used to spawn a [`Future`] or a [`Stream`].
///
/// For more information, check the module docs.
pub fn spawn<T>(task: T) -> Spawn<T> {
    Spawn {
        task: MockTask::new(),
        future: Box::pin(task),
    }
}

/// Future spawned on a mock task that can be used to poll the future or stream
/// without needing pinning or context types.
#[derive(Debug)]
pub struct Spawn<T> {
    task: MockTask,
    future: Pin<Box<T>>,
}

#[derive(Debug, Clone)]
struct MockTask {
    waker: Arc<ThreadWaker>,
}

#[derive(Debug)]
struct ThreadWaker {
    state: Mutex<usize>,
    condvar: Condvar,
}

const IDLE: usize = 0;
const WAKE: usize = 1;
const SLEEP: usize = 2;

impl<T> Spawn<T> {
    /// Consumes `self` returning the inner value
    pub fn into_inner(self) -> T
    where
        T: Unpin,
    {
        *Pin::into_inner(self.future)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    pub fn is_woken(&self) -> bool {
        self.task.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    pub fn waker_ref_count(&self) -> usize {
        self.task.waker_ref_count()
    }

    /// Enter the task context
    pub fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>, Pin<&mut T>) -> R,
    {
        let fut = self.future.as_mut();
        self.task.enter(|cx| f(cx, fut))
    }
}

impl<T: Unpin> ops::Deref for Spawn<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.future
    }
}

impl<T: Unpin> ops::DerefMut for Spawn<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.future
    }
}

impl<T: Future> Spawn<T> {
    /// If `T` is a [`Future`] then poll it. This will handle pinning and the context
    /// type for the future.
    pub fn poll(&mut self) -> Poll<T::Output> {
        let fut = self.future.as_mut();
        self.task.enter(|cx| fut.poll(cx))
    }
}

impl<T: Stream> Spawn<T> {
    /// If `T` is a [`Stream`] then poll_next it. This will handle pinning and the context
    /// type for the stream.
    pub fn poll_next(&mut self) -> Poll<Option<T::Item>> {
        let stream = self.future.as_mut();
        self.task.enter(|cx| stream.poll_next(cx))
    }
}

impl<T: Future> Future for Spawn<T> {
    type Output = T::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.future.as_mut().poll(cx)
    }
}

impl<T: Stream> Stream for Spawn<T> {
    type Item = T::Item;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.future.as_mut().poll_next(cx)
    }
}

impl MockTask {
    /// Creates new mock task
    fn new() -> Self {
        MockTask {
            waker: Arc::new(ThreadWaker::new()),
        }
    }

    /// Runs a closure from the context of the task.
    ///
    /// Any wake notifications resulting from the execution of the closure are
    /// tracked.
    fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>) -> R,
    {
        self.waker.clear();
        let waker = self.waker();
        let mut cx = Context::from_waker(&waker);

        f(&mut cx)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    fn is_woken(&self) -> bool {
        self.waker.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    fn waker_ref_count(&self) -> usize {
        Arc::strong_count(&self.waker)
    }

    fn waker(&self) -> Waker {
        unsafe {
            let raw = to_raw(self.waker.clone());
            Waker::from_raw(raw)
        }
    }
}

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

impl ThreadWaker {
    fn new() -> Self {
        ThreadWaker {
            state: Mutex::new(IDLE),
            condvar: Condvar::new(),
        }
    }

    /// Clears any previously received wakes, avoiding potential spurious
    /// wake notifications. This should only be called immediately before running the
    /// task.
    fn clear(&self) {
        *self.state.lock().unwrap() = IDLE;
    }

    fn is_woken(&self) -> bool {
        match *self.state.lock().unwrap() {
            IDLE => false,
            WAKE => true,
            _ => unreachable!(),
        }
    }

    fn wake(&self) {
        // First, try transitioning from IDLE -> NOTIFY, this does not require a lock.
        let mut state = self.state.lock().unwrap();
        let prev = *state;

        if prev == WAKE {
            return;
        }

        *state = WAKE;

        if prev == IDLE {
            return;
        }

        // The other half is sleeping, so we wake it up.
        assert_eq!(prev, SLEEP);
        self.condvar.notify_one();
    }
}

static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop_waker);

unsafe fn to_raw(waker: Arc<ThreadWaker>) -> RawWaker {
    RawWaker::new(Arc::into_raw(waker) as *const (), &VTABLE)
}

unsafe fn from_raw(raw: *const ()) -> Arc<ThreadWaker> {
    Arc::from_raw(raw as *const ThreadWaker)
}

unsafe fn clone(raw: *const ()) -> RawWaker {
    let waker = from_raw(raw);

    // Increment the ref count
    mem::forget(waker.clone());

    to_raw(waker)
}

unsafe fn wake(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();
}

unsafe fn wake_by_ref(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();

    // We don't actually own a reference to the unparker
    mem::forget(waker);
}

unsafe fn drop_waker(raw: *const ()) {
    let _ = from_raw(raw);
}
<|endoftext|>