<commit_before>use std;
use libc::SIGSEGV;

use execstate::ExecState;
use os::signal::Trap;

pub fn read_execstate(uc: *const u8) -> ExecState {
    let mut es: ExecState = unsafe { std::mem::uninitialized() };

    unsafe {
        let uc = uc as *mut ucontext_t;
        let mc = &(*uc).uc_mcontext;

        es.pc = mc.regs[REG_RIP];
        es.sp = mc.regs[REG_RSP];
        es.ra = 0;

        for i in 0..es.regs.len() {
            let src = reg2ucontext(i);
            let dest = i;

            es.regs[dest] = mc.regs[src];
        }
    }

    es
}

pub fn write_execstate(es: &ExecState, uc: *mut u8) {
    unsafe {
        let uc = uc as *mut ucontext_t;
        let mc = &mut (*uc).uc_mcontext;

        mc.regs[REG_RIP] = es.pc;
        mc.regs[REG_RSP] = es.sp;

        for i in 0..es.regs.len() {
            let src = i;
            let dest = reg2ucontext(i);

            mc.regs[dest] = es.regs[src];
        }
    }
}

/// Dora uses same index for register as CPU,
// but the indices in mcontext are different and need to be mapped
fn reg2ucontext(reg: usize) -> usize {
    match reg {
        0 => REG_RAX,
        1 => REG_RCX,
        2 => REG_RDX,
        3 => REG_RBX,
        4 => REG_RSP,
        5 => REG_RBP,
        6 => REG_RSI,
        7 => REG_RDI,
        8 => REG_R8,
        9 => REG_R9,
        10 => REG_R10,
        11 => REG_R11,
        12 => REG_R12,
        13 => REG_R13,
        14 => REG_R14,
        15 => REG_R15,
        _ => unreachable!(),
    }
}

pub fn detect_trap(signo: i32, es: &ExecState) -> Option<Trap> {
    if signo == SIGSEGV {
        cpu::read_trap(&es)
    } else {
        None
    }
}

#[repr(C)]
struct ucontext_t {
    _ignore: [u64; 5],
    pub uc_mcontext: mcontext_t,
}

#[repr(C)]
struct mcontext_t {
    pub regs: [usize; 23],
}

const REG_R8: usize = 0;
const REG_R9: usize = 1;
const REG_R10: usize = 2;
const REG_R11: usize = 3;
const REG_R12: usize = 4;
const REG_R13: usize = 5;
const REG_R14: usize = 6;
const REG_R15: usize = 7;
const REG_RDI: usize = 8;
const REG_RSI: usize = 9;
const REG_RBP: usize = 10;
const REG_RBX: usize = 11;
const REG_RDX: usize = 12;
const REG_RAX: usize = 13;
const REG_RCX: usize = 14;
const REG_RSP: usize = 15;
const REG_RIP: usize = 16;
<commit_msg>fix linux build<commit_after>use std;
use libc::SIGSEGV;

use cpu;
use execstate::ExecState;
use os::signal::Trap;

pub fn read_execstate(uc: *const u8) -> ExecState {
    let mut es: ExecState = unsafe { std::mem::uninitialized() };

    unsafe {
        let uc = uc as *mut ucontext_t;
        let mc = &(*uc).uc_mcontext;

        es.pc = mc.regs[REG_RIP];
        es.sp = mc.regs[REG_RSP];
        es.ra = 0;

        for i in 0..es.regs.len() {
            let src = reg2ucontext(i);
            let dest = i;

            es.regs[dest] = mc.regs[src];
        }
    }

    es
}

pub fn write_execstate(es: &ExecState, uc: *mut u8) {
    unsafe {
        let uc = uc as *mut ucontext_t;
        let mc = &mut (*uc).uc_mcontext;

        mc.regs[REG_RIP] = es.pc;
        mc.regs[REG_RSP] = es.sp;

        for i in 0..es.regs.len() {
            let src = i;
            let dest = reg2ucontext(i);

            mc.regs[dest] = es.regs[src];
        }
    }
}

/// Dora uses same index for register as CPU,
// but the indices in mcontext are different and need to be mapped
fn reg2ucontext(reg: usize) -> usize {
    match reg {
        0 => REG_RAX,
        1 => REG_RCX,
        2 => REG_RDX,
        3 => REG_RBX,
        4 => REG_RSP,
        5 => REG_RBP,
        6 => REG_RSI,
        7 => REG_RDI,
        8 => REG_R8,
        9 => REG_R9,
        10 => REG_R10,
        11 => REG_R11,
        12 => REG_R12,
        13 => REG_R13,
        14 => REG_R14,
        15 => REG_R15,
        _ => unreachable!(),
    }
}

pub fn detect_trap(signo: i32, es: &ExecState) -> Option<Trap> {
    if signo == SIGSEGV {
        cpu::read_trap(&es)
    } else {
        None
    }
}

#[repr(C)]
struct ucontext_t {
    _ignore: [u64; 5],
    pub uc_mcontext: mcontext_t,
}

#[repr(C)]
struct mcontext_t {
    pub regs: [usize; 23],
}

const REG_R8: usize = 0;
const REG_R9: usize = 1;
const REG_R10: usize = 2;
const REG_R11: usize = 3;
const REG_R12: usize = 4;
const REG_R13: usize = 5;
const REG_R14: usize = 6;
const REG_R15: usize = 7;
const REG_RDI: usize = 8;
const REG_RSI: usize = 9;
const REG_RBP: usize = 10;
const REG_RBX: usize = 11;
const REG_RDX: usize = 12;
const REG_RAX: usize = 13;
const REG_RCX: usize = 14;
const REG_RSP: usize = 15;
const REG_RIP: usize = 16;
<|endoftext|>


<commit_before>
use std::u32;
use std::fmt::Write;

extern crate crypto;
use crypto::md5::Md5;
use crypto::digest::Digest;

// Returns the sixth character if the first five are zero
fn sixth_char_after_zeros(hex_str: &str) -> Option<char> {

    for i in 0..5 {
        if hex_str.as_bytes()[i] != '0' as u8 {
            return None;
        }
    }
    Some(hex_str.as_bytes()[5] as char)
}

fn main() {

    // Puzzle input
    let door_id = "reyedfim";

    let mut hasher = Md5::new();
    let mut password = "".to_owned();
    let target_password_length = 8;

    // Loop through door_id + [0..max] to find hashes that
    // start with five zeros
    for i in 0..u32::max_value() {
        let mut test_value = String::new();
        let _ = write!(test_value,"{}{}", door_id, i);
        hasher.reset();
        hasher.input(test_value.as_bytes());

        let hash_result = hasher.result_str();
        if let Some(next_char) = sixth_char_after_zeros(&hash_result) {
            println!("{}", hash_result);
            password.push(next_char);
        }

        if password.len() == target_password_length {
            break;
        }
    }
    if password.len() < target_password_length {
        println!("Could not find password. Latest attempt: {}", password)
    } else {
        println!("Part1: password = '{}'", password);
    }
    assert!(password == "f97c354d");
}

#[test]
fn test1() {
    let test_value = "abc3231929";
    let mut hasher = Md5::new();
    hasher.input(test_value.as_bytes());
    let hash_result = hasher.result_str();
    println!("{}", hash_result);

    let test_value2 = "abc5017308";
    hasher.reset();
    hasher.input(test_value2.as_bytes());
    let hash_result2 = hasher.result_str();
    println!("{}", hash_result2);
}<commit_msg>Optimize day 5, part 1 for speed<commit_after>
use std::u32;
use std::fmt::Write;

extern crate crypto;
use crypto::md5::Md5;
use crypto::digest::Digest;

// It takes two hex digits to make a byte, so check
// the first 2.5 bytes for zero values
fn first_five_hex_zero(input: &[u8; 16]) -> bool {
    let sum = (input[0] as u32) + (input[1] as u32) + (input[2] as u32 >> 4);
    sum == 0
}

fn get_sixth_hex_char(input: &[u8; 16]) -> char {
    let mut buff = String::new();
    let _ = write!(buff,"{:x}", input[2]);
    buff.as_bytes()[0] as char
}

fn main() {

    // Puzzle input
    let door_id = "reyedfim";

    let mut hasher = Md5::new();
    let mut password = "".to_owned();
    let target_password_length = 8;

    // Static buffer to hold the result
    let mut hash_output = [0u8; 16];

    // Loop through door_id + [0..max] to find hashes that
    // start with five zeros
    for i in 0..u32::max_value() {
        let mut test_value = String::new();
        let _ = write!(test_value,"{}{}", door_id, i);
        hasher.reset();
        hasher.input(test_value.as_bytes());
        hasher.result(&mut hash_output);

        if first_five_hex_zero(&hash_output) {
            let next_char = get_sixth_hex_char(&hash_output);
            //let next_char = hash_output[0] as char;
            password.push(next_char);
        }

        if password.len() >= target_password_length {
            break;
        }
    }
    if password.len() < target_password_length {
        println!("Could not find password. Latest attempt: {}", password)
    } else {
        println!("Part1: password = '{}'", password);
    }
    assert!(password == "f97c354d");
}

#[test]
fn test1() {
    let test_value = "abc3231929";
    let mut hasher = Md5::new();
    hasher.input(test_value.as_bytes());
    let hash_result = hasher.result_str();
    println!("{}", hash_result);

    let mut buff = [0;16];
    hasher.result(&mut buff);
    let test_char1 = get_sixth_hex_char(&buff);
    println!("{}", test_char1);
    //assert!(test_char1 == '');

    let test_value2 = "abc5017308";
    hasher.reset();
    hasher.input(test_value2.as_bytes());
    let hash_result2 = hasher.result_str();
    println!("{}", hash_result2);
}
<|endoftext|>


<commit_before>//! Background layer rendering

use super::{Ppu, Rgb};

/// BG layer scanline cache.
///
/// This cache stores a prerendered scanline of all background layers. The cache is created lazily
/// (when BG layer pixels are looked up), so we will not waste time caching a disabled BG layer.
///
/// TODO: Unimplemented
#[derive(Default)]
pub struct BgCache {
}

/// Collected background settings
struct BgSettings {
    /// Mosaic pixel size (1-16). 1 = Normal pixels.
    /// FIXME: I think there's a difference between disabled and enabled with 1x1 mosaic size in
    /// some modes (highres presumably)
    #[allow(dead_code)] // FIXME NYI
    mosaic: u8,
    /// Tilemap word address in VRAM
    /// "Starting at the tilemap address, the first $800 bytes are for tilemap A. Then come the
    /// $800 bytes for B, then C then D."
    tilemap_word_addr: u16,
    /// When `true`, this BGs tilemaps are repeated sideways
    tilemap_mirror_h: bool,
    /// When `true`, this BGs tilemaps are repeated downwards
    tilemap_mirror_v: bool,
    /// If `true`, BG tiles are 16x16 pixels. If `false`, they are 8x8 pixels.
    tile_size_16: bool,
    /// Character Data start address in VRAM
    chr_addr: u16,
    /// Horizontal scroll offset. Moves the BG layer to the left by some number of pixels.
    hofs: u16,
    /// Vertical scroll offset. Moves the BG layer up by some number of pixels.
    vofs: u16,
}

