<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::cmp;
use collections::HashSet;
use std::local_data;
use std::uint;
use syntax::ast;
use rustc::util::nodemap::NodeSet;

use clean;
use clean::Item;
use plugins;
use fold;
use fold::DocFolder;

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
    let mut stripped = HashSet::new();

    // strip all #[doc(hidden)] items
    let krate = {
        struct Stripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for Stripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                for attr in i.attrs.iter() {
                    match attr {
                        &clean::List(ref x, ref l) if "doc" == *x => {
                            for innerattr in l.iter() {
                                match innerattr {
                                    &clean::Word(ref s) if "hidden" == *s => {
                                        debug!("found one in strip_hidden; removing");
                                        self.stripped.insert(i.id);
                                        return None;
                                    },
                                    _ => (),
                                }
                            }
                        },
                        _ => ()
                    }
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = Stripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    // strip any traits implemented on stripped items
    let krate = {
        struct ImplStripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for ImplStripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                match i.inner {
                    clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: for_id, .. },
                                                 .. }) => {
                        if self.stripped.contains(&for_id) {
                            return None;
                        }
                    }
                    _ => {}
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = ImplStripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    (krate, None)
}

/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
    // This stripper collects all *retained* nodes.
    let mut retained = HashSet::new();
    let exported_items = local_data::get(super::analysiskey, |analysis| {
        analysis.unwrap().exported_items.clone()
    });
    let mut krate = krate;

    // strip all private items
    {
        let mut stripper = Stripper {
            retained: &mut retained,
            exported_items: &exported_items,
        };
        krate = stripper.fold_crate(krate);
    }

    // strip all private implementations of traits
    {
        let mut stripper = ImplStripper(&retained);
        krate = stripper.fold_crate(krate);
    }
    (krate, None)
}

struct Stripper<'a> {
    retained: &'a mut HashSet<ast::NodeId>,
    exported_items: &'a NodeSet,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            // These items can all get re-exported
            clean::TypedefItem(..) | clean::StaticItem(..) |
            clean::StructItem(..) | clean::EnumItem(..) |
            clean::TraitItem(..) | clean::FunctionItem(..) |
            clean::VariantItem(..) | clean::MethodItem(..) |
            clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                if !self.exported_items.contains(&i.id) {
                    return None;
                }
            }

            clean::ViewItemItem(..) |
            clean::ModuleItem(..) => {
                if i.visibility != Some(ast::Public) {
                    return None
                }
            }

            clean::StructFieldItem(..) => {
                if i.visibility == Some(ast::Private) {
                    return None;
                }
            }

            // trait impls for private items should be stripped
            clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: ref for_id, .. }, .. }) => {
                if !self.exported_items.contains(for_id) {
                    return None;
                }
            }
            clean::ImplItem(..) => {}

            // tymethods/macros have no control over privacy
            clean::MacroItem(..) | clean::TyMethodItem(..) => {}
        }

        let fastreturn = match i.inner {
            // nothing left to do for traits (don't want to filter their
            // methods out, visibility controlled by the trait)
            clean::TraitItem(..) => true,

            // implementations of traits are always public.
            clean::ImplItem(ref imp) if imp.trait_.is_some() => true,

            _ => false,
        };

        let i = if fastreturn {
            self.retained.insert(i.id);
            return Some(i);
        } else {
            self.fold_item_recur(i)
        };

        match i {
            Some(i) => {
                match i.inner {
                    // emptied modules/impls have no need to exist
                    clean::ModuleItem(ref m)
                        if m.items.len() == 0 &&
                           i.doc_value().is_none() => None,
                    clean::ImplItem(ref i) if i.methods.len() == 0 => None,
                    _ => {
                        self.retained.insert(i.id);
                        Some(i)
                    }
                }
            }
            None => None,
        }
    }
}

// This stripper discards all private impls of traits
struct ImplStripper<'a>(&'a HashSet<ast::NodeId>);
impl<'a> fold::DocFolder for ImplStripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            clean::ImplItem(ref imp) => {
                match imp.trait_ {
                    Some(clean::ResolvedPath{ id, .. }) => {
                        let ImplStripper(s) = *self;
                        if !s.contains(&id) {
                            return None;
                        }
                    }
                    Some(..) | None => {}
                }
            }
            _ => {}
        }
        self.fold_item_recur(i)
    }
}

pub fn unindent_comments(krate: clean::Crate) -> plugins::PluginResult {
    struct CommentCleaner;
    impl fold::DocFolder for CommentCleaner {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut i = i;
            let mut avec: Vec<clean::Attribute> = Vec::new();
            for attr in i.attrs.iter() {
                match attr {
                    &clean::NameValue(ref x, ref s) if "doc" == *x => avec.push(
                        clean::NameValue(~"doc", unindent(*s))),
                    x => avec.push(x.clone())
                }
            }
            i.attrs = avec;
            self.fold_item_recur(i)
        }
    }
    let mut cleaner = CommentCleaner;
    let krate = cleaner.fold_crate(krate);
    (krate, None)
}

pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
    struct Collapser;
    impl fold::DocFolder for Collapser {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut docstr = ~"";
            let mut i = i;
            for attr in i.attrs.iter() {
                match *attr {
                    clean::NameValue(ref x, ref s) if "doc" == *x => {
                        docstr.push_str(s.clone());
                        docstr.push_char('\n');
                    },
                    _ => ()
                }
            }
            let mut a: Vec<clean::Attribute> = i.attrs.iter().filter(|&a| match a {
                &clean::NameValue(ref x, _) if "doc" == *x => false,
                _ => true
            }).map(|x| x.clone()).collect();
            if "" != docstr {
                a.push(clean::NameValue(~"doc", docstr));
            }
            i.attrs = a;
            self.fold_item_recur(i)
        }
    }
    let mut collapser = Collapser;
    let krate = collapser.fold_crate(krate);
    (krate, None)
}

pub fn unindent(s: &str) -> ~str {
    let lines = s.lines_any().collect::<Vec<&str> >();
    let mut saw_first_line = false;
    let mut saw_second_line = false;
    let min_indent = lines.iter().fold(uint::MAX, |min_indent, line| {

        // After we see the first non-whitespace line, look at
        // the line we have. If it is not whitespace, and therefore
        // part of the first paragraph, then ignore the indentation
        // level of the first line
        let ignore_previous_indents =
            saw_first_line &&
            !saw_second_line &&
            !line.is_whitespace();

        let min_indent = if ignore_previous_indents {
            uint::MAX
        } else {
            min_indent
        };

        if saw_first_line {
            saw_second_line = true;
        }

        if line.is_whitespace() {
            min_indent
        } else {
            saw_first_line = true;
            let mut spaces = 0;
            line.chars().all(|char| {
                // Only comparing against space because I wouldn't
                // know what to do with mixed whitespace chars
                if char == ' ' {
                    spaces += 1;
                    true
                } else {
                    false
                }
            });
            cmp::min(min_indent, spaces)
        }
    });

    if lines.len() >= 1 {
        let mut unindented = vec!( lines.get(0).trim() );
        unindented.push_all(lines.tail().map(|&line| {
            if line.is_whitespace() {
                line
            } else {
                assert!(line.len() >= min_indent);
                line.slice_from(min_indent)
            }
        }));
        unindented.connect("\n")
    } else {
        s.to_owned()
    }
}

#[cfg(test)]
mod unindent_tests {
    use super::unindent;

    #[test]
    fn should_unindent() {
        let s = ~"    line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_unindent_multiple_paragraphs() {
        let s = ~"    line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\nline2");
    }

    #[test]
    fn should_leave_multiple_indent_levels() {
        // Line 2 is indented another level beyond the
        // base indentation and should be preserved
        let s = ~"    line1\n\n        line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }

    #[test]
    fn should_ignore_first_line_indent() {
        // Thi first line of the first paragraph may not be indented as
        // far due to the way the doc string was written:
        //
        // #[doc = "Start way over here
        //          and continue here"]
        let s = ~"line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_not_ignore_first_line_indent_in_a_single_line_para() {
        let s = ~"line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }
}
<commit_msg>Revert "Modules are either public, or private, so private modules should be stripped out"<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::cmp;
use collections::HashSet;
use std::local_data;
use std::uint;
use syntax::ast;
use rustc::util::nodemap::NodeSet;

use clean;
use clean::Item;
use plugins;
use fold;
use fold::DocFolder;

/// Strip items marked `#[doc(hidden)]`
pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
    let mut stripped = HashSet::new();

    // strip all #[doc(hidden)] items
    let krate = {
        struct Stripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for Stripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                for attr in i.attrs.iter() {
                    match attr {
                        &clean::List(ref x, ref l) if "doc" == *x => {
                            for innerattr in l.iter() {
                                match innerattr {
                                    &clean::Word(ref s) if "hidden" == *s => {
                                        debug!("found one in strip_hidden; removing");
                                        self.stripped.insert(i.id);
                                        return None;
                                    },
                                    _ => (),
                                }
                            }
                        },
                        _ => ()
                    }
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = Stripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    // strip any traits implemented on stripped items
    let krate = {
        struct ImplStripper<'a> {
            stripped: &'a mut HashSet<ast::NodeId>
        };
        impl<'a> fold::DocFolder for ImplStripper<'a> {
            fn fold_item(&mut self, i: Item) -> Option<Item> {
                match i.inner {
                    clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: for_id, .. },
                                                 .. }) => {
                        if self.stripped.contains(&for_id) {
                            return None;
                        }
                    }
                    _ => {}
                }
                self.fold_item_recur(i)
            }
        }
        let mut stripper = ImplStripper{ stripped: &mut stripped };
        stripper.fold_crate(krate)
    };

    (krate, None)
}

/// Strip private items from the point of view of a crate or externally from a
/// crate, specified by the `xcrate` flag.
pub fn strip_private(krate: clean::Crate) -> plugins::PluginResult {
    // This stripper collects all *retained* nodes.
    let mut retained = HashSet::new();
    let exported_items = local_data::get(super::analysiskey, |analysis| {
        analysis.unwrap().exported_items.clone()
    });
    let mut krate = krate;

    // strip all private items
    {
        let mut stripper = Stripper {
            retained: &mut retained,
            exported_items: &exported_items,
        };
        krate = stripper.fold_crate(krate);
    }

    // strip all private implementations of traits
    {
        let mut stripper = ImplStripper(&retained);
        krate = stripper.fold_crate(krate);
    }
    (krate, None)
}