/// Unpacked tilemap entry for internal (rendering) use.
///
/// A tilemap entry is 2 bytes large and contains informations about a single background layer tile.
struct TilemapEntry {
    /// Flip this tile vertically (flips top and down of the tile)
    vflip: bool,
    /// Flip horizontally (flips left and right side)
    hflip: bool,
    /// Priority bit (0-1)
    priority: u8,
    /// Tile palette (0-7)
    palette: u8,
    /// Index into the character/tile data, where the actual tile character data is stored in
    /// bitplanes (10 bits)
    tile_number: u16,
}

impl Ppu {
    /// Determines whether the given BG layer (1-4) is enabled
    fn bg_enabled(&self, bg: u8) -> bool { self.tm & (1 << (bg - 1)) != 0 }

    /// Reads the tilemap entry at the given VRAM word address.
    ///     vhopppcc cccccccc (high, low)
    ///     v/h        = Vertical/Horizontal flip this tile.
    ///     o          = Tile priority.
    ///     ppp        = Tile palette base.
    ///     cccccccccc = Tile number.
    fn tilemap_entry(&self, word_address: u16) -> TilemapEntry {
        let byte_address = word_address << 1;
        let lo = self.vram[byte_address];
        let hi = self.vram[byte_address + 1];

        TilemapEntry {
            vflip: hi & 0x80 != 0,
            hflip: hi & 0x40 != 0,
            priority: (hi & 0x20) >> 5,
            palette: (hi & 0x1c) >> 2,
            tile_number: ((hi as u16 & 0x03) << 8) | lo as u16,
        }
    }

    /// Collects properties of a background layer
    fn bg_settings(&self, bg: u8) -> BgSettings {
        // The BGxSC register for our background layer
        let bgsc = match bg {
            1 => self.bg1sc,
            2 => self.bg2sc,
            3 => self.bg3sc,
            4 => self.bg4sc,
            _ => unreachable!(),
        };
        // Chr (Tileset, not Tilemap) start (word?) address >> 12
        let chr = match bg {
            1 => self.bg12nba & 0x0f,
            2 => (self.bg12nba & 0xf0) >> 4,
            3 => self.bg34nba & 0x0f,
            4 => (self.bg34nba & 0xf0) >> 4,
            _ => unreachable!(),
        };
        let (hofs, vofs) = match bg {
            1 => (self.bg1hofs, self.bg1vofs),
            2 => (self.bg2hofs, self.bg2vofs),
            3 => (self.bg3hofs, self.bg3vofs),
            4 => (self.bg4hofs, self.bg4vofs),
            _ => unreachable!(),
        };

        BgSettings {
            mosaic: if self.mosaic & (1 << (bg-1)) == 0 {
                1
            } else {
                ((self.mosaic & 0xf0) >> 4) + 1
            },
            // FIXME: This looks more like the byte address to me!
            tilemap_word_addr: ((bgsc as u16 & 0xfc) >> 2) << 10,
            tilemap_mirror_h: bgsc & 0b01 == 0, // inverted bit value
            tilemap_mirror_v: bgsc & 0b10 == 0, // inverted bit value
            tile_size_16: match self.bg_mode() {
                // "If the BG character size for BG1/BG2/BG3/BG4 bit is set, then the BG is made of
                // 16x16 tiles. Otherwise, 8x8 tiles are used. However, note that Modes 5 and 6
                // always use 16-pixel wide tiles, and Mode 7 always uses 8x8 tiles."
                5 | 6 => true,
                7 => false,
                _ => {
                    // BGMODE: `4321----` (`-` = not relevant here) - Use 16x16 tiles?
                    self.bgmode & (1 << (bg + 3)) != 0
                }
            },
            chr_addr: (chr as u16) << 12,
            hofs: hofs,
            vofs: vofs,
        }
    }

    /// Returns the number of color bits in the given BG layer in the current BG mode (2, 4, 7 or
    /// 8). To get the number of colors, use `1 << color_bits_for_bg`.
    ///
    /// Table of colors for BG layers (not what this function returns!). `X` denotes a BG for
    /// offset-per-tile data.
    /// ```text
    /// Mode    # Colors for BG
    ///          1   2   3   4
    /// ======---=---=---=---=
    /// 0        4   4   4   4
    /// 1       16  16   4   -
    /// 2       16  16   X   -
    /// 3      256  16   -   -
    /// 4      256   4   X   -
    /// 5       16   4   -   -
    /// 6       16   -   X   -
    /// 7      256   -   -   -
    /// 7EXTBG 256 128   -   -
    /// ```
    fn color_bits_for_bg(&self, bg: u8) -> u8 {
        match (self.bg_mode(), bg) {
            (0, _) => 2,
            (1, 1) |
            (1, 2) => 4,
            (1, 3) => 2,
            (2, _) => 4,
            (3, 1) => 8,
            (3, 2) => 4,
            (4, 1) => 8,
            (4, 2) => 2,
            (5, 1) => 4,
            (5, 2) => 2,
            (6, _) => 4,
            (7, _) => panic!("NYI: color_count_for_bg for mode 7"),   // (make sure to handle EXTBG)
            _ => unreachable!(),
        }
    }

    /// Calculates the palette base index for a tile in the given background layer. `palette_num`
    /// is the palette number stored in the tilemap entry (the 3 `p` bits).
    fn palette_base_for_bg_tile(&self, bg: u8, palette_num: u8) -> u8 {
        debug_assert!(bg >= 1 && bg <= 4);
        match (self.bg_mode(), bg) {
            (0, _) => palette_num * 4 + (bg - 1) * 32,
            (1, _) |
            (5, _) => palette_num * (1 << self.color_bits_for_bg(bg) as u8),
            (2, _) => palette_num * 16,
            (3, 1) => 0,
            (3, 2) => palette_num * 16,
            (4, 1) => 0,
            (4, 2) => palette_num * 4,
            (6, _) => palette_num * 16, // BG1 has 16 colors
            (7, _) => panic!("NYI: palette_base_for_bg_tile for mode 7"),
            _ => unreachable!(),
        }
    }

    /// Main entry point into the BG layer renderer.
    ///
    /// Lookup the color of the given background layer (1-4) at the current pixel, using the given
    /// priority (0-1) only. This will also scroll backgrounds accordingly.
    ///
    /// Returns `None` if the pixel is transparent, `Some(Rgb)` otherwise.
    pub fn lookup_bg_color(&mut self, bg_num: u8, prio: u8) -> Option<Rgb> {
        debug_assert!(bg_num >= 1 && bg_num <= 4);
        debug_assert!(prio == 0 || prio == 1);
        if !self.bg_enabled(bg_num) { return None }

        // Apply BG scrolling and get the tile coordinates
        // FIXME Apply mosaic filter
        // FIXME Fix this: "Note that many games will set their vertical scroll values to -1 rather
        // than 0. This is because the SNES loads OBJ data for each scanline during the previous
        // scanline. The very first line, though, wouldn’t have any OBJ data loaded! So the SNES
        // doesn’t actually output scanline 0, although it does everything to render it. These
        // games want the first line of their tilemap to be the first line output, so they set
        // their VOFS registers in this manner. Note that an interlace screen needs -2 rather than
        // -1 to properly correct for the missing line 0 (and an emulator would need to add 2
        // instead of 1 to account for this)."
        let x = self.x;
        let y = self.scanline;
        let bg = self.bg_settings(bg_num);
        let tile_size = if bg.tile_size_16 { 16 } else { 8 };
        let (hofs, vofs) = (bg.hofs, bg.vofs);
        let tile_x = x.wrapping_add(hofs) / tile_size as u16;
        let tile_y = y.wrapping_add(vofs) / tile_size as u16;
        let off_x = (x.wrapping_add(hofs) % tile_size as u16) as u8;
        let off_y = (y.wrapping_add(vofs) % tile_size as u16) as u8;
        let (sx, sy) = (!bg.tilemap_mirror_h, !bg.tilemap_mirror_v);

        // Calculate the VRAM word address, where the tilemap entry for our tile is stored
        // FIXME Check if this really is correct
        let tilemap_entry_word_address =
            bg.tilemap_word_addr |
            ((tile_y & 0x1f) << 5) |
            (tile_x & 0x1f) |
            if sy {(tile_y & 0x20) << if sx {6} else {5}} else {0} |
            if sx {(tile_x & 0x20) << 5} else {0};
        let tilemap_entry = self.tilemap_entry(tilemap_entry_word_address);
        if tilemap_entry.priority != prio { return None }

        let color_bits = self.color_bits_for_bg(bg_num);
        if color_bits == 8 {
            // can use direct color mode
            debug_assert!(self.cgwsel & 0x01 == 0, "NYI: direct color mode");
        }

        let bitplane_start_addr =
            (bg.chr_addr << 1) +
            (tilemap_entry.tile_number * 8 * color_bits as u16);   // 8 bytes per bitplane

        let palette_base = self.palette_base_for_bg_tile(bg_num, tilemap_entry.palette);
        let palette_index = self.read_chr_entry(color_bits,
                                                bitplane_start_addr,
                                                tile_size,
                                                (off_x, off_y),
                                                (tilemap_entry.vflip, tilemap_entry.hflip));

        match palette_index {
            0 => None,
            _ => Some(self.cgram.get_color(palette_base + palette_index)),
        }
    }
}
<commit_msg>Cache BG layer data per-scanline<commit_after>//! Background layer rendering

use super::{Ppu, Rgb};

/// BG layer scanline cache.
///
/// This cache stores a prerendered scanline of all background layers. The cache is created lazily
/// (when BG layer pixels are looked up), so we will not waste time caching a disabled BG layer.
#[derive(Default)]
pub struct BgCache {
    layers: [BgLayerCache; 4],
}

/// Data that's stored in the BG layer caches for a single pixel
#[derive(Copy, Clone, Default)]
struct CachedPixel {
    // These are just copied from `TilemapEntry`.

    /// Tile priority bit (0-1)
    priority: u8,
    /// Tile palette (0-7)
    palette: u8,
    /// Index into the character/tile data, where the actual tile character data is stored in
    /// bitplanes (10 bits)
    tile_number: u16,
    /// Precalculated color of the pixel (15-bit RGB). `None` = transparent.
    color: Option<Rgb>,
}

/// BG cache for a single layer
struct BgLayerCache {
    /// Whether this cache contains valid data. If `false`, the cache will be refreshed on next
    /// access.
    valid: bool,
    /// Stores the prerendered scanline
    scanline: [CachedPixel; super::SCREEN_WIDTH as usize],
}

impl Default for BgLayerCache {
    fn default() -> Self {
        BgLayerCache {
            valid: false,
            scanline: [CachedPixel::default(); super::SCREEN_WIDTH as usize],
        }
    }
}

impl BgLayerCache {
    /// Invalidates the cache of this layer, causing it to be rebuilt on next access.
    #[allow(dead_code)] // FIXME Use in the right locations
    fn invalidate(&mut self) {
        self.valid = false;
    }
}

impl BgCache {
    /// Invalidates the BG cache of all layers
    fn invalidate_all(&mut self) {
        self.layers[0].valid = false;
        self.layers[1].valid = false;
        self.layers[2].valid = false;
        self.layers[3].valid = false;
    }
}

/// Collected background settings
struct BgSettings {
    /// Mosaic pixel size (1-16). 1 = Normal pixels.
    /// FIXME: I think there's a difference between disabled and enabled with 1x1 mosaic size in
    /// some modes (highres presumably)
    #[allow(dead_code)] // FIXME NYI
    mosaic: u8,
    /// Tilemap word address in VRAM
    /// "Starting at the tilemap address, the first $800 bytes are for tilemap A. Then come the
    /// $800 bytes for B, then C then D."
    tilemap_word_addr: u16,
    /// When `true`, this BGs tilemaps are repeated sideways
    tilemap_mirror_h: bool,
    /// When `true`, this BGs tilemaps are repeated downwards
    tilemap_mirror_v: bool,
    /// If `true`, BG tiles are 16x16 pixels. If `false`, they are 8x8 pixels.
    tile_size_16: bool,
    /// Character Data start address in VRAM
    chr_addr: u16,
    /// Horizontal scroll offset. Moves the BG layer to the left by some number of pixels.
    hofs: u16,
    /// Vertical scroll offset. Moves the BG layer up by some number of pixels.
    vofs: u16,
}

/// Unpacked tilemap entry for internal (rendering) use.
///
/// A tilemap entry is 2 bytes large and contains informations about a single background layer tile.
struct TilemapEntry {
    /// Flip this tile vertically (flips top and down of the tile)
    vflip: bool,
    /// Flip horizontally (flips left and right side)
    hflip: bool,
    /// Priority bit (0-1)
    priority: u8,
    /// Tile palette (0-7)
    palette: u8,
    /// Index into the character/tile data, where the actual tile character data is stored in
    /// bitplanes (10 bits)
    tile_number: u16,
}

impl Ppu {
    /// Determines whether the given BG layer (1-4) is enabled
    fn bg_enabled(&self, bg: u8) -> bool { self.tm & (1 << (bg - 1)) != 0 }

    /// Reads the tilemap entry at the given VRAM word address.
    ///     vhopppcc cccccccc (high, low)
    ///     v/h        = Vertical/Horizontal flip this tile.
    ///     o          = Tile priority.
    ///     ppp        = Tile palette base.
    ///     cccccccccc = Tile number.
    fn tilemap_entry(&self, word_address: u16) -> TilemapEntry {
        let byte_address = word_address << 1;
        let lo = self.vram[byte_address];
        let hi = self.vram[byte_address + 1];

        TilemapEntry {
            vflip: hi & 0x80 != 0,
            hflip: hi & 0x40 != 0,
            priority: (hi & 0x20) >> 5,
            palette: (hi & 0x1c) >> 2,
            tile_number: ((hi as u16 & 0x03) << 8) | lo as u16,
        }
    }

    /// Collects properties of a background layer
    fn bg_settings(&self, bg: u8) -> BgSettings {
        // The BGxSC register for our background layer
        let bgsc = match bg {
            1 => self.bg1sc,
            2 => self.bg2sc,
            3 => self.bg3sc,
            4 => self.bg4sc,
            _ => unreachable!(),
        };
        // Chr (Tileset, not Tilemap) start (word?) address >> 12
        let chr = match bg {
            1 => self.bg12nba & 0x0f,
            2 => (self.bg12nba & 0xf0) >> 4,
            3 => self.bg34nba & 0x0f,
            4 => (self.bg34nba & 0xf0) >> 4,
            _ => unreachable!(),
        };
        let (hofs, vofs) = match bg {
            1 => (self.bg1hofs, self.bg1vofs),
            2 => (self.bg2hofs, self.bg2vofs),
            3 => (self.bg3hofs, self.bg3vofs),
            4 => (self.bg4hofs, self.bg4vofs),
            _ => unreachable!(),
        };

        BgSettings {
            mosaic: if self.mosaic & (1 << (bg-1)) == 0 {
                1
            } else {
                ((self.mosaic & 0xf0) >> 4) + 1
            },
            // FIXME: This looks more like the byte address to me!
            tilemap_word_addr: ((bgsc as u16 & 0xfc) >> 2) << 10,
            tilemap_mirror_h: bgsc & 0b01 == 0, // inverted bit value
            tilemap_mirror_v: bgsc & 0b10 == 0, // inverted bit value
            tile_size_16: match self.bg_mode() {
                // "If the BG character size for BG1/BG2/BG3/BG4 bit is set, then the BG is made of
                // 16x16 tiles. Otherwise, 8x8 tiles are used. However, note that Modes 5 and 6
                // always use 16-pixel wide tiles, and Mode 7 always uses 8x8 tiles."
                5 | 6 => true,
                7 => false,
                _ => {
                    // BGMODE: `4321----` (`-` = not relevant here) - Use 16x16 tiles?
                    self.bgmode & (1 << (bg + 3)) != 0
                }
            },
            chr_addr: (chr as u16) << 12,
            hofs: hofs,
            vofs: vofs,
        }
    }

    /// Returns the number of color bits in the given BG layer in the current BG mode (2, 4, 7 or
    /// 8). To get the number of colors, use `1 << color_bits_for_bg`.
    ///
    /// Table of colors for BG layers (not what this function returns!). `X` denotes a BG for
    /// offset-per-tile data.
    /// ```text
    /// Mode    # Colors for BG
    ///          1   2   3   4
    /// ======---=---=---=---=
    /// 0        4   4   4   4
    /// 1       16  16   4   -
    /// 2       16  16   X   -
    /// 3      256  16   -   -
    /// 4      256   4   X   -
    /// 5       16   4   -   -
    /// 6       16   -   X   -
    /// 7      256   -   -   -
    /// 7EXTBG 256 128   -   -
    /// ```
    fn color_bits_for_bg(&self, bg: u8) -> u8 {
        match (self.bg_mode(), bg) {
            (0, _) => 2,
            (1, 1) |
            (1, 2) => 4,
            (1, 3) => 2,
            (2, _) => 4,
            (3, 1) => 8,
            (3, 2) => 4,
            (4, 1) => 8,
            (4, 2) => 2,
            (5, 1) => 4,
            (5, 2) => 2,
            (6, _) => 4,
            (7, _) => panic!("NYI: color_count_for_bg for mode 7"),   // (make sure to handle EXTBG)
            _ => unreachable!(),
        }
    }

    /// Calculates the palette base index for a tile in the given background layer. `palette_num`
    /// is the palette number stored in the tilemap entry (the 3 `p` bits).
    fn palette_base_for_bg_tile(&self, bg: u8, palette_num: u8) -> u8 {
        debug_assert!(bg >= 1 && bg <= 4);
        match (self.bg_mode(), bg) {
            (0, _) => palette_num * 4 + (bg - 1) * 32,
            (1, _) |
            (5, _) => palette_num * (1 << self.color_bits_for_bg(bg) as u8),
            (2, _) => palette_num * 16,
            (3, 1) => 0,
            (3, 2) => palette_num * 16,
            (4, 1) => 0,
            (4, 2) => palette_num * 4,
            (6, _) => palette_num * 16, // BG1 has 16 colors
            (7, _) => panic!("NYI: palette_base_for_bg_tile for mode 7"),
            _ => unreachable!(),
        }
    }

    /// Main entry point into the BG layer renderer.
    ///
    /// Lookup the color of the given background layer (1-4) at the current pixel, using the given
    /// priority (0-1) only. This will also scroll backgrounds accordingly.
    ///
    /// Returns `None` if the pixel is transparent, `Some(Rgb)` otherwise.
    pub fn lookup_bg_color(&mut self, bg_num: u8, prio: u8) -> Option<Rgb> {
        debug_assert!(bg_num >= 1 && bg_num <= 4);
        debug_assert!(prio == 0 || prio == 1);
        if !self.bg_enabled(bg_num) { return None }

        if self.x == 0 {
            // Before we draw the first pixel, make sure that we invalidate the cache so it is
            // rebuilt first.
            self.bg_cache.invalidate_all();
        }

        if !self.bg_cache.layers[bg_num as usize - 1].valid {
            // Render the current scanline of this BG layer into the cache.
            // We render starting at `self.x` (the pixel we actually need) until the end of the
            // scanline. Note that this means that the `valid` flag is only relevant for the
            // leftover part of the scanline, not the entire cached scanline.

            // Apply BG scrolling and get the tile coordinates
            // FIXME Apply mosaic filter
            // FIXME Fix this: "Note that many games will set their vertical scroll values to -1 rather
            // than 0. This is because the SNES loads OBJ data for each scanline during the previous
            // scanline. The very first line, though, wouldn’t have any OBJ data loaded! So the SNES
            // doesn’t actually output scanline 0, although it does everything to render it. These
            // games want the first line of their tilemap to be the first line output, so they set
            // their VOFS registers in this manner. Note that an interlace screen needs -2 rather than
            // -1 to properly correct for the missing line 0 (and an emulator would need to add 2
            // instead of 1 to account for this)."
            let mut x = self.x;
            let y = self.scanline;
            let bg = self.bg_settings(bg_num);
            let tile_size = if bg.tile_size_16 { 16 } else { 8 };
            let (hofs, vofs) = (bg.hofs, bg.vofs);
            let (sx, sy) = (!bg.tilemap_mirror_h, !bg.tilemap_mirror_v);

            let color_bits = self.color_bits_for_bg(bg_num);
            if color_bits == 8 {
                // can use direct color mode
                debug_assert!(self.cgwsel & 0x01 == 0, "NYI: direct color mode");
            }

            let mut tile_x = x.wrapping_add(hofs) / tile_size as u16;
            let tile_y = y.wrapping_add(vofs) / tile_size as u16;
            let mut off_x = (x.wrapping_add(hofs) % tile_size as u16) as u8;
            let off_y = (y.wrapping_add(vofs) % tile_size as u16) as u8;

            while x < super::SCREEN_WIDTH as u16 {
                // Render current tile (`tile_x`) starting at `off_x` until the end of the tile,
                // then go to next tile and set `off_x = 0`

                // Calculate the VRAM word address, where the tilemap entry for our tile is stored
                let tilemap_entry_word_address =
                    bg.tilemap_word_addr |
                    ((tile_y & 0x1f) << 5) |
                    (tile_x & 0x1f) |
                    if sy {(tile_y & 0x20) << if sx {6} else {5}} else {0} |
                    if sx {(tile_x & 0x20) << 5} else {0};
                let tilemap_entry = self.tilemap_entry(tilemap_entry_word_address);

                let bitplane_start_addr =
                    (bg.chr_addr << 1) +
                    (tilemap_entry.tile_number * 8 * color_bits as u16);   // 8 bytes per bitplane

                let palette_base = self.palette_base_for_bg_tile(bg_num, tilemap_entry.palette);

                while off_x < tile_size && x < super::SCREEN_WIDTH as u16 {
                    let palette_index = self.read_chr_entry(color_bits,
                                                            bitplane_start_addr,
                                                            tile_size,
                                                            (off_x, off_y),
                                                            (tilemap_entry.vflip, tilemap_entry.hflip));

                    let rgb = match palette_index {
                        0 => None,
                        _ => Some(self.cgram.get_color(palette_base + palette_index)),
                    };

                    self.bg_cache.layers[bg_num as usize - 1].scanline[x as usize] = CachedPixel {
                        priority: tilemap_entry.priority,
                        palette: tilemap_entry.palette,
                        tile_number: tilemap_entry.tile_number,
                        color: rgb,
                    };
                    x += 1;
                    off_x += 1;
                }

                tile_x += 1;
                off_x = 0;
            }

            self.bg_cache.layers[bg_num as usize - 1].valid = true;
        }

        // Cache must be valid now, so we can access the pixel we need:
        let pixel = &self.bg_cache.layers[bg_num as usize - 1].scanline[self.x as usize];
        if pixel.priority == prio {
            return pixel.color;
        } else {
            return None;
        }
    }
}
<|endoftext|>