struct Stripper<'a> {
    retained: &'a mut HashSet<ast::NodeId>,
    exported_items: &'a NodeSet,
}

impl<'a> fold::DocFolder for Stripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            // These items can all get re-exported
            clean::TypedefItem(..) | clean::StaticItem(..) |
            clean::StructItem(..) | clean::EnumItem(..) |
            clean::TraitItem(..) | clean::FunctionItem(..) |
            clean::VariantItem(..) | clean::MethodItem(..) |
            clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                if !self.exported_items.contains(&i.id) {
                    return None;
                }
            }

            clean::ViewItemItem(..) => {
                if i.visibility != Some(ast::Public) {
                    return None
                }
            }

            clean::StructFieldItem(..) => {
                if i.visibility == Some(ast::Private) {
                    return None;
                }
            }

            // handled below
            clean::ModuleItem(..) => {}

            // trait impls for private items should be stripped
            clean::ImplItem(clean::Impl{ for_: clean::ResolvedPath{ id: ref for_id, .. }, .. }) => {
                if !self.exported_items.contains(for_id) {
                    return None;
                }
            }
            clean::ImplItem(..) => {}

            // tymethods/macros have no control over privacy
            clean::MacroItem(..) | clean::TyMethodItem(..) => {}
        }

        let fastreturn = match i.inner {
            // nothing left to do for traits (don't want to filter their
            // methods out, visibility controlled by the trait)
            clean::TraitItem(..) => true,

            // implementations of traits are always public.
            clean::ImplItem(ref imp) if imp.trait_.is_some() => true,

            _ => false,
        };

        let i = if fastreturn {
            self.retained.insert(i.id);
            return Some(i);
        } else {
            self.fold_item_recur(i)
        };

        match i {
            Some(i) => {
                match i.inner {
                    // emptied modules/impls have no need to exist
                    clean::ModuleItem(ref m)
                        if m.items.len() == 0 &&
                           i.doc_value().is_none() => None,
                    clean::ImplItem(ref i) if i.methods.len() == 0 => None,
                    _ => {
                        self.retained.insert(i.id);
                        Some(i)
                    }
                }
            }
            None => None,
        }
    }
}

// This stripper discards all private impls of traits
struct ImplStripper<'a>(&'a HashSet<ast::NodeId>);
impl<'a> fold::DocFolder for ImplStripper<'a> {
    fn fold_item(&mut self, i: Item) -> Option<Item> {
        match i.inner {
            clean::ImplItem(ref imp) => {
                match imp.trait_ {
                    Some(clean::ResolvedPath{ id, .. }) => {
                        let ImplStripper(s) = *self;
                        if !s.contains(&id) {
                            return None;
                        }
                    }
                    Some(..) | None => {}
                }
            }
            _ => {}
        }
        self.fold_item_recur(i)
    }
}

pub fn unindent_comments(krate: clean::Crate) -> plugins::PluginResult {
    struct CommentCleaner;
    impl fold::DocFolder for CommentCleaner {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut i = i;
            let mut avec: Vec<clean::Attribute> = Vec::new();
            for attr in i.attrs.iter() {
                match attr {
                    &clean::NameValue(ref x, ref s) if "doc" == *x => avec.push(
                        clean::NameValue(~"doc", unindent(*s))),
                    x => avec.push(x.clone())
                }
            }
            i.attrs = avec;
            self.fold_item_recur(i)
        }
    }
    let mut cleaner = CommentCleaner;
    let krate = cleaner.fold_crate(krate);
    (krate, None)
}

pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
    struct Collapser;
    impl fold::DocFolder for Collapser {
        fn fold_item(&mut self, i: Item) -> Option<Item> {
            let mut docstr = ~"";
            let mut i = i;
            for attr in i.attrs.iter() {
                match *attr {
                    clean::NameValue(ref x, ref s) if "doc" == *x => {
                        docstr.push_str(s.clone());
                        docstr.push_char('\n');
                    },
                    _ => ()
                }
            }
            let mut a: Vec<clean::Attribute> = i.attrs.iter().filter(|&a| match a {
                &clean::NameValue(ref x, _) if "doc" == *x => false,
                _ => true
            }).map(|x| x.clone()).collect();
            if "" != docstr {
                a.push(clean::NameValue(~"doc", docstr));
            }
            i.attrs = a;
            self.fold_item_recur(i)
        }
    }
    let mut collapser = Collapser;
    let krate = collapser.fold_crate(krate);
    (krate, None)
}

pub fn unindent(s: &str) -> ~str {
    let lines = s.lines_any().collect::<Vec<&str> >();
    let mut saw_first_line = false;
    let mut saw_second_line = false;
    let min_indent = lines.iter().fold(uint::MAX, |min_indent, line| {

        // After we see the first non-whitespace line, look at
        // the line we have. If it is not whitespace, and therefore
        // part of the first paragraph, then ignore the indentation
        // level of the first line
        let ignore_previous_indents =
            saw_first_line &&
            !saw_second_line &&
            !line.is_whitespace();

        let min_indent = if ignore_previous_indents {
            uint::MAX
        } else {
            min_indent
        };

        if saw_first_line {
            saw_second_line = true;
        }

        if line.is_whitespace() {
            min_indent
        } else {
            saw_first_line = true;
            let mut spaces = 0;
            line.chars().all(|char| {
                // Only comparing against space because I wouldn't
                // know what to do with mixed whitespace chars
                if char == ' ' {
                    spaces += 1;
                    true
                } else {
                    false
                }
            });
            cmp::min(min_indent, spaces)
        }
    });

    if lines.len() >= 1 {
        let mut unindented = vec!( lines.get(0).trim() );
        unindented.push_all(lines.tail().map(|&line| {
            if line.is_whitespace() {
                line
            } else {
                assert!(line.len() >= min_indent);
                line.slice_from(min_indent)
            }
        }));
        unindented.connect("\n")
    } else {
        s.to_owned()
    }
}

#[cfg(test)]
mod unindent_tests {
    use super::unindent;

    #[test]
    fn should_unindent() {
        let s = ~"    line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_unindent_multiple_paragraphs() {
        let s = ~"    line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\nline2");
    }

    #[test]
    fn should_leave_multiple_indent_levels() {
        // Line 2 is indented another level beyond the
        // base indentation and should be preserved
        let s = ~"    line1\n\n        line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }

    #[test]
    fn should_ignore_first_line_indent() {
        // Thi first line of the first paragraph may not be indented as
        // far due to the way the doc string was written:
        //
        // #[doc = "Start way over here
        //          and continue here"]
        let s = ~"line1\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\nline2");
    }

    #[test]
    fn should_not_ignore_first_line_indent_in_a_single_line_para() {
        let s = ~"line1\n\n    line2";
        let r = unindent(s);
        assert_eq!(r, ~"line1\n\n    line2");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Philipp Oppermann. See the README.md
// 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.

pub use self::entry::*;
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use self::table::{Table, Level4};
use self::temporary_page::TemporaryPage;
pub use self::mapper::Mapper;
use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use multiboot2::BootInformation;

mod entry;
mod table;
mod temporary_page;
mod mapper;

const ENTRY_COUNT: usize = 512;

pub type PhysicalAddress = usize;
pub type VirtualAddress = usize;

#[derive(Debug, Clone, Copy)]
pub struct Page {
    number: usize,
}

impl Page {
    pub fn containing_address(address: VirtualAddress) -> Page {
        assert!(address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
                "invalid address: 0x{:x}",
                address);
        Page { number: address / PAGE_SIZE }
    }

    fn start_address(&self) -> usize {
        self.number * PAGE_SIZE
    }

    fn p4_index(&self) -> usize {
        (self.number >> 27) & 0o777
    }
    fn p3_index(&self) -> usize {
        (self.number >> 18) & 0o777
    }
    fn p2_index(&self) -> usize {
        (self.number >> 9) & 0o777
    }
    fn p1_index(&self) -> usize {
        (self.number >> 0) & 0o777
    }
}

pub struct ActivePageTable {
    mapper: Mapper,
}

impl Deref for ActivePageTable {
    type Target = Mapper;

    fn deref(&self) -> &Mapper {
        &self.mapper
    }
}

impl DerefMut for ActivePageTable {
    fn deref_mut(&mut self) -> &mut Mapper {
        &mut self.mapper
    }
}

impl ActivePageTable {
    unsafe fn new() -> ActivePageTable {
        ActivePageTable { mapper: Mapper::new() }
    }

    pub fn with<F>(&mut self,
                   table: &mut InactivePageTable,
                   temporary_page: &mut temporary_page::TemporaryPage, // new
                   f: F)
        where F: FnOnce(&mut Mapper)
    {
        use x86::{controlregs, tlb};
        let flush_tlb = || unsafe { tlb::flush_all() };

        {
            let backup = Frame::containing_address(unsafe { controlregs::cr3() } as usize);

            // map temporary_page to current p4 table
            let p4_table = temporary_page.map_table_frame(backup.clone(), self);

            // overwrite recursive mapping
            self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE);
            flush_tlb();

            // execute f in the new context
            f(self);

            // restore recursive mapping to original p4 table
            p4_table[511].set(backup, PRESENT | WRITABLE);
            flush_tlb();
        }

        temporary_page.unmap(self);
    }

    pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
        use x86::controlregs;

        let old_table = InactivePageTable {
            p4_frame: Frame::containing_address(unsafe { controlregs::cr3() } as usize),
        };
        unsafe {
            controlregs::cr3_write(new_table.p4_frame.start_address() as u64);
        }
        old_table
    }
}

pub struct InactivePageTable {
    p4_frame: Frame,
}

impl InactivePageTable {
    pub fn new(frame: Frame,
               active_table: &mut ActivePageTable,
               temporary_page: &mut TemporaryPage)
               -> InactivePageTable {
        {
            let table = temporary_page.map_table_frame(frame.clone(), active_table);
            table.zero();
            table[511].set(frame.clone(), PRESENT | WRITABLE);
        }
        temporary_page.unmap(active_table);

        InactivePageTable { p4_frame: frame }
    }
}