<commit_before>use regex::{Regex};
use std::str::{FromStr};

use super::super::metrics::*;

/// Reader that takes a log line string and returns any metrics found in it.
pub trait LogLineReader: Send + Sync {
    fn read(&self, &str) -> Vec<Metric>;
}

/// Reads metrics from log lines in the standard formats:
///
/// - Measures: `measure#metric=1.2`
/// - Counts: `count#metric=3`
pub struct StandardLogLineReader;

lazy_static! {
    static ref LOG_MEASURE_REGEX: Regex =
        Regex::new(r"measure#([a-zA-Z0-9._]+)=(\d+(?:\.\d+)?)").unwrap();

    static ref LOG_COUNT_REGEX: Regex =
        Regex::new(r"count#([a-zA-Z0-9._]+)=(\d+)").unwrap();
}

impl LogLineReader for StandardLogLineReader {
    fn read(&self, line: &str) -> Vec<Metric> {
        let mut metrics = vec![];

        // Look for measures
        for cap in LOG_MEASURE_REGEX.captures_iter(line) {
            let name = cap.at(1).unwrap();

            if let Ok(value) = f64::from_str(cap.at(2).unwrap()) {
                metrics.push(Measure(name.to_owned(), value))
            }
        }

        // Look for counts
        for cap in LOG_COUNT_REGEX.captures_iter(line) {
            let name = cap.at(1).unwrap();

            if let Ok(value) = u64::from_str(cap.at(2).unwrap()) {
                metrics.push(Count(name.to_owned(), value))
            }
        }

        metrics
    } // fn read
}

#[cfg(test)]
mod tests {
    use super::{LogLineReader, StandardLogLineReader};
    use super::super::metrics::*;

    #[test]
    fn it_reads_measure() {
        let reader = StandardLogLineReader;
        let line = "measure#foo=1.2\n";

        assert_eq!(
            reader.read(line),
            vec![Measure("foo".to_owned(), 1.2)]
        )
    }

    #[test]
    fn it_reads_count() {
        let reader = StandardLogLineReader;
        let line = "count#foo=1\n";

        assert_eq!(
            reader.read(line),
            vec![Count("foo".to_owned(), 1)]
        )
    }

    #[test]
    fn it_returns_nothing_on_failed_read() {
        let reader = StandardLogLineReader;
        let line = "metric#bar=3.4\n";

        assert_eq!(
            reader.read(line),
            vec![]
        )
    }
}
<commit_msg>Add parsing of Heroku metrics<commit_after>use regex::{Regex};
use std::str::{FromStr};

use super::super::metrics::*;

/// Reader that takes a log line string and returns any metrics found in it.
pub trait LogLineReader: Send + Sync {
    fn read(&self, &str) -> Vec<Metric>;
}

/// Reads metrics from log lines in the standard formats:
///
/// - Measures: `measure#metric=1.2`
/// - Counts: `count#metric=3`
pub struct StandardLogLineReader;

lazy_static! {
    static ref LOG_MEASURE_REGEX: Regex =
        Regex::new(r"measure#([a-zA-Z0-9._]+)=(\d+(?:\.\d+)?)").unwrap();

    static ref LOG_COUNT_REGEX: Regex =
        Regex::new(r"count#([a-zA-Z0-9._]+)=(\d+)").unwrap();
}

impl LogLineReader for StandardLogLineReader {
    fn read(&self, line: &str) -> Vec<Metric> {
        let mut metrics = vec![];

        // Look for measures
        for cap in LOG_MEASURE_REGEX.captures_iter(line) {
            let name = cap.at(1).unwrap();

            if let Ok(value) = f64::from_str(cap.at(2).unwrap()) {
                metrics.push(Measure(name.to_owned(), value))
            }
        }

        // Look for counts
        for cap in LOG_COUNT_REGEX.captures_iter(line) {
            let name = cap.at(1).unwrap();

            if let Ok(value) = u64::from_str(cap.at(2).unwrap()) {
                metrics.push(Count(name.to_owned(), value))
            }
        }

        metrics
    } // fn read
}

/// Reads Heroku's logging metrics.
pub struct HerokuLogLineReader;

lazy_static! {
    static ref DYNO_TYPE_REGEX: Regex =
        Regex::new(r"dyno=(\w+)").unwrap();

    static ref SERVICE_REGEX: Regex =
        Regex::new(r"service=(\d+)ms").unwrap();

    static ref STATUS_REGEX: Regex =
        Regex::new(r"status=(\d+)").unwrap();

    static ref HEROKU_ERROR_CODE_REGEX: Regex =
        Regex::new(r"code=(H\d+)").unwrap();

    static ref LOAD_AVG_1M_REGEX: Regex =
        Regex::new(r"sample#load_avg_1m=([0-9.]+)").unwrap();

    static ref SOURCE_REGEX: Regex =
        Regex::new(r"source=(\w+).(\d+)").unwrap();
}

impl HerokuLogLineReader {
    fn parse_status(line: &str) -> Vec<Metric> {
        let mut metrics: Vec<Metric> = vec![];

        let status = match STATUS_REGEX.captures(line) {
            Some(captures) => captures.at(1).unwrap(),
            None => return vec![],
        };
        let status = u16::from_str(status).unwrap();

        let service = SERVICE_REGEX.captures(line)
            .and_then(|c| c.at(1))
            .and_then(|s| u32::from_str(s).ok())
            .unwrap();

        let dyno_type = DYNO_TYPE_REGEX.captures(line).and_then(|c| c.at(1)).unwrap();

        let base = format!("dyno.{}", dyno_type);

        // Don't record timing for 499 and 5xx errors
        if status < 499 || status > 599 {
            let service_time = format!("{}.service_time", base);
            metrics.push(Measure(service_time.to_owned(), service as f64));
        }

        // Count the status
        metrics.push(Count(format!("{}.status.{}", base, status).to_owned(), 1));

        metrics
    }

    fn parse_heroku_codes(line: &str) -> Vec<Metric> {
        let is_warning = line.contains("at=warning");
        let is_error   = line.contains("at=error");

        if !is_warning && !is_error { return vec![] }

        let code = HEROKU_ERROR_CODE_REGEX.captures(line).and_then(|c| c.at(1)).unwrap();

        vec![
            Count(format!("heroku.error.{}", code), 1)
        ]
    }

    fn parse_loads(line: &str) -> Vec<Metric> {
        let load_avg_1m = match LOAD_AVG_1M_REGEX.captures(line) {
            Some(captures) => captures.at(1).and_then(|c| f64::from_str(c).ok()).unwrap(),
            None => return vec![],
        };

        let dyno_type = SOURCE_REGEX.captures(line).and_then(|c| c.at(1)).unwrap();

        vec![
            Measure(format!("dyno.{}.load_avg_1m", dyno_type), load_avg_1m)
        ]
    }
}

impl LogLineReader for HerokuLogLineReader {
    fn read(&self, line: &str) -> Vec<Metric> {
        let mut metrics: Vec<Metric> = vec![];

        metrics.extend(HerokuLogLineReader::parse_status(line));
        metrics.extend(HerokuLogLineReader::parse_heroku_codes(line));
        metrics.extend(HerokuLogLineReader::parse_loads(line));

        metrics
    }
}

#[cfg(test)]
mod tests {
    use super::{LogLineReader, StandardLogLineReader};
    use super::super::super::metrics::*;

    #[test]
    fn it_reads_measure() {
        let reader = StandardLogLineReader;
        let line = "measure#foo=1.2\n";

        assert_eq!(
            reader.read(line),
            vec![Measure("foo".to_owned(), 1.2)]
        )
    }

    #[test]
    fn it_reads_count() {
        let reader = StandardLogLineReader;
        let line = "count#foo=1\n";

        assert_eq!(
            reader.read(line),
            vec![Count("foo".to_owned(), 1)]
        )
    }

    #[test]
    fn it_returns_nothing_on_failed_read() {
        let reader = StandardLogLineReader;
        let line = "metric#bar=3.4\n";

        assert_eq!(
            reader.read(line),
            vec![]
        )
    }
}
<|endoftext|>


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

use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder to optionally edit certain fields of a [`Guild`]. This is meant
/// for usage with [`Guild::edit`].
///
/// **Note**: Editing a guild requires that the current user have the
/// [Manage Guild] permission.
///
/// [`Guild::edit`]: crate::model::guild::Guild::edit
/// [`Guild`]: crate::model::guild::Guild
/// [Manage Guild]: crate::model::permissions::Permissions::MANAGE_GUILD
#[derive(Clone, Debug, Default)]
pub struct EditGuild(pub HashMap<&'static str, Value>);

impl EditGuild {
    /// Set the "AFK voice channel" that users are to move to if they have been
    /// AFK for an amount of time, configurable by [`Self::afk_timeout`].
    ///
    /// The given channel must be either some valid voice channel, or [`None`] to
    /// not set an AFK channel. The library does not check if a channel is
    /// valid.
    #[inline]
    pub fn afk_channel<C: Into<ChannelId>>(&mut self, channel: Option<C>) -> &mut Self {
        self._afk_channel(channel.map(Into::into));
        self
    }

    fn _afk_channel(&mut self, channel: Option<ChannelId>) {
        self.0.insert("afk_channel_id", match channel {
            Some(channel) => Value::Number(Number::from(channel.0)),
            None => Value::Null,
        });
    }

    /// Set the amount of time a user is to be moved to the AFK channel -
    /// configured via [`Self::afk_channel`] - after being AFK.
    pub fn afk_timeout(&mut self, timeout: u64) -> &mut Self {
        self.0.insert("afk_timeout", Value::Number(Number::from(timeout)));
        self
    }

    /// Set the icon of the guild. Pass [`None`] to remove the icon.
    ///
    /// # Examples
    ///
    /// Using the utility function - [`utils::read_image`] - to read an image
    /// from the cwd and encode it in base64 to send to Discord.
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::utils;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let base64_icon = utils::read_image("./guild_icon.png")?;
    ///
    /// guild.edit(&http, |mut g| g.icon(Some(&base64_icon))).await?;
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// [`utils::read_image`]: crate::utils::read_image
    pub fn icon(&mut self, icon: Option<&str>) -> &mut Self {
        self.0.insert("icon", icon.map_or_else(|| Value::Null, |x| Value::String(x.to_string())));
        self
    }

    /// Set the name of the guild.
    ///
    /// **Note**: Must be between (and including) 2-100 chracters.
    pub fn name<S: ToString>(&mut self, name: S) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));
        self
    }

    /// Set the description of the guild.
    ///
    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn description<S: ToString>(&mut self, name: S) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));
        self
    }

    /// Set the features of the guild.
    ///
    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn features(&mut self, features: Vec<String>) -> &mut Self {
        let mut values: Vec<Value> = vec![];

        for value in features {
            values.push(Value::String(value));
        }

        self.0.insert("features", Value::Array(values));
        self
    }

    /// Transfers the ownership of the guild to another user by Id.
    ///
    /// **Note**: The current user must be the owner of the guild.
    #[inline]
    pub fn owner<U: Into<UserId>>(&mut self, user_id: U) -> &mut Self {
        self._owner(user_id.into());
        self
    }

    fn _owner(&mut self, user_id: UserId) {
        let id = Value::Number(Number::from(user_id.0));
        self.0.insert("owner_id", id);
    }

    /// Set the voice region of the server.
    ///
    /// # Examples
    ///
    /// Setting the region to [`Region::UsWest`]:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::Region;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// guild.edit(&http, |g| g.region(Region::UsWest)).await?;
    /// #     Ok(())
    /// # }
    /// ```
    #[deprecated(note = "Regions are now set per voice channel instead of globally.")]
    pub fn region(&mut self, region: Region) -> &mut Self {
        self.0.insert("region", Value::String(region.name().to_string()));
        self
    }

    /// Set the splash image of the guild on the invitation page.
    ///
    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
    ///
    /// Requires that the guild have the `INVITE_SPLASH` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn splash(&mut self, splash: Option<&str>) -> &mut Self {
        let splash = splash.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("splash", splash);
        self
    }

    /// Set the splash image of the guild on the discovery page.
    ///
    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
    ///
    /// Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn discovery_splash(&mut self, splash: Option<&str>) -> &mut Self {
        let splash = splash.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("splash", splash);
        self
    }

    /// Set the banner image of the guild, it appears on the left side-bar.
    ///
    /// The `banner` must be base64-encoded 16:9 png/jpeg image data.
    ///
    /// Requires that the guild have the `BANNER` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn banner(&mut self, banner: Option<&str>) -> &mut Self {
        let banner = banner.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("banner", banner);
        self
    }

    /// Set the channel ID where welcome messages and boost events will be
    /// posted.
    pub fn system_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("system_channel_id", channel_id);
        self
    }

    /// Set the channel ID of the rules and guidelines channel.
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn rules_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("rules_channel_id", channel_id);
        self
    }

    /// Set the channel ID where admins and moderators receive update messages
    /// from Discord.
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn public_updates_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("public_updates_channel_id", channel_id);
        self
    }

    /// Set the preferred locale used in Server Discovery and update messages
    /// from Discord.
    ///
    /// If this is not set, the locale will default to "en-US";
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn preferred_locale(&mut self, locale: Option<&str>) -> &mut Self {
        let locale = locale.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("preferred_locale", locale);
        self
    }

    /// Set the content filter level.
    pub fn explicit_content_filter(&mut self, level: Option<ExplicitContentFilter>) -> &mut Self {
        let level = level.map_or(Value::Null, |x| Value::from(x as u8));
        self.0.insert("explicit_content_filter", level);
        self
    }

    /// Set the default message notification level.
    pub fn default_message_notifications(
        &mut self,
        level: Option<DefaultMessageNotificationLevel>,
    ) -> &mut Self {
        let level = level.map_or(Value::Null, |x| Value::from(x as u8));
        self.0.insert("default_message_notifications", level);
        self
    }

    /// Set the verification level of the guild. This can restrict what a
    /// user must have prior to being able to send messages in a guild.
    ///
    /// Refer to the documentation for [`VerificationLevel`] for more
    /// information on each variant.
    ///
    ///
    /// # Examples
    ///
    /// Setting the verification level to [`High`][`VerificationLevel::High`]:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::VerificationLevel;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let edit = guild.edit(&http, |g| g.verification_level(VerificationLevel::High)).await;
    ///
    /// if let Err(why) = edit {
    ///     println!("Error setting verification level: {:?}", why);
    /// }
    /// #     Ok(())
    /// # }
    /// ```
    #[inline]
    pub fn verification_level<V>(&mut self, verification_level: V) -> &mut Self
    where
        V: Into<VerificationLevel>,
    {
        self._verification_level(verification_level.into());
        self
    }

    fn _verification_level(&mut self, verification_level: VerificationLevel) {
        let num = Value::Number(Number::from(verification_level.num()));
        self.0.insert("verification_level", num);
    }

    /// Modifies the notifications that are sent by discord to the configured system channel.
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::SystemChannelFlags;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let edit = guild
    ///     .edit(&http, |g| {
    ///         g.system_channel_flags(
    ///             SystemChannelFlags::SUPPRESS_JOIN_NOTIFICATIONS
    ///                 | SystemChannelFlags::SUPPRESS_GUILD_REMINDER_NOTIFICATIONS,
    ///         )
    ///     })
    ///     .await;
    ///
    /// if let Err(why) = edit {
    ///     println!("Error setting verification level: {:?}", why);
    /// }
    /// #     Ok(())
    /// # }
    /// ```
    pub fn system_channel_flags(&mut self, system_channel_flags: SystemChannelFlags) -> &mut Self {
        self.0.insert("system_channel_flags", system_channel_flags.bits().into());
        self
    }
}
<commit_msg>Suppress deprecation warning for the use of `Region` (#1686)<commit_after>use std::collections::HashMap;

use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder to optionally edit certain fields of a [`Guild`]. This is meant
/// for usage with [`Guild::edit`].
///
/// **Note**: Editing a guild requires that the current user have the
/// [Manage Guild] permission.
///
/// [`Guild::edit`]: crate::model::guild::Guild::edit
/// [`Guild`]: crate::model::guild::Guild
/// [Manage Guild]: crate::model::permissions::Permissions::MANAGE_GUILD
#[derive(Clone, Debug, Default)]
pub struct EditGuild(pub HashMap<&'static str, Value>);

impl EditGuild {
    /// Set the "AFK voice channel" that users are to move to if they have been
    /// AFK for an amount of time, configurable by [`Self::afk_timeout`].
    ///
    /// The given channel must be either some valid voice channel, or [`None`] to
    /// not set an AFK channel. The library does not check if a channel is
    /// valid.
    #[inline]
    pub fn afk_channel<C: Into<ChannelId>>(&mut self, channel: Option<C>) -> &mut Self {
        self._afk_channel(channel.map(Into::into));
        self
    }

    fn _afk_channel(&mut self, channel: Option<ChannelId>) {
        self.0.insert("afk_channel_id", match channel {
            Some(channel) => Value::Number(Number::from(channel.0)),
            None => Value::Null,
        });
    }

    /// Set the amount of time a user is to be moved to the AFK channel -
    /// configured via [`Self::afk_channel`] - after being AFK.
    pub fn afk_timeout(&mut self, timeout: u64) -> &mut Self {
        self.0.insert("afk_timeout", Value::Number(Number::from(timeout)));
        self
    }

    /// Set the icon of the guild. Pass [`None`] to remove the icon.
    ///
    /// # Examples
    ///
    /// Using the utility function - [`utils::read_image`] - to read an image
    /// from the cwd and encode it in base64 to send to Discord.
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::utils;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let base64_icon = utils::read_image("./guild_icon.png")?;
    ///
    /// guild.edit(&http, |mut g| g.icon(Some(&base64_icon))).await?;
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// [`utils::read_image`]: crate::utils::read_image
    pub fn icon(&mut self, icon: Option<&str>) -> &mut Self {
        self.0.insert("icon", icon.map_or_else(|| Value::Null, |x| Value::String(x.to_string())));
        self
    }

    /// Set the name of the guild.
    ///
    /// **Note**: Must be between (and including) 2-100 chracters.
    pub fn name<S: ToString>(&mut self, name: S) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));
        self
    }

    /// Set the description of the guild.
    ///
    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn description<S: ToString>(&mut self, name: S) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));
        self
    }

    /// Set the features of the guild.
    ///
    /// **Note**: Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn features(&mut self, features: Vec<String>) -> &mut Self {
        let mut values: Vec<Value> = vec![];

        for value in features {
            values.push(Value::String(value));
        }

        self.0.insert("features", Value::Array(values));
        self
    }

    /// Transfers the ownership of the guild to another user by Id.
    ///
    /// **Note**: The current user must be the owner of the guild.
    #[inline]
    pub fn owner<U: Into<UserId>>(&mut self, user_id: U) -> &mut Self {
        self._owner(user_id.into());
        self
    }

    fn _owner(&mut self, user_id: UserId) {
        let id = Value::Number(Number::from(user_id.0));
        self.0.insert("owner_id", id);
    }

    /// Set the voice region of the server.
    ///
    /// # Examples
    ///
    /// Setting the region to [`Region::UsWest`]:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::Region;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// guild.edit(&http, |g| g.region(Region::UsWest)).await?;
    /// #     Ok(())
    /// # }
    /// ```
    #[deprecated(note = "Regions are now set per voice channel instead of globally.")]
    #[allow(deprecated)]
    pub fn region(&mut self, region: Region) -> &mut Self {
        self.0.insert("region", Value::String(region.name().to_string()));
        self
    }

    /// Set the splash image of the guild on the invitation page.
    ///
    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
    ///
    /// Requires that the guild have the `INVITE_SPLASH` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn splash(&mut self, splash: Option<&str>) -> &mut Self {
        let splash = splash.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("splash", splash);
        self
    }

    /// Set the splash image of the guild on the discovery page.
    ///
    /// The `splash` must be base64-encoded 1024x1024 png/jpeg/gif image-data.
    ///
    /// Requires that the guild have the `DISCOVERABLE` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn discovery_splash(&mut self, splash: Option<&str>) -> &mut Self {
        let splash = splash.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("splash", splash);
        self
    }

    /// Set the banner image of the guild, it appears on the left side-bar.
    ///
    /// The `banner` must be base64-encoded 16:9 png/jpeg image data.
    ///
    /// Requires that the guild have the `BANNER` feature enabled.
    /// You can check this through a guild's [`features`] list.
    ///
    /// [`features`]: crate::model::guild::Guild::features
    pub fn banner(&mut self, banner: Option<&str>) -> &mut Self {
        let banner = banner.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("banner", banner);
        self
    }

    /// Set the channel ID where welcome messages and boost events will be
    /// posted.
    pub fn system_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("system_channel_id", channel_id);
        self
    }

    /// Set the channel ID of the rules and guidelines channel.
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn rules_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("rules_channel_id", channel_id);
        self
    }

    /// Set the channel ID where admins and moderators receive update messages
    /// from Discord.
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn public_updates_channel_id(&mut self, channel_id: Option<ChannelId>) -> &mut Self {
        let channel_id = channel_id.map_or(Value::Null, |x| Value::from(x.0));
        self.0.insert("public_updates_channel_id", channel_id);
        self
    }

    /// Set the preferred locale used in Server Discovery and update messages
    /// from Discord.
    ///
    /// If this is not set, the locale will default to "en-US";
    ///
    /// **Note**:
    /// This feature is for Community guilds only.
    pub fn preferred_locale(&mut self, locale: Option<&str>) -> &mut Self {
        let locale = locale.map_or(Value::Null, |x| Value::String(x.to_string()));
        self.0.insert("preferred_locale", locale);
        self
    }

    /// Set the content filter level.
    pub fn explicit_content_filter(&mut self, level: Option<ExplicitContentFilter>) -> &mut Self {
        let level = level.map_or(Value::Null, |x| Value::from(x as u8));
        self.0.insert("explicit_content_filter", level);
        self
    }

    /// Set the default message notification level.
    pub fn default_message_notifications(
        &mut self,
        level: Option<DefaultMessageNotificationLevel>,
    ) -> &mut Self {
        let level = level.map_or(Value::Null, |x| Value::from(x as u8));
        self.0.insert("default_message_notifications", level);
        self
    }

    /// Set the verification level of the guild. This can restrict what a
    /// user must have prior to being able to send messages in a guild.
    ///
    /// Refer to the documentation for [`VerificationLevel`] for more
    /// information on each variant.
    ///
    ///
    /// # Examples
    ///
    /// Setting the verification level to [`High`][`VerificationLevel::High`]:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::VerificationLevel;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let edit = guild.edit(&http, |g| g.verification_level(VerificationLevel::High)).await;
    ///
    /// if let Err(why) = edit {
    ///     println!("Error setting verification level: {:?}", why);
    /// }
    /// #     Ok(())
    /// # }
    /// ```
    #[inline]
    pub fn verification_level<V>(&mut self, verification_level: V) -> &mut Self
    where
        V: Into<VerificationLevel>,
    {
        self._verification_level(verification_level.into());
        self
    }

    fn _verification_level(&mut self, verification_level: VerificationLevel) {
        let num = Value::Number(Number::from(verification_level.num()));
        self.0.insert("verification_level", num);
    }

    /// Modifies the notifications that are sent by discord to the configured system channel.
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Http::default();
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::guild::SystemChannelFlags;
    ///
    /// // assuming a `guild` has already been bound
    ///
    /// let edit = guild
    ///     .edit(&http, |g| {
    ///         g.system_channel_flags(
    ///             SystemChannelFlags::SUPPRESS_JOIN_NOTIFICATIONS
    ///                 | SystemChannelFlags::SUPPRESS_GUILD_REMINDER_NOTIFICATIONS,
    ///         )
    ///     })
    ///     .await;
    ///
    /// if let Err(why) = edit {
    ///     println!("Error setting verification level: {:?}", why);
    /// }
    /// #     Ok(())
    /// # }
    /// ```
    pub fn system_channel_flags(&mut self, system_channel_flags: SystemChannelFlags) -> &mut Self {
        self.0.insert("system_channel_flags", system_channel_flags.bits().into());
        self
    }
}
<|endoftext|>