pub fn test_paging<A>(allocator: &mut A)
    where A: FrameAllocator
{
    let mut page_table = unsafe { ActivePageTable::new() };

    // test translate
    println!("Some = {:?}", page_table.translate(0));
    println!("Some = {:?}", page_table.translate(4096)); // second P1 entry
    println!("Some = {:?}", page_table.translate(512 * 4096)); // second P2 entry
    println!("Some = {:?}", page_table.translate(300 * 512 * 4096)); // 300th P2 entry
    println!("None = {:?}", page_table.translate(512 * 512 * 4096)); // second P3 entry
    println!("Some = {:?}", page_table.translate(512 * 512 * 4096 - 1)); // last mapped byte

    // test map_to
    let addr = 42 * 512 * 512 * 4096; // 42th P3 entry
    let page = Page::containing_address(addr);
    let frame = allocator.allocate_frame().expect("no more frames");
    println!("None = {:?}, map to {:?}",
             page_table.translate(addr),
             frame);
    page_table.map_to(page, frame, EntryFlags::empty(), allocator);
    println!("Some = {:?}", page_table.translate(addr));
    println!("next free frame: {:?}", allocator.allocate_frame());

    // test unmap
    println!("{:#x}",
             unsafe { *(Page::containing_address(addr).start_address() as *const u64) });
    page_table.unmap(Page::containing_address(addr), allocator);
    println!("None = {:?}", page_table.translate(addr));
}

pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
    where A: FrameAllocator
{
    use core::ops::Range;

    let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe }, allocator);

    let mut active_table = unsafe { ActivePageTable::new() };
    let mut new_table = {
        let frame = allocator.allocate_frame().expect("no more frames");
        InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
    };

    active_table.with(&mut new_table, &mut temporary_page, |mapper| {
        let elf_sections_tag = boot_info.elf_sections_tag()
                                        .expect("Memory map tag required");

        for section in elf_sections_tag.sections() {
            use multiboot2::ELF_SECTION_ALLOCATED;
            use self::entry::WRITABLE;

            if !section.flags().contains(ELF_SECTION_ALLOCATED) {
                // section is not loaded to memory
                continue;
            }

            println!("mapping section at addr: {:#x}, size: {:#x}",
                     section.addr,
                     section.size);

            let flags = EntryFlags::from_elf_section_flags(section);

            let range = Range {
                start: section.addr as usize,
                end: (section.addr + section.size) as usize,
            };
            for address in range.step_by(PAGE_SIZE) {
                assert!(address % PAGE_SIZE == 0, "sections need to be page aligned");
                let frame = Frame::containing_address(address);
                mapper.identity_map(frame, flags, allocator);
            }
        }

        let vga_buffer_frame = Frame::containing_address(0xb8000);
        mapper.identity_map(vga_buffer_frame, WRITABLE, allocator);
    });

    let old_table = active_table.switch(new_table);
    println!("NEW TABLE!!!");
}
<commit_msg>Unmap the old P4 page to create a basic guard page for the kernel stack<commit_after>// Copyright 2015 Philipp Oppermann. See the README.md
// 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.

pub use self::entry::*;
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use self::table::{Table, Level4};
use self::temporary_page::TemporaryPage;
pub use self::mapper::Mapper;
use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use multiboot2::BootInformation;

mod entry;
mod table;
mod temporary_page;
mod mapper;

const ENTRY_COUNT: usize = 512;

pub type PhysicalAddress = usize;
pub type VirtualAddress = usize;

#[derive(Debug, Clone, Copy)]
pub struct Page {
    number: usize,
}

impl Page {
    pub fn containing_address(address: VirtualAddress) -> Page {
        assert!(address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
                "invalid address: 0x{:x}",
                address);
        Page { number: address / PAGE_SIZE }
    }

    fn start_address(&self) -> usize {
        self.number * PAGE_SIZE
    }

    fn p4_index(&self) -> usize {
        (self.number >> 27) & 0o777
    }
    fn p3_index(&self) -> usize {
        (self.number >> 18) & 0o777
    }
    fn p2_index(&self) -> usize {
        (self.number >> 9) & 0o777
    }
    fn p1_index(&self) -> usize {
        (self.number >> 0) & 0o777
    }
}

pub struct ActivePageTable {
    mapper: Mapper,
}

impl Deref for ActivePageTable {
    type Target = Mapper;

    fn deref(&self) -> &Mapper {
        &self.mapper
    }
}

impl DerefMut for ActivePageTable {
    fn deref_mut(&mut self) -> &mut Mapper {
        &mut self.mapper
    }
}

impl ActivePageTable {
    unsafe fn new() -> ActivePageTable {
        ActivePageTable { mapper: Mapper::new() }
    }

    pub fn with<F>(&mut self,
                   table: &mut InactivePageTable,
                   temporary_page: &mut temporary_page::TemporaryPage, // new
                   f: F)
        where F: FnOnce(&mut Mapper)
    {
        use x86::{controlregs, tlb};
        let flush_tlb = || unsafe { tlb::flush_all() };

        {
            let backup = Frame::containing_address(unsafe { controlregs::cr3() } as usize);

            // map temporary_page to current p4 table
            let p4_table = temporary_page.map_table_frame(backup.clone(), self);

            // overwrite recursive mapping
            self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE);
            flush_tlb();

            // execute f in the new context
            f(self);

            // restore recursive mapping to original p4 table
            p4_table[511].set(backup, PRESENT | WRITABLE);
            flush_tlb();
        }

        temporary_page.unmap(self);
    }

    pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
        use x86::controlregs;

        let old_table = InactivePageTable {
            p4_frame: Frame::containing_address(unsafe { controlregs::cr3() } as usize),
        };
        unsafe {
            controlregs::cr3_write(new_table.p4_frame.start_address() as u64);
        }
        old_table
    }
}

pub struct InactivePageTable {
    p4_frame: Frame,
}

impl InactivePageTable {
    pub fn new(frame: Frame,
               active_table: &mut ActivePageTable,
               temporary_page: &mut TemporaryPage)
               -> InactivePageTable {
        {
            let table = temporary_page.map_table_frame(frame.clone(), active_table);
            table.zero();
            table[511].set(frame.clone(), PRESENT | WRITABLE);
        }
        temporary_page.unmap(active_table);

        InactivePageTable { p4_frame: frame }
    }
}

pub fn test_paging<A>(allocator: &mut A)
    where A: FrameAllocator
{
    let mut page_table = unsafe { ActivePageTable::new() };

    // test translate
    println!("Some = {:?}", page_table.translate(0));
    println!("Some = {:?}", page_table.translate(4096)); // second P1 entry
    println!("Some = {:?}", page_table.translate(512 * 4096)); // second P2 entry
    println!("Some = {:?}", page_table.translate(300 * 512 * 4096)); // 300th P2 entry
    println!("None = {:?}", page_table.translate(512 * 512 * 4096)); // second P3 entry
    println!("Some = {:?}", page_table.translate(512 * 512 * 4096 - 1)); // last mapped byte

    // test map_to
    let addr = 42 * 512 * 512 * 4096; // 42th P3 entry
    let page = Page::containing_address(addr);
    let frame = allocator.allocate_frame().expect("no more frames");
    println!("None = {:?}, map to {:?}",
             page_table.translate(addr),
             frame);
    page_table.map_to(page, frame, EntryFlags::empty(), allocator);
    println!("Some = {:?}", page_table.translate(addr));
    println!("next free frame: {:?}", allocator.allocate_frame());

    // test unmap
    println!("{:#x}",
             unsafe { *(Page::containing_address(addr).start_address() as *const u64) });
    page_table.unmap(Page::containing_address(addr), allocator);
    println!("None = {:?}", page_table.translate(addr));
}

pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation)
    where A: FrameAllocator
{
    use core::ops::Range;

    let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe }, allocator);

    let mut active_table = unsafe { ActivePageTable::new() };
    let mut new_table = {
        let frame = allocator.allocate_frame().expect("no more frames");
        InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
    };

    active_table.with(&mut new_table, &mut temporary_page, |mapper| {
        let elf_sections_tag = boot_info.elf_sections_tag()
                                        .expect("Memory map tag required");

        for section in elf_sections_tag.sections() {
            use multiboot2::ELF_SECTION_ALLOCATED;
            use self::entry::WRITABLE;

            if !section.flags().contains(ELF_SECTION_ALLOCATED) {
                // section is not loaded to memory
                continue;
            }

            println!("mapping section at addr: {:#x}, size: {:#x}",
                     section.addr,
                     section.size);

            let flags = EntryFlags::from_elf_section_flags(section);

            let range = Range {
                start: section.addr as usize,
                end: (section.addr + section.size) as usize,
            };
            for address in range.step_by(PAGE_SIZE) {
                assert!(address % PAGE_SIZE == 0, "sections need to be page aligned");
                let frame = Frame::containing_address(address);
                mapper.identity_map(frame, flags, allocator);
            }
        }

        let vga_buffer_frame = Frame::containing_address(0xb8000);
        mapper.identity_map(vga_buffer_frame, WRITABLE, allocator);
    });

    let old_table = active_table.switch(new_table);
    println!("NEW TABLE!!!");

    let old_p4_page = Page::containing_address(old_table.p4_frame.start_address());
    active_table.unmap(old_p4_page, allocator);
    println!("guard page at {:#x}", old_p4_page.start_address());
}
<|endoftext|>


<commit_before>use pyo3::ffi::{Py_hash_t, Py_intptr_t, Py_uintptr_t};
use std::os::raw::*;

pub type npy_intp = Py_intptr_t;
pub type npy_uintp = Py_uintptr_t;
pub type npy_longlong = c_longlong;
pub type npy_ulonglong = c_ulonglong;
pub type npy_bool = c_uchar;
pub type npy_longdouble = f64;
pub type npy_byte = c_char;
pub type npy_ubyte = c_uchar;
pub type npy_ushort = c_ushort;
pub type npy_uint = c_uint;
pub type npy_ulong = c_ulong;
pub type npy_char = c_char;
pub type npy_short = c_short;
pub type npy_int = c_int;
pub type npy_long = c_long;
pub type npy_float = f32;
pub type npy_double = f64;
pub type npy_hash_t = Py_hash_t;
pub type npy_int64 = c_long;
pub type npy_uint64 = c_ulong;
pub type npy_int32 = c_int;
pub type npy_uint32 = c_uint;
pub type npy_ucs4 = c_uint;
pub type npy_int16 = c_short;
pub type npy_uint16 = c_ushort;
pub type npy_int8 = c_char;
pub type npy_uint8 = c_uchar;
pub type npy_float64 = f64;
pub type npy_complex128 = npy_cdouble;
pub type npy_float32 = f32;
pub type npy_complex64 = npy_cfloat;
pub type npy_half = npy_uint16;
pub type npy_float16 = npy_half;
pub type npy_float128 = npy_longdouble;
pub type npy_complex256 = npy_clongdouble;
pub type npy_timedelta = npy_int64;
pub type npy_datetime = npy_int64;

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cdouble {
    pub real: f64,
    pub imag: f64,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cfloat {
    pub real: f32,
    pub imag: f32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_clongdouble {
    pub real: npy_longdouble,
    pub imag: npy_longdouble,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_ORDER {
    NPY_ANYORDER = -1,
    NPY_CORDER = 0,
    NPY_FORTRANORDER = 1,
    NPY_KEEPORDER = 2,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SCALARKIND {
    NPY_NOSCALAR = -1,
    NPY_BOOL_SCALAR = 0,
    NPY_INTPOS_SCALAR = 1,
    NPY_INTNEG_SCALAR = 2,
    NPY_FLOAT_SCALAR = 3,
    NPY_COMPLEX_SCALAR = 4,
    NPY_OBJECT_SCALAR = 5,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SORTKIND {
    NPY_QUICKSORT = 0,
    NPY_HEAPSORT = 1,
    NPY_MERGESORT = 2,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SEARCHSIDE {
    NPY_SEARCHLEFT = 0,
    NPY_SEARCHRIGHT = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_DATETIMEUNIT {
    NPY_FR_Y = 0,
    NPY_FR_M = 1,
    NPY_FR_W = 2,
    NPY_FR_D = 4,
    NPY_FR_h = 5,
    NPY_FR_m = 6,
    NPY_FR_s = 7,
    NPY_FR_ms = 8,
    NPY_FR_us = 9,
    NPY_FR_ns = 10,
    NPY_FR_ps = 11,
    NPY_FR_fs = 12,
    NPY_FR_as = 13,
    NPY_FR_GENERIC = 14,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_TYPES {
    NPY_BOOL = 0,
    NPY_BYTE = 1,
    NPY_UBYTE = 2,
    NPY_SHORT = 3,
    NPY_USHORT = 4,
    NPY_INT = 5,
    NPY_UINT = 6,
    NPY_LONG = 7,
    NPY_ULONG = 8,
    NPY_LONGLONG = 9,
    NPY_ULONGLONG = 10,
    NPY_FLOAT = 11,
    NPY_DOUBLE = 12,
    NPY_LONGDOUBLE = 13,
    NPY_CFLOAT = 14,
    NPY_CDOUBLE = 15,
    NPY_CLONGDOUBLE = 16,
    NPY_OBJECT = 17,
    NPY_STRING = 18,
    NPY_UNICODE = 19,
    NPY_VOID = 20,
    NPY_DATETIME = 21,
    NPY_TIMEDELTA = 22,
    NPY_HALF = 23,
    NPY_NTYPES = 24,
    NPY_NOTYPE = 25,
    NPY_CHAR = 26,
    NPY_USERDEF = 256,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SELECTKIND {
    NPY_INTROSELECT = 0,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CASTING {
    NPY_NO_CASTING = 0,
    NPY_EQUIV_CASTING = 1,
    NPY_SAFE_CASTING = 2,
    NPY_SAME_KIND_CASTING = 3,
    NPY_UNSAFE_CASTING = 4,
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_datetimestruct {
    pub year: npy_int64,
    pub month: npy_int32,
    pub day: npy_int32,
    pub hour: npy_int32,
    pub min: npy_int32,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_timedeltastruct {
    pub day: npy_int64,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_stride_sort_item {
    pub perm: npy_intp,
    pub stride: npy_intp,
}
<commit_msg>ffi: add a few char-like enums<commit_after>use pyo3::ffi::{Py_hash_t, Py_intptr_t, Py_uintptr_t};
use std::os::raw::*;

pub type npy_intp = Py_intptr_t;
pub type npy_uintp = Py_uintptr_t;
pub type npy_longlong = c_longlong;
pub type npy_ulonglong = c_ulonglong;
pub type npy_bool = c_uchar;
pub type npy_longdouble = f64;
pub type npy_byte = c_char;
pub type npy_ubyte = c_uchar;
pub type npy_ushort = c_ushort;
pub type npy_uint = c_uint;
pub type npy_ulong = c_ulong;
pub type npy_char = c_char;
pub type npy_short = c_short;
pub type npy_int = c_int;
pub type npy_long = c_long;
pub type npy_float = f32;
pub type npy_double = f64;
pub type npy_hash_t = Py_hash_t;
pub type npy_int64 = c_long;
pub type npy_uint64 = c_ulong;
pub type npy_int32 = c_int;
pub type npy_uint32 = c_uint;
pub type npy_ucs4 = c_uint;
pub type npy_int16 = c_short;
pub type npy_uint16 = c_ushort;
pub type npy_int8 = c_char;
pub type npy_uint8 = c_uchar;
pub type npy_float64 = f64;
pub type npy_complex128 = npy_cdouble;
pub type npy_float32 = f32;
pub type npy_complex64 = npy_cfloat;
pub type npy_half = npy_uint16;
pub type npy_float16 = npy_half;
pub type npy_float128 = npy_longdouble;
pub type npy_complex256 = npy_clongdouble;
pub type npy_timedelta = npy_int64;
pub type npy_datetime = npy_int64;

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cdouble {
    pub real: f64,
    pub imag: f64,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_cfloat {
    pub real: f32,
    pub imag: f32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_clongdouble {
    pub real: npy_longdouble,
    pub imag: npy_longdouble,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_ORDER {
    NPY_ANYORDER = -1,
    NPY_CORDER = 0,
    NPY_FORTRANORDER = 1,
    NPY_KEEPORDER = 2,
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SCALARKIND {
    NPY_NOSCALAR = -1,
    NPY_BOOL_SCALAR = 0,
    NPY_INTPOS_SCALAR = 1,
    NPY_INTNEG_SCALAR = 2,
    NPY_FLOAT_SCALAR = 3,
    NPY_COMPLEX_SCALAR = 4,
    NPY_OBJECT_SCALAR = 5,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SORTKIND {
    NPY_QUICKSORT = 0,
    NPY_HEAPSORT = 1,
    NPY_MERGESORT = 2,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SEARCHSIDE {
    NPY_SEARCHLEFT = 0,
    NPY_SEARCHRIGHT = 1,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_DATETIMEUNIT {
    NPY_FR_Y = 0,
    NPY_FR_M = 1,
    NPY_FR_W = 2,
    NPY_FR_D = 4,
    NPY_FR_h = 5,
    NPY_FR_m = 6,
    NPY_FR_s = 7,
    NPY_FR_ms = 8,
    NPY_FR_us = 9,
    NPY_FR_ns = 10,
    NPY_FR_ps = 11,
    NPY_FR_fs = 12,
    NPY_FR_as = 13,
    NPY_FR_GENERIC = 14,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_TYPES {
    NPY_BOOL = 0,
    NPY_BYTE = 1,
    NPY_UBYTE = 2,
    NPY_SHORT = 3,
    NPY_USHORT = 4,
    NPY_INT = 5,
    NPY_UINT = 6,
    NPY_LONG = 7,
    NPY_ULONG = 8,
    NPY_LONGLONG = 9,
    NPY_ULONGLONG = 10,
    NPY_FLOAT = 11,
    NPY_DOUBLE = 12,
    NPY_LONGDOUBLE = 13,
    NPY_CFLOAT = 14,
    NPY_CDOUBLE = 15,
    NPY_CLONGDOUBLE = 16,
    NPY_OBJECT = 17,
    NPY_STRING = 18,
    NPY_UNICODE = 19,
    NPY_VOID = 20,
    NPY_DATETIME = 21,
    NPY_TIMEDELTA = 22,
    NPY_HALF = 23,
    NPY_NTYPES = 24,
    NPY_NOTYPE = 25,
    NPY_CHAR = 26,
    NPY_USERDEF = 256,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_SELECTKIND {
    NPY_INTROSELECT = 0,
}

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CASTING {
    NPY_NO_CASTING = 0,
    NPY_EQUIV_CASTING = 1,
    NPY_SAFE_CASTING = 2,
    NPY_SAME_KIND_CASTING = 3,
    NPY_UNSAFE_CASTING = 4,
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_datetimestruct {
    pub year: npy_int64,
    pub month: npy_int32,
    pub day: npy_int32,
    pub hour: npy_int32,
    pub min: npy_int32,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_timedeltastruct {
    pub day: npy_int64,
    pub sec: npy_int32,
    pub us: npy_int32,
    pub ps: npy_int32,
    pub as_: npy_int32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct npy_stride_sort_item {
    pub perm: npy_intp,
    pub stride: npy_intp,
}

#[repr(u8)]
#[derive(Debug, Clone, Copy)]
enum NPY_TYPECHAR {
    NPY_BOOLLTR = b'?',
    NPY_BYTELTR = b'b',
    NPY_UBYTELTR = b'B',
    NPY_SHORTLTR = b'h',
    NPY_USHORTLTR = b'H',
    NPY_INTLTR = b'i',
    NPY_UINTLTR = b'I',
    NPY_LONGLTR = b'l',
    NPY_ULONGLTR = b'L',
    NPY_LONGLONGLTR = b'q',
    NPY_ULONGLONGLTR = b'Q',
    NPY_HALFLTR = b'e',
    NPY_FLOATLTR = b'f',
    NPY_DOUBLELTR = b'd',
    NPY_LONGDOUBLELTR = b'g',
    NPY_CFLOATLTR = b'F',
    NPY_CDOUBLELTR = b'D',
    NPY_CLONGDOUBLELTR = b'G',
    NPY_OBJECTLTR = b'O',
    NPY_STRINGLTR = b'S',
    NPY_STRINGLTR2 = b'a',
    NPY_UNICODELTR = b'U',
    NPY_VOIDLTR = b'V',
    NPY_DATETIMELTR = b'M',
    NPY_TIMEDELTALTR = b'm',
    NPY_CHARLTR = b'c',
    NPY_INTPLTR = b'p',
    NPY_UINTPLTR = b'P',
}

#[repr(u8)]
#[derive(Debug, Clone, Copy)]
// NPY_TYPEKINDCHAR doesn't exist in the header, but these enum values are not
// related to NPY_TYPECHAR although being stuffed into it (type kinds, not type codes)
enum NPY_TYPEKINDCHAR {
    NPY_GENBOOLLTR = b'b',
    NPY_SIGNEDLTR = b'i',
    NPY_UNSIGNEDLTR = b'u',
    NPY_FLOATINGLTR = b'f',
    NPY_COMPLEXLTR = b'c',
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_BYTEORDER_CHAR {
    NPY_LITTLE = b'<',
    NPY_BIG = b'>',
    NPY_NATIVE = b'=',
    NPY_SWAP = b's',
    NPY_IGNORE = b'|',
}

impl NPY_BYTEORDER_CHAR {
    #[cfg(target_endian = "little")]
    pub const NPY_NATBYTE: Self = Self::NPY_LITTLE;
    #[cfg(target_endian = "little")]
    pub const NPY_OPPBYTE: Self = Self::NPY_BIG;

    #[cfg(target_endian = "big")]
    pub const NPY_NATBYTE: Self = Self::NPY_BIG;
    #[cfg(target_endian = "big")]
    pub const NPY_OPPBYTE: Self = Self::NPY_LITTLE;
}
<|endoftext|>


<commit_before>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt::{Show, Result, Formatter};
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : &'a str,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
fn get_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

// Creates a Session Object, which contains all reused
// parameters for OAuth 1.0A
impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: &'a str) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }

    pub fn get_temporary_credentials(&self) {

    }

    fn get_header(&self) -> String {
        let header = format!("Authorization: OAuth oauth_consumer_key={}\
                &oauth_signature={}&oauth_signature_method=\"{}\"\
                &oauth_token={}&oauth_version=1.0",
                self.oauth_consumer_key, self.oauth_signature,
                self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            "PLAINTEXT" => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
                        header, now_utc().to_timespec().sec, get_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    use oauth::oauth1::Session;

    // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            "HMAC-SHA1");
        println!("{}", s.get_header());
    }
}
<commit_msg>added some comments<commit_after>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt::{Show, Result, Formatter};
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : &'a str,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
fn get_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

// Creates a Session Object, which contains all reused
// parameters for OAuth 1.0A
impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: &'a str) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }

    pub fn get_temporary_credentials(&self) {

    }

    // Creates a URL encoded String containing headers
    // This should be called everytime you make a request, since the
    // `oauth_timestamp` and `oauth_nonce` need to freshly made
    fn get_header(&self) -> String {
        let header = format!("Authorization: OAuth oauth_consumer_key={}\
                &oauth_signature={}&oauth_signature_method=\"{}\"\
                &oauth_token={}&oauth_version=1.0",
                self.oauth_consumer_key, self.oauth_signature,
                self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            "PLAINTEXT" => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
                        header, now_utc().to_timespec().sec, get_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate curl;
    use self::curl::http;
    use oauth::oauth1::Session;

    // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            "HMAC-SHA1");
        println!("{}", s.get_header());
    }
}
<|endoftext|>


<commit_before>//! Server side

use std::{
    io::{self, ErrorKind},
    time::Duration,
};

use futures::future::{select_all, FutureExt};
use log::{debug, error, trace, warn};
use tokio::{runtime::Handle, time};

use crate::{
    config::Config,
    context::{Context, ServerState, SharedServerState},
    plugin::{PluginMode, Plugins},
    relay::{
        flow::{MultiServerFlowStatistic, SharedMultiServerFlowStatistic},
        manager::ManagerDatagram,
        tcprelay::server::run as run_tcp,
        udprelay::server::run as run_udp,
        utils::set_nofile,
    },
};

/// Runs Relay server on server side.
#[inline]
pub async fn run(config: Config, rt: Handle) -> io::Result<()> {
    // Create a context containing a DNS resolver and server running state flag.
    let server_state = ServerState::new_shared(&config, rt).await?;

    // Create statistics for multiple servers
    //
    // This is for statistic purpose for [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) APIs
    let flow_stat = MultiServerFlowStatistic::new_shared(&config);

    run_with(config, flow_stat, server_state).await
}

pub(crate) async fn run_with(
    mut config: Config,
    flow_stat: SharedMultiServerFlowStatistic,
    server_stat: SharedServerState,
) -> io::Result<()> {
    trace!("RUN Server {:?}", config);
    assert!(config.config_type.is_server());

    if let Some(nofile) = config.nofile {
        debug!("Setting RLIMIT_NOFILE to {}", nofile);
        if let Err(err) = set_nofile(nofile) {
            match err.kind() {
                ErrorKind::PermissionDenied => {
                    warn!("Insufficient permission to change `nofile`, try to restart as root user");
                }
                ErrorKind::InvalidInput => {
                    warn!("Invalid `nofile` value {}, decrease it and try again", nofile);
                }
                _ => {
                    error!("Failed to set RLIMIT_NOFILE with value {}, error: {}", nofile, err);
                }
            }
            return Err(err);
        }
    }

    let mode = config.mode;

    let mut vf = Vec::new();

    let context = if mode.enable_tcp() {
        if config.has_server_plugins() {
            let plugins = Plugins::launch_plugins(&mut config, PluginMode::Client)?;
            vf.push(plugins.into_future().boxed());
        }

        let context = Context::new_shared(config, server_stat);

        let tcp_fut = run_tcp(context.clone(), flow_stat.clone());
        vf.push(tcp_fut.boxed());

        context
    } else {
        Context::new_shared(config, server_stat)
    };

    if mode.enable_udp() {
        // Run UDP relay before starting plugins
        // Because plugins doesn't support UDP relay
        let udp_fut = run_udp(context.clone(), flow_stat.clone());
        vf.push(udp_fut.boxed());
    }

    // If specified manager-address, reports transmission statistic to it
    if context.config().manager_address.is_some() {
        let context = context.clone();

        let report_fut = async move {
            let manager_addr = context.config().manager_address.as_ref().unwrap();
            let mut socket = ManagerDatagram::bind_for(manager_addr).await?;

            while context.server_running() {
                // For each servers, send "stat" command to manager
                for svr_cfg in &context.config().server {
                    let port = svr_cfg.addr().port();
                    if let Some(ref fstat) = flow_stat.get(port) {
                        let trans = fstat.tcp().tx() + fstat.tcp().rx() + fstat.udp().tx() + fstat.udp().rx();
                        let stat = format!("stat: {{\"{}\":{}}}", port, trans);
                        match socket.send_to_manager(stat.as_bytes(), &*context, &manager_addr).await {
                            Ok(..) => {
                                trace!(
                                    "Sent {} for server \"{}\" to manger \"{}\"",
                                    stat,
                                    svr_cfg.addr(),
                                    manager_addr
                                );
                            }
                            Err(err) => {
                                error!(
                                    "Failed to send {} for server \"{}\" to manager \"{}\", error: {}",
                                    stat,
                                    svr_cfg.addr(),
                                    manager_addr,
                                    err
                                );
                            }
                        }
                    }

                    // Report every 10 seconds
                    time::delay_for(Duration::from_secs(10)).await;
                }
            }

            Ok(())
        };
        vf.push(report_fut.boxed());
    }

    let (res, ..) = select_all(vf.into_iter()).await;
    error!("one of servers exited unexpectly, result: {:?}", res);

    // Tells all detached tasks to exit
    context.set_server_stopped();

    Err(io::Error::new(io::ErrorKind::Other, "server exited unexpectly"))
}
<commit_msg>Fixed bug, manager report task sleep 10s<commit_after>//! Server side

use std::{
    io::{self, ErrorKind},
    time::Duration,
};

use futures::future::{select_all, FutureExt};
use log::{debug, error, trace, warn};
use tokio::{runtime::Handle, time};

use crate::{
    config::Config,
    context::{Context, ServerState, SharedServerState},
    plugin::{PluginMode, Plugins},
    relay::{
        flow::{MultiServerFlowStatistic, SharedMultiServerFlowStatistic},
        manager::ManagerDatagram,
        tcprelay::server::run as run_tcp,
        udprelay::server::run as run_udp,
        utils::set_nofile,
    },
};

/// Runs Relay server on server side.
#[inline]
pub async fn run(config: Config, rt: Handle) -> io::Result<()> {
    // Create a context containing a DNS resolver and server running state flag.
    let server_state = ServerState::new_shared(&config, rt).await?;

    // Create statistics for multiple servers
    //
    // This is for statistic purpose for [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) APIs
    let flow_stat = MultiServerFlowStatistic::new_shared(&config);

    run_with(config, flow_stat, server_state).await
}

pub(crate) async fn run_with(
    mut config: Config,
    flow_stat: SharedMultiServerFlowStatistic,
    server_stat: SharedServerState,
) -> io::Result<()> {
    trace!("RUN Server {:?}", config);
    assert!(config.config_type.is_server());

    if let Some(nofile) = config.nofile {
        debug!("Setting RLIMIT_NOFILE to {}", nofile);
        if let Err(err) = set_nofile(nofile) {
            match err.kind() {
                ErrorKind::PermissionDenied => {
                    warn!("Insufficient permission to change `nofile`, try to restart as root user");
                }
                ErrorKind::InvalidInput => {
                    warn!("Invalid `nofile` value {}, decrease it and try again", nofile);
                }
                _ => {
                    error!("Failed to set RLIMIT_NOFILE with value {}, error: {}", nofile, err);
                }
            }
            return Err(err);
        }
    }

    let mode = config.mode;

    let mut vf = Vec::new();

    let context = if mode.enable_tcp() {
        if config.has_server_plugins() {
            let plugins = Plugins::launch_plugins(&mut config, PluginMode::Client)?;
            vf.push(plugins.into_future().boxed());
        }

        let context = Context::new_shared(config, server_stat);

        let tcp_fut = run_tcp(context.clone(), flow_stat.clone());
        vf.push(tcp_fut.boxed());

        context
    } else {
        Context::new_shared(config, server_stat)
    };

    if mode.enable_udp() {
        // Run UDP relay before starting plugins
        // Because plugins doesn't support UDP relay
        let udp_fut = run_udp(context.clone(), flow_stat.clone());
        vf.push(udp_fut.boxed());
    }

    // If specified manager-address, reports transmission statistic to it
    if context.config().manager_address.is_some() {
        let context = context.clone();

        let report_fut = async move {
            let manager_addr = context.config().manager_address.as_ref().unwrap();
            let mut socket = ManagerDatagram::bind_for(manager_addr).await?;

            while context.server_running() {
                // For each servers, send "stat" command to manager
                for svr_cfg in &context.config().server {
                    let port = svr_cfg.addr().port();
                    if let Some(ref fstat) = flow_stat.get(port) {
                        let trans = fstat.tcp().tx() + fstat.tcp().rx() + fstat.udp().tx() + fstat.udp().rx();
                        let stat = format!("stat: {{\"{}\":{}}}", port, trans);
                        match socket.send_to_manager(stat.as_bytes(), &*context, &manager_addr).await {
                            Ok(..) => {
                                trace!(
                                    "Sent {} for server \"{}\" to manger \"{}\"",
                                    stat,
                                    svr_cfg.addr(),
                                    manager_addr
                                );
                            }
                            Err(err) => {
                                error!(
                                    "Failed to send {} for server \"{}\" to manager \"{}\", error: {}",
                                    stat,
                                    svr_cfg.addr(),
                                    manager_addr,
                                    err
                                );
                            }
                        }
                    }
                }

                // Report every 10 seconds
                time::delay_for(Duration::from_secs(10)).await;
            }

            Ok(())
        };
        vf.push(report_fut.boxed());
    }

    let (res, ..) = select_all(vf.into_iter()).await;
    error!("one of servers exited unexpectly, result: {:?}", res);

    // Tells all detached tasks to exit
    context.set_server_stopped();

    Err(io::Error::new(io::ErrorKind::Other, "server exited unexpectly"))
}
<|endoftext|>


<commit_before>use borrow;
use denormalize;
use normalize;
use valid;

pub fn sub(num_l: &str, num_r: &str) -> Result<String, String> {
    if !valid(num_l) {
        Err(format!("Invalid numeral {}", num_l))
    } else if !valid(num_r) {
        Err(format!("Invalid numeral {}", num_r))
    } else {
        let lhs = denormalize(num_l);
        let rhs = denormalize(num_r);

        match rhs.chars().fold(Ok(lhs), |from, digit| {
            match from {
                Ok(remaining) => sub_one_char(remaining, digit),
                Err(e) => Err(e)
            }
        }) {
            Ok(denorm) => Ok(normalize(&denorm).unwrap()),
            Err(e) => Err(e)
        }
    }
}

fn sub_one_char(numeral: String, digit: char) -> Result<String, String> {
    let parts: Vec<&str> = numeral.splitn(2, digit).collect();
    if parts.len() == 2 {
        Ok(parts.join(""))
    } else {
        match borrow(numeral.as_ref(), digit) {
            Ok(expanded) => {
                let expanded_parts: Vec<&str> = expanded.splitn(2, digit).collect();
                Ok(expanded_parts.join(""))
            },
            Err(_) => {
                Err("Could not borrow a letter".into())
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::sub;

    #[test]
    fn sub_ii_i() {
        assert_eq!("I", sub("II", "I").unwrap());
    }

    #[test]
    fn sub_iii_i() {
        assert_eq!("II", sub("III", "I").unwrap());
    }

    #[test]
    fn sub_v_ii_borrows_i_from_v() {
        assert_eq!("III", sub("V", "II").unwrap());
    }

    #[test]
    fn sub_v_i_normalizes_result() {
        assert_eq!("IV", sub("V", "I").unwrap());
    }

    #[test]
    fn sub_iv_i_denormalizes_rhs_before_subtracting() {
        assert_eq!("III", sub("IV", "I").unwrap());
    }

    #[test]
    fn sub_v_iv_denormalizes_rhs_before_subtracting() {
        assert_eq!("I", sub("V", "IV").unwrap());
    }

    #[test]
    fn sub_x_v_borrows_v_from_x() {
        assert_eq!("V", sub("X", "V").unwrap());
    }

    #[test]
    fn sub_x_v_borrows_v_from_x_at_end_of_number() {
        assert_eq!("CV", sub("CX", "V").unwrap());
    }

    #[test]
    fn sub_x_i_borrows_i_from_x_transitively() {
        assert_eq!("IX", sub("X", "I").unwrap());
    }

    #[test]
    fn sub_i_ii_returns_an_error() {
        assert!(sub("I", "II").is_err());
    }

    #[test]
    fn sub_m_i_fully_borrow_from_m() {
        assert_eq!("CMXCIX", sub("M", "I").unwrap());
    }

    #[test]
    fn sub_fails_when_lhs_is_invalid() {
        assert!(sub("IJ", "I").is_err());
    }

    #[test]
    fn sub_fails_when_rhs_is_invalid() {
        assert!(sub("MM", "IM").is_err());
    }
}
<commit_msg>Further refactoring to simplify sub() in Rust<commit_after>use borrow;
use denormalize;
use normalize;
use valid;

pub fn sub(num_l: &str, num_r: &str) -> Result<String, String> {
    if !valid(num_l) {
        Err(format!("Invalid numeral {}", num_l))
    } else if !valid(num_r) {
        Err(format!("Invalid numeral {}", num_r))
    } else {
        let lhs = denormalize(num_l);
        let rhs = denormalize(num_r);

        rhs.chars().fold(Ok(lhs), |partial_diff, digit| {
            partial_diff.and_then(|remaining| sub_one_char(remaining, digit))
        }).and_then(
            |denorm| Ok(normalize(&denorm).unwrap())
        )
    }
}

fn sub_one_char(numeral: String, digit: char) -> Result<String, String> {
    let parts: Vec<&str> = numeral.splitn(2, digit).collect();
    if parts.len() == 2 {
        Ok(parts.join(""))
    } else {
        borrow(numeral.as_ref(), digit).and_then(|expanded| {
            let expanded_parts: Vec<&str> = expanded.splitn(2, digit).collect();
            Ok(expanded_parts.join(""))
        })
    }
}

#[cfg(test)]
mod tests {
    use super::sub;

    #[test]
    fn sub_ii_i() {
        assert_eq!("I", sub("II", "I").unwrap());
    }

    #[test]
    fn sub_iii_i() {
        assert_eq!("II", sub("III", "I").unwrap());
    }

    #[test]
    fn sub_v_ii_borrows_i_from_v() {
        assert_eq!("III", sub("V", "II").unwrap());
    }

    #[test]
    fn sub_v_i_normalizes_result() {
        assert_eq!("IV", sub("V", "I").unwrap());
    }

    #[test]
    fn sub_iv_i_denormalizes_rhs_before_subtracting() {
        assert_eq!("III", sub("IV", "I").unwrap());
    }

    #[test]
    fn sub_v_iv_denormalizes_rhs_before_subtracting() {
        assert_eq!("I", sub("V", "IV").unwrap());
    }

    #[test]
    fn sub_x_v_borrows_v_from_x() {
        assert_eq!("V", sub("X", "V").unwrap());
    }

    #[test]
    fn sub_x_v_borrows_v_from_x_at_end_of_number() {
        assert_eq!("CV", sub("CX", "V").unwrap());
    }

    #[test]
    fn sub_x_i_borrows_i_from_x_transitively() {
        assert_eq!("IX", sub("X", "I").unwrap());
    }

    #[test]
    fn sub_i_ii_returns_an_error() {
        assert!(sub("I", "II").is_err());
    }

    #[test]
    fn sub_m_i_fully_borrow_from_m() {
        assert_eq!("CMXCIX", sub("M", "I").unwrap());
    }

    #[test]
    fn sub_fails_when_lhs_is_invalid() {
        assert!(sub("IJ", "I").is_err());
    }

    #[test]
    fn sub_fails_when_rhs_is_invalid() {
        assert!(sub("MM", "IM").is_err());
    }
}
<|endoftext|>


<commit_before>// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }
}
<commit_msg>note to self<commit_after>// TODO: This will panic on certain opcodes. The ideas I have for cpu_lang
// will probably fix it; we'll see. For now tho, I'm gonna leave it as-is;
// I can imagine fixing it trivially might lead to performance problems.
// I'll deal with it after the port is finished.

// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }

    fn run(&mut self, target_cycles: i32) -> i32 {
        0 // TODO
    }
}
<|endoftext|>


<commit_before>use consumer::*;

/// Represents a subscription to a `Stream`
pub struct Subscription {
    closed: bool,
}

impl Subscription {
    /// Closes the `Subscription`
    pub fn close(mut self) {
        self.closed = true;
    }

    pub fn new() -> Self {
        Subscription { closed: false }
    }
}

impl<T> Consumer<T> for Subscription {
    fn emit(&mut self, _: T) -> bool {
        !self.closed
    }
}<commit_msg>Add Subscription funct operator and remove close since it was not possible to be used correctly anyway<commit_after>use consumer::*;

/// Represents a subscription to a `Stream`
pub struct Subscription;

/// Represents a subscription to a `Stream` based on an action
pub struct SubscriptionAction<F> {
    f: F,
}

/// Represents a subscription to a `Stream` based on a func
pub struct SubscriptionFunc<F> {
    predicate: F,
}

impl<F> SubscriptionAction<F> {
    /// Creates a new `SubscriptionAction`
    pub fn new(f: F) -> Self {
        SubscriptionAction { f: f }
    }
}

impl<F> SubscriptionFunc<F> {
    /// Creates a new `SubscriptionFunc`
    pub fn new(f: F) -> Self {
        SubscriptionFunc { predicate: f }
    }
}

impl<T> Consumer<T> for Subscription {
    fn emit(&mut self, _: T) -> bool {
        true
    }
}

impl<F, T> Consumer<T> for SubscriptionAction<F>
    where F: FnMut(T)
{
    fn emit(&mut self, item: T) -> bool {
        (self.f)(item);
        true
    }
}

impl<F, T> Consumer<T> for SubscriptionFunc<F>
    where F: FnMut(T) -> bool
{
    fn emit(&mut self, item: T) -> bool {
        (self.predicate)(item)
    }
}<|endoftext|>


<commit_before>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use super::{Term, cursor};

pub fn handle(term: &mut Term, ch: char) {
    match ch {
        'i' => {
            term.editor.switch_mode();
        }
        'h' => {
            term.move_cursor(cursor::Direction::Left);
        }
        'j' => {
            term.move_cursor(cursor::Direction::Down);
        }
        'k' => {
            term.move_cursor(cursor::Direction::Up);
        }
        'l' => {
            term.move_cursor(cursor::Direction::Right);
        }
        'q' => {
            term.quit();
        }
        _ => { }
    }
}
<commit_msg>Added replace command<commit_after>/* Copyright (C)  2016 nokaa <nokaa@cock.li>
 * This software is licensed under the terms of the
 * GNU Affero General Public License. You should have
 * received a copy of this license with this software.
 * The license may also be found at https://gnu.org/licenses/agpl.txt
 */

use super::{Term, cursor};
use rustty::{Event};

pub fn handle(term: &mut Term, ch: char) {
    match ch {
        'i' => {
            term.editor.switch_mode();
        }
        'h' => {
            term.move_cursor(cursor::Direction::Left);
        }
        'j' => {
            term.move_cursor(cursor::Direction::Down);
        }
        'k' => {
            term.move_cursor(cursor::Direction::Up);
        }
        'l' => {
            term.move_cursor(cursor::Direction::Right);
        }
        'r' => {
            let evt = term.term.get_event(-1).unwrap();
            if let Some(Event::Key(ch)) = evt {
                match ch {
                    '\x1b' | '\x7f' => { }
                    // TODO(nokaa): ENTER and TAB are ignored for now.
                    '\r' | '\t' => { }
                    c @ _ => {
                        term.term[term.cursor.current_pos()].set_ch(c);
                    }
                }
            }
        }
        'w' => {
        }
        'q' => {
            term.quit();
        }
        _ => { }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::util::*;

pub const MAX_TILE_WIDTH: usize = 4096;
pub const MAX_TILE_AREA: usize = 4096 * 2304;
pub const MAX_TILE_COLS: usize = 64;
pub const MAX_TILE_ROWS: usize = 64;

/// Tiling information
///
/// This stores everything necessary to split a frame into tiles, and write
/// headers fields into the bitstream.
///
/// The method tile_iter_mut() actually provides tiled views of FrameState
/// and FrameBlocks.
#[derive(Debug, Clone, Copy)]
pub struct TilingInfo {
  pub frame_width: usize,
  pub frame_height: usize,
  pub tile_width_sb: usize,
  pub tile_height_sb: usize,
  pub cols: usize, // number of columns of tiles within the whole frame
  pub rows: usize, // number of rows of tiles within the whole frame
  pub sb_size_log2: usize,
}

impl TilingInfo {
  pub fn new(
    sb_size_log2: usize,
    frame_width: usize,
    frame_height: usize,
    tile_cols_log2: usize,
    tile_rows_log2: usize,
  ) -> Self {
    // <https://aomediacodec.github.io/av1-spec/#tile-info-syntax>

    // Frame::new() aligns to the next multiple of 8
    let frame_width = frame_width.align_power_of_two(3);
    let frame_height = frame_height.align_power_of_two(3);
    let frame_width_sb =
      frame_width.align_power_of_two_and_shift(sb_size_log2);
    let frame_height_sb =
      frame_height.align_power_of_two_and_shift(sb_size_log2);
    let sb_cols = frame_width.align_power_of_two_and_shift(sb_size_log2);
    let sb_rows = frame_height.align_power_of_two_and_shift(sb_size_log2);

    let max_tile_width_sb = MAX_TILE_WIDTH >> sb_size_log2;
    let max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size_log2);
    let min_tile_cols_log2 = Self::tile_log2(max_tile_width_sb, sb_cols);
    let max_tile_cols_log2 = Self::tile_log2(1, sb_cols.min(MAX_TILE_COLS));
    let max_tile_rows_log2 = Self::tile_log2(1, sb_rows.min(MAX_TILE_ROWS));

    let min_tiles_log2 = min_tile_cols_log2
      .max(Self::tile_log2(max_tile_area_sb, sb_cols * sb_rows));

    let tile_cols_log2 =
      tile_cols_log2.max(min_tile_cols_log2).min(max_tile_cols_log2);
    let tile_width_sb = sb_cols.align_power_of_two_and_shift(tile_cols_log2);

    let min_tile_rows_log2 = if min_tiles_log2 > tile_cols_log2 {
      min_tiles_log2 - tile_cols_log2
    } else {
      0
    };
    let tile_rows_log2 =
      tile_rows_log2.max(min_tile_rows_log2).min(max_tile_rows_log2);
    let tile_height_sb = sb_rows.align_power_of_two_and_shift(tile_rows_log2);

    let cols = (frame_width_sb + tile_width_sb - 1) / tile_width_sb;
    let rows = (frame_height_sb + tile_height_sb - 1) / tile_height_sb;

    Self {
      frame_width,
      frame_height,
      tile_width_sb,
      tile_height_sb,
      cols,
      rows,
      sb_size_log2,
    }
  }

  /// Return the smallest value for `k` such that `blkSize << k` is greater than
  /// or equal to `target`.
  ///
  /// <https://aomediacodec.github.io/av1-spec/#tile-size-calculation-function>
  fn tile_log2(blk_size: usize, target: usize) -> usize {
    let mut k = 0;
    while (blk_size << k) < target {
      k += 1;
    }
    k
  }

  #[inline(always)]
  pub fn tile_count(&self) -> usize {
    self.cols * self.rows
  }
}
<commit_msg>Expose tile-iterator<commit_after>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use super::*;

use crate::context::*;
use crate::encoder::*;
use crate::util::*;

use std::marker::PhantomData;

pub const MAX_TILE_WIDTH: usize = 4096;
pub const MAX_TILE_AREA: usize = 4096 * 2304;
pub const MAX_TILE_COLS: usize = 64;
pub const MAX_TILE_ROWS: usize = 64;

/// Tiling information
///
/// This stores everything necessary to split a frame into tiles, and write
/// headers fields into the bitstream.
///
/// The method tile_iter_mut() actually provides tiled views of FrameState
/// and FrameBlocks.
#[derive(Debug, Clone, Copy)]
pub struct TilingInfo {
  pub frame_width: usize,
  pub frame_height: usize,
  pub tile_width_sb: usize,
  pub tile_height_sb: usize,
  pub cols: usize, // number of columns of tiles within the whole frame
  pub rows: usize, // number of rows of tiles within the whole frame
  pub sb_size_log2: usize,
}

impl TilingInfo {
  pub fn new(
    sb_size_log2: usize,
    frame_width: usize,
    frame_height: usize,
    tile_cols_log2: usize,
    tile_rows_log2: usize,
  ) -> Self {
    // <https://aomediacodec.github.io/av1-spec/#tile-info-syntax>

    // Frame::new() aligns to the next multiple of 8
    let frame_width = frame_width.align_power_of_two(3);
    let frame_height = frame_height.align_power_of_two(3);
    let frame_width_sb =
      frame_width.align_power_of_two_and_shift(sb_size_log2);
    let frame_height_sb =
      frame_height.align_power_of_two_and_shift(sb_size_log2);
    let sb_cols = frame_width.align_power_of_two_and_shift(sb_size_log2);
    let sb_rows = frame_height.align_power_of_two_and_shift(sb_size_log2);

    let max_tile_width_sb = MAX_TILE_WIDTH >> sb_size_log2;
    let max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size_log2);
    let min_tile_cols_log2 = Self::tile_log2(max_tile_width_sb, sb_cols);
    let max_tile_cols_log2 = Self::tile_log2(1, sb_cols.min(MAX_TILE_COLS));
    let max_tile_rows_log2 = Self::tile_log2(1, sb_rows.min(MAX_TILE_ROWS));

    let min_tiles_log2 = min_tile_cols_log2
      .max(Self::tile_log2(max_tile_area_sb, sb_cols * sb_rows));

    let tile_cols_log2 =
      tile_cols_log2.max(min_tile_cols_log2).min(max_tile_cols_log2);
    let tile_width_sb = sb_cols.align_power_of_two_and_shift(tile_cols_log2);

    let min_tile_rows_log2 = if min_tiles_log2 > tile_cols_log2 {
      min_tiles_log2 - tile_cols_log2
    } else {
      0
    };
    let tile_rows_log2 =
      tile_rows_log2.max(min_tile_rows_log2).min(max_tile_rows_log2);
    let tile_height_sb = sb_rows.align_power_of_two_and_shift(tile_rows_log2);

    let cols = (frame_width_sb + tile_width_sb - 1) / tile_width_sb;
    let rows = (frame_height_sb + tile_height_sb - 1) / tile_height_sb;

    Self {
      frame_width,
      frame_height,
      tile_width_sb,
      tile_height_sb,
      cols,
      rows,
      sb_size_log2,
    }
  }

  /// Return the smallest value for `k` such that `blkSize << k` is greater than
  /// or equal to `target`.
  ///
  /// <https://aomediacodec.github.io/av1-spec/#tile-size-calculation-function>
  fn tile_log2(blk_size: usize, target: usize) -> usize {
    let mut k = 0;
    while (blk_size << k) < target {
      k += 1;
    }
    k
  }

  #[inline(always)]
  pub fn tile_count(&self) -> usize {
    self.cols * self.rows
  }

  /// Split frame-level structures into tiles
  ///
  /// Provide mutable tiled views of frame-level structures.
  pub fn tile_iter_mut<'a, 'b, T: Pixel>(
    &self,
    fs: &'a mut FrameState<T>,
    fb: &'b mut FrameBlocks,
  ) -> TileContextIterMut<'a, 'b, T> {
    TileContextIterMut { ti: *self, fs, fb, next: 0, phantom: PhantomData }
  }
}

/// Container for all tiled views
pub struct TileContextMut<'a, 'b, T: Pixel> {
  pub ts: TileStateMut<'a, T>,
  pub tb: TileBlocksMut<'b>,
}

/// Iterator over tiled views
pub struct TileContextIterMut<'a, 'b, T: Pixel> {
  ti: TilingInfo,
  fs: *mut FrameState<T>,
  fb: *mut FrameBlocks,
  next: usize,
  phantom: PhantomData<(&'a mut FrameState<T>, &'b mut FrameBlocks)>,
}

impl<'a, 'b, T: Pixel> Iterator for TileContextIterMut<'a, 'b, T> {
  type Item = TileContextMut<'a, 'b, T>;

  fn next(&mut self) -> Option<Self::Item> {
    if self.next < self.ti.rows * self.ti.cols {
      let tile_col = self.next % self.ti.cols;
      let tile_row = self.next / self.ti.cols;
      let ctx = TileContextMut {
        ts: {
          let fs = unsafe { &mut *self.fs };
          let sbo = SuperBlockOffset {
            x: tile_col * self.ti.tile_width_sb,
            y: tile_row * self.ti.tile_height_sb,
          };
          let x = sbo.x << self.ti.sb_size_log2;
          let y = sbo.y << self.ti.sb_size_log2;
          let tile_width = self.ti.tile_width_sb << self.ti.sb_size_log2;
          let tile_height = self.ti.tile_height_sb << self.ti.sb_size_log2;
          let width = tile_width.min(self.ti.frame_width - x);
          let height = tile_height.min(self.ti.frame_height - y);
          TileStateMut::new(fs, sbo, self.ti.sb_size_log2, width, height)
        },
        tb: {
          let fb = unsafe { &mut *self.fb };
          let tile_width_mi =
            self.ti.tile_width_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2);
          let tile_height_mi =
            self.ti.tile_height_sb << (self.ti.sb_size_log2 - MI_SIZE_LOG2);
          let x = tile_col * tile_width_mi;
          let y = tile_row * tile_height_mi;
          let cols = tile_width_mi.min(fb.cols - x);
          let rows = tile_height_mi.min(fb.rows - y);
          TileBlocksMut::new(fb, x, y, cols, rows)
        },
      };
      self.next += 1;
      Some(ctx)
    } else {
      None
    }
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let remaining = self.ti.cols * self.ti.rows - self.next;
    (remaining, Some(remaining))
  }
}

impl<T: Pixel> ExactSizeIterator for TileContextIterMut<'_, '_, T> {}
<|endoftext|>


<commit_before>extern crate chrono;

use std::io::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC};

use Result;
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};

fn base() -> NaiveDateTime {
    NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0)
}

impl FromSql for NaiveDateTime {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDateTime> {
        let t = try!(raw.read_i64::<BigEndian>());
        Ok(base() + Duration::microseconds(t))
    }

    accepts!(Type::Timestamp);
}

impl ToSql for NaiveDateTime {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let t = (*self - base()).num_microseconds().unwrap();
        try!(w.write_i64::<BigEndian>(t));
        Ok(IsNull::No)
    }

    accepts!(Type::Timestamp);
    to_sql_checked!();
}

impl FromSql for DateTime<UTC> {
    fn from_sql<R: Read>(type_: &Type, raw: &mut R, _: &SessionInfo) -> Result<DateTime<UTC>> {
        let naive = try!(NaiveDateTime::from_sql(type_, raw));
        Ok(DateTime::from_utc(naive, UTC))
    }

    accepts!(Type::TimestampTZ);
}

impl ToSql for DateTime<UTC> {
    fn to_sql<W: Write+?Sized>(&self, type_: &Type, mut w: &mut W, _: &SessionInfo)
                               -> Result<IsNull> {
        self.naive_utc().to_sql(type_, w)
    }

    accepts!(Type::TimestampTZ);
    to_sql_checked!();
}

impl FromSql for NaiveDate {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDate> {
        let jd = try!(raw.read_i32::<BigEndian>());
        Ok(base().date() + Duration::days(jd as i64))
    }

    accepts!(Type::Date);
}

impl ToSql for NaiveDate {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let jd = *self - base().date();
        try!(w.write_i32::<BigEndian>(jd.num_days() as i32));
        Ok(IsNull::No)
    }

    accepts!(Type::Date);
    to_sql_checked!();
}

impl FromSql for NaiveTime {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveTime> {
        let usec = try!(raw.read_i64::<BigEndian>());
        Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec))
    }

    accepts!(Type::Time);
}

impl ToSql for NaiveTime {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let delta = *self - NaiveTime::from_hms(0, 0, 0);
        try!(w.write_i64::<BigEndian>(delta.num_microseconds().unwrap()));
        Ok(IsNull::No)
    }

    accepts!(Type::Time);
    to_sql_checked!();
}
<commit_msg>Fix chrono support<commit_after>extern crate chrono;

use std::io::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use self::chrono::{Duration, NaiveDate, NaiveTime, NaiveDateTime, DateTime, UTC};

use Result;
use types::{FromSql, ToSql, IsNull, Type, SessionInfo};

fn base() -> NaiveDateTime {
    NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0)
}

impl FromSql for NaiveDateTime {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDateTime> {
        let t = try!(raw.read_i64::<BigEndian>());
        Ok(base() + Duration::microseconds(t))
    }

    accepts!(Type::Timestamp);
}

impl ToSql for NaiveDateTime {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let t = (*self - base()).num_microseconds().unwrap();
        try!(w.write_i64::<BigEndian>(t));
        Ok(IsNull::No)
    }

    accepts!(Type::Timestamp);
    to_sql_checked!();
}

impl FromSql for DateTime<UTC> {
    fn from_sql<R: Read>(type_: &Type, raw: &mut R, info: &SessionInfo) -> Result<DateTime<UTC>> {
        let naive = try!(NaiveDateTime::from_sql(type_, raw, info));
        Ok(DateTime::from_utc(naive, UTC))
    }

    accepts!(Type::TimestampTZ);
}

impl ToSql for DateTime<UTC> {
    fn to_sql<W: Write+?Sized>(&self, type_: &Type, mut w: &mut W, info: &SessionInfo)
                               -> Result<IsNull> {
        self.naive_utc().to_sql(type_, w, info)
    }

    accepts!(Type::TimestampTZ);
    to_sql_checked!();
}

impl FromSql for NaiveDate {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveDate> {
        let jd = try!(raw.read_i32::<BigEndian>());
        Ok(base().date() + Duration::days(jd as i64))
    }

    accepts!(Type::Date);
}

impl ToSql for NaiveDate {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let jd = *self - base().date();
        try!(w.write_i32::<BigEndian>(jd.num_days() as i32));
        Ok(IsNull::No)
    }

    accepts!(Type::Date);
    to_sql_checked!();
}

impl FromSql for NaiveTime {
    fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<NaiveTime> {
        let usec = try!(raw.read_i64::<BigEndian>());
        Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec))
    }

    accepts!(Type::Time);
}

impl ToSql for NaiveTime {
    fn to_sql<W: Write+?Sized>(&self, _: &Type, mut w: &mut W, _: &SessionInfo) -> Result<IsNull> {
        let delta = *self - NaiveTime::from_hms(0, 0, 0);
        try!(w.write_i64::<BigEndian>(delta.num_microseconds().unwrap()));
        Ok(IsNull::No)
    }

    accepts!(Type::Time);
    to_sql_checked!();
}
<|endoftext|>


<commit_before>use cairo;

use librsvg::{rsvg_convert_only::LegacySize, CairoRenderer};

use crate::utils::load_svg;

#[test]
fn just_viewbox_uses_viewbox_size() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 200"/>
"#,
    )
        .unwrap();

    assert_eq!(
        CairoRenderer::new(&svg).legacy_layer_geometry(None).unwrap(),
        (cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 100.0,
            height: 200.0,
        },
         cairo::Rectangle {
             x: 0.0,
             y: 0.0,
             width: 100.0,
             height: 200.0,
         })
    );
}

#[test]
fn no_intrinsic_size_uses_element_geometries() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="20" width="30" height="40" fill="black"/>
</svg>
"#,
    )
        .unwrap();

    assert_eq!(
        CairoRenderer::new(&svg).legacy_layer_geometry(None).unwrap(),
        (cairo::Rectangle {
            x: 10.0,
            y: 20.0,
            width: 30.0,
            height: 40.0,
        },
         cairo::Rectangle {
             x: 10.0,
             y: 20.0,
             width: 30.0,
             height: 40.0,
         })
    );
}
<commit_msg>Test for 100% width and height<commit_after>use cairo;

use librsvg::{rsvg_convert_only::LegacySize, CairoRenderer};

use crate::utils::load_svg;

#[test]
fn just_viewbox_uses_viewbox_size() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 200"/>
"#,
    )
        .unwrap();

    assert_eq!(
        CairoRenderer::new(&svg).legacy_layer_geometry(None).unwrap(),
        (cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 100.0,
            height: 200.0,
        },
         cairo::Rectangle {
             x: 0.0,
             y: 0.0,
             width: 100.0,
             height: 200.0,
         })
    );
}

#[test]
fn no_intrinsic_size_uses_element_geometries() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="10" y="20" width="30" height="40" fill="black"/>
</svg>
"#,
    )
        .unwrap();

    assert_eq!(
        CairoRenderer::new(&svg).legacy_layer_geometry(None).unwrap(),
        (cairo::Rectangle {
            x: 10.0,
            y: 20.0,
            width: 30.0,
            height: 40.0,
        },
         cairo::Rectangle {
             x: 10.0,
             y: 20.0,
             width: 30.0,
             height: 40.0,
         })
    );
}

#[test]
fn hundred_percent_width_height_uses_viewbox() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 200"/>
"#,
    )
        .unwrap();

    assert_eq!(
        CairoRenderer::new(&svg).legacy_layer_geometry(None).unwrap(),
        (cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 100.0,
            height: 200.0,
        },
         cairo::Rectangle {
             x: 0.0,
             y: 0.0,
             width: 100.0,
             height: 200.0,
         })
    );
}
<|endoftext|>