<commit_before>use bios_boot_device::BIOSBootDeviceTag;
use tag::{Tag, TagIter};

pub struct MultiBootInfo {
    total_size: u32,
    reserved: u32,      // Should always be 0
    mem_lower: u32,
    mem_upper: u32,
    boot_device: u32,
    boot_cmd_line: u32,
    module_count: u32,
    modules: u32,
    elf_symbols: u32,
    memory_map: u32,
    boot_loader_name: u32,
    apm_table: u32,
    vbe_info: u32,
    framebuffer_info: u32
}

impl MultiBootInfo {
    unsafe fn new(multiboot_addr: u32) -> () {
        let total_size = *(multiboot_addr as *const u32);
        let reserved = *((multiboot_addr + 4) as *const u32);
        let first_tag = (multiboot_addr + 8) as *const Tag;
        let tag_iter = TagIter::new(first_tag);
    }
}<commit_msg>Redefine Multiboot info struct in an easier way. Because we do not know what tags will be there at startup, we need to use the tag iterator to search for the tags by their tag type as we need them.<commit_after>use bios_boot_device::BIOSBootDeviceTag;
use tag::{Tag, TagIter};

#[derive(Debug)]
#[repr(C, packed)]
pub struct MultiBootInfo {
    total_size: u32,
    reserved: u32,      // Should always be 0.
    first_tag: *const Tag
}

impl MultiBootInfo {
    unsafe fn new(multiboot_addr: u32) -> MultiBootInfo {
        let total_size = *(multiboot_addr as *const u32);
        let reserved = *((multiboot_addr + 4) as *const u32);
        let first_tag = (multiboot_addr + 8) as *const Tag;

        MultiBootInfo {
            total_size: total_size,
            reserved: reserved,
            first_tag: first_tag
        }

    }

    pub fn start_address(&self) -> usize {
        self as *const _ as usize
    }

    pub fn end_address(&self) -> usize {
        self.start_address() + self.total_size()
    }

    pub fn total_size(&self) -> usize {
        self.total_size as usize
    }

}<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::ptr;
use libc::{c_char, c_int};

use glib::translate::*;
use glib::{Type, Value};
use ffi;

use super::tree_model::{TreeIter, TreeModel};

///////////////////////////////////////////////////////////////////////////////

glib_wrapper! {
    pub struct ListStore(Object<ffi::GtkListStore>): TreeModel, ::Buildable;

    match fn {
        get_type => || ffi::gtk_list_store_get_type(),
    }
}

impl ListStore {
    pub fn new(column_types: &[Type]) -> ListStore {
        unsafe {
            from_glib_full(
                ffi::gtk_list_store_newv(column_types.len() as c_int,
                    column_types.to_glib_none().0))
        }
    }

    pub fn set_column_types(&self, column_types: &[Type]) {
        unsafe {
            ffi::gtk_list_store_set_column_types(self.to_glib_none().0, column_types.len() as c_int,
                column_types.to_glib_none().0)
        }
    }

    pub fn set_string(&self, iter: &TreeIter, column: i32, text: &str) {
        unsafe {
            let text: Stash<*const c_char, _> = text.to_glib_none();
            ffi::gtk_list_store_set(self.to_glib_none().0, iter.unwrap_pointer(), column,
                text.0, -1)
        }
    }

    pub fn remove(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(ffi::gtk_list_store_remove(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn insert(&self, iter: &mut TreeIter, position: i32) {
        unsafe {
            ffi::gtk_list_store_insert(self.to_glib_none().0, iter.unwrap_pointer(), position)
        }
    }

    pub fn insert_before(&self, iter: &mut TreeIter, sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_insert_before(self.to_glib_none().0, iter.unwrap_pointer(),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn insert_after(&self, iter: &mut TreeIter, sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_insert_after(self.to_glib_none().0, iter.unwrap_pointer(),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn prepend(&self, iter: &mut TreeIter) {
        unsafe { ffi::gtk_list_store_prepend(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn append(&self, iter: &mut TreeIter) {
        unsafe { ffi::gtk_list_store_append(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_list_store_clear(self.to_glib_none().0) }
    }

    pub fn iter_is_valid(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_list_store_iter_is_valid(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn reorder(&self, new_order: &[i32]) {
        unsafe { ffi::gtk_list_store_reorder(self.to_glib_none().0, new_order.to_glib_none().0) }
    }

    pub fn swap(&self, a: &TreeIter, b: &TreeIter) {
        unsafe {
            ffi::gtk_list_store_swap(self.to_glib_none().0, a.unwrap_pointer(), b.unwrap_pointer())
        }
    }

    pub fn move_before(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn move_after(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn set_value(&self, iter: &TreeIter, column: i32, value: &Value) {
        unsafe {
            ffi::gtk_list_store_set_value(self.to_glib_none().0, iter.unwrap_pointer(),
                column, value.as_ptr() as *mut _);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////

glib_wrapper! {
    pub struct TreeStore(Object<ffi::GtkTreeStore>): TreeModel, ::Buildable;

    match fn {
        get_type => || ffi::gtk_tree_store_get_type(),
    }
}

impl TreeStore {
    pub fn new(column_types: &[Type]) -> TreeStore {
        unsafe {
            from_glib_full(
                ffi::gtk_tree_store_newv(column_types.len() as c_int,
                    column_types.to_glib_none().0))
        }
    }

    pub fn set_column_types(&self, column_types: &[Type]) {
        unsafe {
            ffi::gtk_tree_store_set_column_types(self.to_glib_none().0, column_types.len() as c_int,
                column_types.to_glib_none().0)
        }
    }

    pub fn set_string(&self, iter: &TreeIter, column: i32, text: &str) {
        unsafe {
            let text: Stash<*const c_char, _> = text.to_glib_none();
            ffi::gtk_tree_store_set(self.to_glib_none().0, iter.unwrap_pointer(), column,
                text.0, -1)
        }
    }

    pub fn remove(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(ffi::gtk_tree_store_remove(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn insert(&self, iter: &mut TreeIter, parent: Option<&TreeIter>, position: i32) {
        unsafe {
            ffi::gtk_tree_store_insert(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()), position)
        }
    }

    pub fn insert_before(&self, iter: &mut TreeIter, parent: Option<&TreeIter>,
            sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_insert_before(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn insert_after(&self, iter: &mut TreeIter, parent: Option<&TreeIter>,
            sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_insert_after(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn prepend(&self, iter: &mut TreeIter, parent: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_prepend(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn append(&self, iter: &mut TreeIter, parent: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_append(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn is_ancestor(&self, iter: &TreeIter, descendant: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_tree_store_is_ancestor(self.to_glib_none().0, iter.unwrap_pointer(),
                    descendant.unwrap_pointer()))
        }
    }

    pub fn iter_depth(&self, iter: &TreeIter) -> i32 {
        unsafe { ffi::gtk_tree_store_iter_depth(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_tree_store_clear(self.to_glib_none().0) }
    }

    pub fn iter_is_valid(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_tree_store_iter_is_valid(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn reorder(&self, parent: &TreeIter, new_order: &[i32]) {
        unsafe {
            ffi::gtk_tree_store_reorder(self.to_glib_none().0, parent.unwrap_pointer(),
                new_order.to_glib_none().0)
        }
    }

    pub fn swap(&self, a: &TreeIter, b: &TreeIter) {
        unsafe {
            ffi::gtk_tree_store_swap(self.to_glib_none().0, a.unwrap_pointer(), b.unwrap_pointer())
        }
    }

    pub fn move_before(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn move_after(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn set_value(&self, iter: &TreeIter, column: i32, value: &Value) {
        unsafe {
            ffi::gtk_tree_store_set_value(self.to_glib_none().0, iter.unwrap_pointer(),
                column, value.as_ptr() as *mut _);
        }
    }

    /*pub fn set_valuesv<T: ::traits::GValuePrivate>(&self, iter: &::TreeIter, columns: &[i32], values: &[T]) {
        let mut tmp_values = Vec::with_capacity(values.len());

        for value in values {
            tmp_values.push(value.get_gvalue());
        }
        unsafe { ffi::gtk_tree_store_set_valuesv(::cast::GTK_TREE_MODEL_FROM_TREE_STORE(self.to_glib_none().0), iter.unwrap_pointer(),
            columns.as_ptr(), tmp_values.as_slice().as_ptr()) }
    }*/
}
<commit_msg>Fix functions that take slices<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::ptr;
use libc::{c_char, c_int};

use glib::translate::*;
use glib::{Type, Value};
use ffi;

use super::tree_model::{TreeIter, TreeModel};

///////////////////////////////////////////////////////////////////////////////

glib_wrapper! {
    pub struct ListStore(Object<ffi::GtkListStore>): TreeModel, ::Buildable;

    match fn {
        get_type => || ffi::gtk_list_store_get_type(),
    }
}

impl ListStore {
    pub fn new(column_types: &[Type]) -> ListStore {
        unsafe {
            let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
            from_glib_full(
                ffi::gtk_list_store_newv(column_types.len() as c_int,
                    column_types.as_mut_ptr()))
        }
    }

    pub fn set_column_types(&self, column_types: &[Type]) {
        unsafe {
            let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
            ffi::gtk_list_store_set_column_types(self.to_glib_none().0, column_types.len() as c_int,
                column_types.as_mut_ptr())
        }
    }

    pub fn set_string(&self, iter: &TreeIter, column: i32, text: &str) {
        unsafe {
            let text: Stash<*const c_char, _> = text.to_glib_none();
            ffi::gtk_list_store_set(self.to_glib_none().0, iter.unwrap_pointer(), column,
                text.0, -1)
        }
    }

    pub fn remove(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(ffi::gtk_list_store_remove(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn insert(&self, iter: &mut TreeIter, position: i32) {
        unsafe {
            ffi::gtk_list_store_insert(self.to_glib_none().0, iter.unwrap_pointer(), position)
        }
    }

    pub fn insert_before(&self, iter: &mut TreeIter, sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_insert_before(self.to_glib_none().0, iter.unwrap_pointer(),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn insert_after(&self, iter: &mut TreeIter, sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_insert_after(self.to_glib_none().0, iter.unwrap_pointer(),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn prepend(&self, iter: &mut TreeIter) {
        unsafe { ffi::gtk_list_store_prepend(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn append(&self, iter: &mut TreeIter) {
        unsafe { ffi::gtk_list_store_append(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_list_store_clear(self.to_glib_none().0) }
    }

    pub fn iter_is_valid(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_list_store_iter_is_valid(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn reorder(&self, new_order: &[i32]) {
        unsafe {
            let count = ffi::gtk_tree_model_iter_n_children(self.to_glib_none().0, ptr::null_mut());
            let safe_count = count as usize == new_order.len();
            debug_assert!(safe_count,
                          "Incorrect `new_order` slice length. Expected `{}`, found `{}`.",
                          count,
                          new_order.len());
            let safe_values = new_order.iter()
                .max()
                .map(|&max| {
                    let max = max as i32;
                    max >= 0 && max < count
                })
                .unwrap_or(true);
            debug_assert!(safe_values,
                          "Some `new_order` slice values are out of range. Maximum safe value: \
                           `{}`. The slice contents: `{:?}`",
                          count - 1,
                          new_order);
            if safe_count && safe_values {
                ffi::gtk_list_store_reorder(self.to_glib_none().0, new_order.as_ptr() as *mut _);
            }
        }
    }

    pub fn swap(&self, a: &TreeIter, b: &TreeIter) {
        unsafe {
            ffi::gtk_list_store_swap(self.to_glib_none().0, a.unwrap_pointer(), b.unwrap_pointer())
        }
    }

    pub fn move_before(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn move_after(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_list_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn set_value(&self, iter: &TreeIter, column: i32, value: &Value) {
        unsafe {
            ffi::gtk_list_store_set_value(self.to_glib_none().0, iter.unwrap_pointer(),
                column, value.as_ptr() as *mut _);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////

glib_wrapper! {
    pub struct TreeStore(Object<ffi::GtkTreeStore>): TreeModel, ::Buildable;

    match fn {
        get_type => || ffi::gtk_tree_store_get_type(),
    }
}

impl TreeStore {
    pub fn new(column_types: &[Type]) -> TreeStore {
        unsafe {
            let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
            from_glib_full(
                ffi::gtk_tree_store_newv(column_types.len() as c_int,
                    column_types.as_mut_ptr()))
        }
    }

    pub fn set_column_types(&self, column_types: &[Type]) {
        unsafe {
            let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
            ffi::gtk_tree_store_set_column_types(self.to_glib_none().0, column_types.len() as c_int,
                column_types.as_mut_ptr())
        }
    }

    pub fn set_string(&self, iter: &TreeIter, column: i32, text: &str) {
        unsafe {
            let text: Stash<*const c_char, _> = text.to_glib_none();
            ffi::gtk_tree_store_set(self.to_glib_none().0, iter.unwrap_pointer(), column,
                text.0, -1)
        }
    }

    pub fn remove(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(ffi::gtk_tree_store_remove(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn insert(&self, iter: &mut TreeIter, parent: Option<&TreeIter>, position: i32) {
        unsafe {
            ffi::gtk_tree_store_insert(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()), position)
        }
    }

    pub fn insert_before(&self, iter: &mut TreeIter, parent: Option<&TreeIter>,
            sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_insert_before(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn insert_after(&self, iter: &mut TreeIter, parent: Option<&TreeIter>,
            sibling: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_insert_after(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()),
                sibling.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn prepend(&self, iter: &mut TreeIter, parent: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_prepend(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn append(&self, iter: &mut TreeIter, parent: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_append(self.to_glib_none().0, iter.unwrap_pointer(),
                parent.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn is_ancestor(&self, iter: &TreeIter, descendant: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_tree_store_is_ancestor(self.to_glib_none().0, iter.unwrap_pointer(),
                    descendant.unwrap_pointer()))
        }
    }

    pub fn iter_depth(&self, iter: &TreeIter) -> i32 {
        unsafe { ffi::gtk_tree_store_iter_depth(self.to_glib_none().0, iter.unwrap_pointer()) }
    }

    pub fn clear(&self) {
        unsafe { ffi::gtk_tree_store_clear(self.to_glib_none().0) }
    }

    pub fn iter_is_valid(&self, iter: &TreeIter) -> bool {
        unsafe {
            from_glib(
                ffi::gtk_tree_store_iter_is_valid(self.to_glib_none().0, iter.unwrap_pointer()))
        }
    }

    pub fn reorder(&self, parent: &TreeIter, new_order: &[i32]) {
        unsafe {
            let count = ffi::gtk_tree_model_iter_n_children(self.to_glib_none().0,
                                                            parent.unwrap_pointer());
            let safe_count = count as usize == new_order.len();
            debug_assert!(safe_count,
                          "Incorrect `new_order` slice length. Expected `{}`, found `{}`.",
                          count,
                          new_order.len());
            let safe_values = new_order.iter()
                .max()
                .map(|&max| {
                    let max = max as i32;
                    max >= 0 && max < count
                })
                .unwrap_or(true);
            debug_assert!(safe_values,
                          "Some `new_order` slice values are out of range. Maximum safe value: \
                           `{}`. The slice contents: `{:?}`",
                          count - 1,
                          new_order);
            if safe_count && safe_values {
                ffi::gtk_tree_store_reorder(self.to_glib_none().0,
                                            parent.unwrap_pointer(),
                                            new_order.as_ptr() as *mut _);
            }
        }
    }

    pub fn swap(&self, a: &TreeIter, b: &TreeIter) {
        unsafe {
            ffi::gtk_tree_store_swap(self.to_glib_none().0, a.unwrap_pointer(), b.unwrap_pointer())
        }
    }

    pub fn move_before(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn move_after(&self, iter: &TreeIter, position: Option<&TreeIter>) {
        unsafe {
            ffi::gtk_tree_store_move_before(self.to_glib_none().0, iter.unwrap_pointer(),
                position.map_or(ptr::null_mut(), |p| p.unwrap_pointer()))
        }
    }

    pub fn set_value(&self, iter: &TreeIter, column: i32, value: &Value) {
        unsafe {
            ffi::gtk_tree_store_set_value(self.to_glib_none().0, iter.unwrap_pointer(),
                column, value.as_ptr() as *mut _);
        }
    }

    /*pub fn set_valuesv<T: ::traits::GValuePrivate>(&self, iter: &::TreeIter, columns: &[i32], values: &[T]) {
        let mut tmp_values = Vec::with_capacity(values.len());

        for value in values {
            tmp_values.push(value.get_gvalue());
        }
        unsafe { ffi::gtk_tree_store_set_valuesv(::cast::GTK_TREE_MODEL_FROM_TREE_STORE(self.to_glib_none().0), iter.unwrap_pointer(),
            columns.as_ptr(), tmp_values.as_slice().as_ptr()) }
    }*/
}
<|endoftext|>


<commit_before>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Information about a server

use std::fmt;
use std::fmt::{Display, Formatter};

use extension::Extension;

/// Contains information about an SMTP server
#[derive(Clone,Debug)]
pub struct ServerInfo {
    /// Server name
    ///
    /// The name given in the server banner
    pub name: String,
    /// ESMTP features supported by the server
    ///
    /// It contains the features supported by the server and known by the `Extension` module.
    pub esmtp_features: Vec<Extension>,
}

impl Display for ServerInfo {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} with {}",
            self.name,
            match self.esmtp_features.is_empty() {
                true => "no supported features".to_string(),
                false => format! ("{:?}", self.esmtp_features),
            }
        )
    }
}

impl ServerInfo {
    /// Checks if the server supports an ESMTP feature
    pub fn supports_feature(&self, keyword: Extension) -> Option<Extension> {
        for feature in self.esmtp_features {
            if keyword.same_extension_as(feature) {
                return Some(*feature);
            }
        }
        None
    }
}

#[cfg(test)]
mod test {
    use super::ServerInfo;
    use extension::Extension;

    #[test]
    fn test_fmt() {
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }), "name with [EightBitMime]".to_string());
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }), "name with [EightBitMime]".to_string());
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec!()
        }), "name with no supported features".to_string());
    }

    #[test]
    fn test_supports_feature() {
        assert_eq!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }.supports_feature(Extension::EightBitMime), Some(Extension::EightBitMime));
        assert_eq!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::PlainAuthentication, Extension::EightBitMime]
        }.supports_feature(Extension::EightBitMime), Some(Extension::EightBitMime));
        assert!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }.supports_feature(Extension::PlainAuthentication).is_none());
    }
}
<commit_msg>Remove support for SIZE extension<commit_after>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Information about a server

use std::fmt;
use std::fmt::{Display, Formatter};

use extension::Extension;

/// Contains information about an SMTP server
#[derive(Clone,Debug)]
pub struct ServerInfo {
    /// Server name
    ///
    /// The name given in the server banner
    pub name: String,
    /// ESMTP features supported by the server
    ///
    /// It contains the features supported by the server and known by the `Extension` module.
    pub esmtp_features: Vec<Extension>,
}

impl Display for ServerInfo {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{} with {}",
            self.name,
            match self.esmtp_features.is_empty() {
                true => "no supported features".to_string(),
                false => format! ("{:?}", self.esmtp_features),
            }
        )
    }
}

impl ServerInfo {
    /// Checks if the server supports an ESMTP feature
    pub fn supports_feature(&self, keyword: Extension) -> Option<Extension> {
        for feature in self.esmtp_features.iter() {
            if keyword.same_extension_as(feature) {
                return Some(*feature);
            }
        }
        None
    }
}

#[cfg(test)]
mod test {
    use super::ServerInfo;
    use extension::Extension;

    #[test]
    fn test_fmt() {
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }), "name with [EightBitMime]".to_string());
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }), "name with [EightBitMime]".to_string());
        assert_eq!(format!("{}", ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec!()
        }), "name with no supported features".to_string());
    }

    #[test]
    fn test_supports_feature() {
        assert_eq!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }.supports_feature(Extension::EightBitMime), Some(Extension::EightBitMime));
        assert_eq!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::PlainAuthentication, Extension::EightBitMime]
        }.supports_feature(Extension::EightBitMime), Some(Extension::EightBitMime));
        assert!(ServerInfo{
            name: "name".to_string(),
            esmtp_features: vec![Extension::EightBitMime]
        }.supports_feature(Extension::PlainAuthentication).is_none());
    }
}
<|endoftext|>


<commit_before>//! Cryptographic hash functions primitives
//!
//! Via [Wikipedia](https://en.wikipedia.org/wiki/Cryptographic_hash_function):
//!
//! > The ideal cryptographic hash function has four main properties:
//! >
//! > - it is easy to compute the hash value for any given message
//! > - it is infeasible to generate a message from its hash
//! > - it is infeasible to modify a message without changing the hash
//! > - it is infeasible to find two different messages with the same hash.
//!
//! # Example
//!
//! Calculate SHA-512 sum:
//!
//! ```rust
//! # extern crate octavo_digest;
//! use octavo_digest::prelude::*;
//!
//! # fn main() {
//! # let data = "Hello World!";
//! let mut result = vec![0; sha2::Sha512::output_bytes()];
//! let mut sha = sha2::Sha512::default();
//!
//! sha.update(data);
//! sha.result(&mut result);
//!
//! for byte in result {
//!     print!("{:2x}", byte);
//! }
//! println!(" {}", data);
//! # }
//! ```

#![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
       html_root_url = "http://libOctavo.github.io/")]

#![feature(repr_simd)]

#![no_std]

#![allow(inline_always, unknown_lints)]
#![forbid(overflowing_literals, missing_docs)]

extern crate generic_array;
extern crate static_buffer;
extern crate typenum;
extern crate byteorder;

use generic_array::ArrayLength;
use typenum::uint::Unsigned;

/// Hash function digest definition
pub trait Digest: Clone {
    /// Output size in bits
    type OutputBits: Unsigned + ArrayLength<u8>;
    /// Output size in bytes
    type OutputBytes: Unsigned + ArrayLength<u8>;

    /// Block size in bytes
    type BlockSize: Unsigned + ArrayLength<u8>;

    /// Update digest with data.
    fn update<T>(&mut self, input: T) where T: AsRef<[u8]>;

    /// Output size in bits
    fn output_bits() -> usize {
        Self::OutputBits::to_usize()
    }
    /// Output size in bytes
    fn output_bytes() -> usize {
        Self::OutputBytes::to_usize()
    }
    /// Block size in bytes
    fn block_size() -> usize {
        Self::BlockSize::to_usize()
    }

    /// Write resulting hash into `output`.
    ///
    /// `output` should be big enough to contain whole output.
    ///
    /// ## Panics
    ///
    /// If output length is less than `Digest::output_bytes`.
    fn result<T>(self, output: T) where T: AsMut<[u8]>;
}

/// Digest prelude
pub mod prelude {
    pub use Digest;

    #[cfg(feature = "blake2")]
    pub use blake2;
    #[cfg(feature = "md5")]
    pub use md5::Md5;
    #[cfg(feature = "ripemd")]
    pub use ripemd::Ripemd160;
    #[cfg(feature = "sha1")]
    pub use sha1::Sha1;
    #[cfg(feature = "sha2")]
    pub use sha2;
    #[cfg(feature = "sha3")]
    pub use sha3;
    #[cfg(feature = "tiger")]
    pub use tiger;
    #[cfg(feature = "whirlpool")]
    pub use whirlpool::Whirlpool;
}

#[cfg(feature = "blake2")]
pub mod blake2;
#[cfg(feature = "md5")]
pub mod md5;
#[cfg(feature = "ripemd")]
pub mod ripemd;
#[cfg(feature = "sha1")]
pub mod sha1;
#[cfg(feature = "sha2")]
pub mod sha2;
#[cfg(feature = "sha3")]
pub mod sha3;
#[cfg(feature = "tiger")]
pub mod tiger;
#[cfg(feature = "whirlpool")]
pub mod whirlpool;

mod wrapping;
mod simd;
<commit_msg>fix(digest): remove unneeded feature gate<commit_after>//! Cryptographic hash functions primitives
//!
//! Via [Wikipedia](https://en.wikipedia.org/wiki/Cryptographic_hash_function):
//!
//! > The ideal cryptographic hash function has four main properties:
//! >
//! > - it is easy to compute the hash value for any given message
//! > - it is infeasible to generate a message from its hash
//! > - it is infeasible to modify a message without changing the hash
//! > - it is infeasible to find two different messages with the same hash.
//!
//! # Example
//!
//! Calculate SHA-512 sum:
//!
//! ```rust
//! # extern crate octavo_digest;
//! use octavo_digest::prelude::*;
//!
//! # fn main() {
//! # let data = "Hello World!";
//! let mut result = vec![0; sha2::Sha512::output_bytes()];
//! let mut sha = sha2::Sha512::default();
//!
//! sha.update(data);
//! sha.result(&mut result);
//!
//! for byte in result {
//!     print!("{:2x}", byte);
//! }
//! println!(" {}", data);
//! # }
//! ```

#![doc(html_logo_url = "https://raw.githubusercontent.com/libOctavo/octavo/master/docs/logo.png",
       html_root_url = "http://libOctavo.github.io/")]

#![no_std]

#![allow(inline_always, unknown_lints)]
#![forbid(overflowing_literals, missing_docs)]

extern crate generic_array;
extern crate static_buffer;
extern crate typenum;
extern crate byteorder;

use generic_array::ArrayLength;
use typenum::uint::Unsigned;

/// Hash function digest definition
pub trait Digest: Clone {
    /// Output size in bits
    type OutputBits: Unsigned + ArrayLength<u8>;
    /// Output size in bytes
    type OutputBytes: Unsigned + ArrayLength<u8>;

    /// Block size in bytes
    type BlockSize: Unsigned + ArrayLength<u8>;

    /// Update digest with data.
    fn update<T>(&mut self, input: T) where T: AsRef<[u8]>;

    /// Output size in bits
    fn output_bits() -> usize {
        Self::OutputBits::to_usize()
    }
    /// Output size in bytes
    fn output_bytes() -> usize {
        Self::OutputBytes::to_usize()
    }
    /// Block size in bytes
    fn block_size() -> usize {
        Self::BlockSize::to_usize()
    }

    /// Write resulting hash into `output`.
    ///
    /// `output` should be big enough to contain whole output.
    ///
    /// ## Panics
    ///
    /// If output length is less than `Digest::output_bytes`.
    fn result<T>(self, output: T) where T: AsMut<[u8]>;
}

/// Digest prelude
pub mod prelude {
    pub use Digest;

    #[cfg(feature = "blake2")]
    pub use blake2;
    #[cfg(feature = "md5")]
    pub use md5::Md5;
    #[cfg(feature = "ripemd")]
    pub use ripemd::Ripemd160;
    #[cfg(feature = "sha1")]
    pub use sha1::Sha1;
    #[cfg(feature = "sha2")]
    pub use sha2;
    #[cfg(feature = "sha3")]
    pub use sha3;
    #[cfg(feature = "tiger")]
    pub use tiger;
    #[cfg(feature = "whirlpool")]
    pub use whirlpool::Whirlpool;
}

#[cfg(feature = "blake2")]
pub mod blake2;
#[cfg(feature = "md5")]
pub mod md5;
#[cfg(feature = "ripemd")]
pub mod ripemd;
#[cfg(feature = "sha1")]
pub mod sha1;
#[cfg(feature = "sha2")]
pub mod sha2;
#[cfg(feature = "sha3")]
pub mod sha3;
#[cfg(feature = "tiger")]
pub mod tiger;
#[cfg(feature = "whirlpool")]
pub mod whirlpool;

mod wrapping;
mod simd;
<|endoftext|>