<commit_before>use encoding::label::encoding_from_whatwg_label;
use encoding::DecoderTrap;
use libc;
use std;
use std::mem;
use std::ptr;
use std::rc::Rc;
use std::str;

use attributes::Attribute;
use css;
use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use style::NodeStyle;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

enum ContextKind {
    // Starting state
    Start,

    // Creating nodes for elements under the current node
    ElementCreation,

    // Inside <xi:include>
    XInclude(XIncludeContext),

    // An unsupported element inside a <xi:include> context, to be ignored
    UnsupportedXIncludeChild,

    // Insie <xi::fallback>
    XIncludeFallback(XIncludeContext),
}

#[derive(Clone)]
struct XIncludeContext {
    need_fallback: bool,
}

/// A concrete parsing context for a surrounding `element_name` and its XML event handlers
struct Context {
    element_name: String,
    kind: ContextKind,
}

impl Context {
    fn empty() -> Context {
        Context {
            element_name: String::new(),
            kind: ContextKind::Start,
        }
    }
}

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

/// Holds the state used for XML processing
///
/// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
/// `end_element`, `characters`.
///
/// When an element starts, we push a corresponding `Context` into the `context_stack`.  Within
/// that context, all XML events will be forwarded to it, and processed in one of the `XmlHandler`
/// trait objects. Normally the context refers to a `NodeCreationContext` implementation which is
/// what creates normal graphical elements.
struct XmlState {
    tree: Option<Box<Tree>>,
    context: Context,
    context_stack: Vec<Context>,
    current_node: Option<Rc<Node>>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            context: Context::empty(),
            context_stack: Vec::new(),
            current_node: None,
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    fn push_context(&mut self, ctx: Context) {
        let top = mem::replace(&mut self.context, ctx);
        self.context_stack.push(top);
    }

    pub fn start_element(&mut self, handle: *mut RsvgHandle, name: &str, pbag: &PropertyBag) {
        let ctx = mem::replace(&mut self.context, Context::empty());

        let new_ctx = match ctx.kind {
            ContextKind::Start => self.element_creation_start_element(handle, name, pbag),
            ContextKind::ElementCreation => self.element_creation_start_element(handle, name, pbag),
            ContextKind::XInclude(ref ctx) => self.inside_xinclude_start_element(ctx, name),
            ContextKind::UnsupportedXIncludeChild => self.unsupported_xinclude_start_element(name),
            ContextKind::XIncludeFallback(ref ctx) => {
                self.xinclude_fallback_start_element(&ctx.clone(), handle, name, pbag)
            }
        };

        mem::replace(&mut self.context, ctx);
        self.push_context(new_ctx);
    }

    pub fn end_element(&mut self, handle: *mut RsvgHandle, name: &str) {
        // We can unwrap since start_element() always adds a context to the stack
        let top = self.context_stack.pop().unwrap();

        let context = mem::replace(&mut self.context, top);

        assert!(context.element_name == name);

        match context.kind {
            ContextKind::Start => panic!("end_element: XML handler stack is empty!?"),
            ContextKind::ElementCreation => self.element_creation_end_element(handle),
            ContextKind::XInclude(_) => (),
            ContextKind::UnsupportedXIncludeChild => (),
            ContextKind::XIncludeFallback(_) => (),
        }
    }

    pub fn characters(&mut self, text: &str) {
        let ctx = mem::replace(&mut self.context, Context::empty());

        match ctx.kind {
            ContextKind::Start => (), // character data outside the toplevel element?  Ignore it.
            ContextKind::ElementCreation => self.element_creation_characters(text),
            ContextKind::XInclude(_) => (),
            ContextKind::UnsupportedXIncludeChild => (),
            ContextKind::XIncludeFallback(ref ctx) => {
                self.xinclude_fallback_characters(&ctx.clone(), text)
            }
        }

        mem::replace(&mut self.context, ctx);
    }

    fn element_creation_start_element(
        &mut self,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        match name {
            "include" => self.xinclude_start_element(handle, name, pbag),
            _ => {
                let node = self.create_node(self.current_node.as_ref(), handle, name, pbag);
                if self.current_node.is_none() {
                    self.set_root(&node);
                }
                self.current_node = Some(node);

                Context {
                    element_name: name.to_string(),
                    kind: ContextKind::ElementCreation,
                }
            }
        }
    }

    fn element_creation_end_element(&mut self, handle: *mut RsvgHandle) {
        let node = self.current_node.take().unwrap();

        // The "svg" node is special; it parses its style attributes
        // here, not during element creation.
        if node.get_type() == NodeType::Svg {
            node.with_impl(|svg: &NodeSvg| {
                svg.set_delayed_style(&node, handle);
            });
        }

        if node.get_type() == NodeType::Style {
            let css_data = node.with_impl(|style: &NodeStyle| style.get_css(&node));

            css::parse_into_handle(handle, &css_data);
        }

        self.current_node = node.get_parent();
    }

    fn element_creation_characters(&self, text: &str) {
        let node = self.current_node.as_ref().unwrap();

        if text.len() != 0 && node.accept_chars() {
            let chars_node = if let Some(child) = node.find_last_chars_child() {
                child
            } else {
                let child = node_new(
                    NodeType::Chars,
                    Some(node),
                    "rsvg-chars",
                    None,
                    None,
                    Box::new(NodeChars::new()),
                );
                node.add_child(&child);
                child
            };

            chars_node.with_impl(|chars: &NodeChars| {
                chars.append(text);
            });
        }
    }

    fn create_node(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Rc<Node> {
        let mut defs = handle::get_defs(handle);

        let new_node = rsvg_load_new_node(name, parent, pbag, &mut defs);

        if let Some(parent) = parent {
            parent.add_child(&new_node);
        }

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.set_style(handle, pbag);
        }

        new_node.set_overridden_properties();

        new_node
    }

    fn xinclude_start_element(
        &mut self,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        let mut href = None;
        let mut parse = None;
        let mut encoding = None;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::Href => href = Some(value),
                Attribute::Parse => parse = Some(value),
                Attribute::Encoding => encoding = Some(value),
                _ => (),
            }
        }

        let need_fallback = !self.acquire(handle, href, parse, encoding).is_ok();

        Context {
            element_name: name.to_string(),
            kind: ContextKind::XInclude(XIncludeContext { need_fallback }),
        }
    }

    fn inside_xinclude_start_element(&self, ctx: &XIncludeContext, name: &str) -> Context {
        // FIXME: we aren't using the xi: namespace
        if name == "fallback" {
            Context {
                element_name: name.to_string(),
                kind: ContextKind::XIncludeFallback(ctx.clone()),
            }
        } else {
            self.unsupported_xinclude_start_element(name)
        }
    }

    fn xinclude_fallback_start_element(
        &mut self,
        ctx: &XIncludeContext,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        if ctx.need_fallback {
            // FIXME: we aren't using the xi: namespace
            if name == "include" {
                self.xinclude_start_element(handle, name, pbag)
            } else {
                self.element_creation_start_element(handle, name, pbag)
            }
        } else {
            Context {
                element_name: name.to_string(),
                kind: ContextKind::UnsupportedXIncludeChild,
            }
        }
    }

    fn xinclude_fallback_characters(&mut self, ctx: &XIncludeContext, text: &str) {
        if ctx.need_fallback {
            self.element_creation_characters(text);
        }
    }

    fn acquire(
        &mut self,
        handle: *mut RsvgHandle,
        href: Option<&str>,
        parse: Option<&str>,
        encoding: Option<&str>,
    ) -> Result<(), ()> {
        if let Some(href) = href {
            if parse == Some("text") {
                self.acquire_text(handle, href, encoding)
            } else {
                self.acquire_xml(handle, href)
            }
        } else {
            Err(())
        }
    }

    fn acquire_text(
        &mut self,
        handle: *mut RsvgHandle,
        href: &str,
        encoding: Option<&str>,
    ) -> Result<(), ()> {
        let binary = handle::acquire_data(handle, href).map_err(|e| {
            rsvg_log!("could not acquire \"{}\": {}", href, e);
            ()
        })?;

        let encoding = encoding.unwrap_or("utf-8");

        let encoder = encoding_from_whatwg_label(encoding).ok_or_else(|| {
            rsvg_log!("unknown encoding \"{}\" for \"{}\"", encoding, href);
            ()
        })?;

        let utf8_data = encoder
            .decode(&binary.data, DecoderTrap::Strict)
            .map_err(|e| {
                rsvg_log!(
                    "could not convert contents of \"{}\" from character encoding \"{}\": {}",
                    href,
                    encoding,
                    e
                );
                ()
            })?;

        self.element_creation_characters(&utf8_data);
        Ok(())
    }

    fn acquire_xml(&self, handle: *mut RsvgHandle, href: &str) -> Result<(), ()> {
        if handle::load_xml_xinclude(handle, href) {
            Ok(())
        } else {
            Err(())
        }
    }

    fn unsupported_xinclude_start_element(&self, name: &str) -> Context {
        Context {
            element_name: name.to_string(),
            kind: ContextKind::UnsupportedXIncludeChild,
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_start_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.start_element(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_end_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.end_element(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.characters(utf8);
}
<commit_msg>xml.rs: Preserve the context without mem::replace()<commit_after>use encoding::label::encoding_from_whatwg_label;
use encoding::DecoderTrap;
use libc;
use std;
use std::mem;
use std::ptr;
use std::rc::Rc;
use std::str;

use attributes::Attribute;
use css;
use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use style::NodeStyle;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

#[derive(Clone)]
enum ContextKind {
    // Starting state
    Start,

    // Creating nodes for elements under the current node
    ElementCreation,

    // Inside <xi:include>
    XInclude(XIncludeContext),

    // An unsupported element inside a <xi:include> context, to be ignored
    UnsupportedXIncludeChild,

    // Insie <xi::fallback>
    XIncludeFallback(XIncludeContext),
}

#[derive(Clone)]
struct XIncludeContext {
    need_fallback: bool,
}

/// A concrete parsing context for a surrounding `element_name` and its XML event handlers
#[derive(Clone)]
struct Context {
    element_name: String,
    kind: ContextKind,
}

impl Context {
    fn empty() -> Context {
        Context {
            element_name: String::new(),
            kind: ContextKind::Start,
        }
    }
}

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

/// Holds the state used for XML processing
///
/// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
/// `end_element`, `characters`.
///
/// When an element starts, we push a corresponding `Context` into the `context_stack`.  Within
/// that context, all XML events will be forwarded to it, and processed in one of the `XmlHandler`
/// trait objects. Normally the context refers to a `NodeCreationContext` implementation which is
/// what creates normal graphical elements.
struct XmlState {
    tree: Option<Box<Tree>>,
    context: Context,
    context_stack: Vec<Context>,
    current_node: Option<Rc<Node>>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            context: Context::empty(),
            context_stack: Vec::new(),
            current_node: None,
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    fn push_context(&mut self, ctx: Context) {
        let top = mem::replace(&mut self.context, ctx);
        self.context_stack.push(top);
    }

    pub fn start_element(&mut self, handle: *mut RsvgHandle, name: &str, pbag: &PropertyBag) {
        let context = self.context.clone();

        let new_context = match context.kind {
            ContextKind::Start => self.element_creation_start_element(handle, name, pbag),
            ContextKind::ElementCreation => self.element_creation_start_element(handle, name, pbag),
            ContextKind::XInclude(ref ctx) => self.inside_xinclude_start_element(&ctx, name),
            ContextKind::UnsupportedXIncludeChild => self.unsupported_xinclude_start_element(name),
            ContextKind::XIncludeFallback(ref ctx) => {
                self.xinclude_fallback_start_element(&ctx, handle, name, pbag)
            }
        };

        self.push_context(new_context);
    }

    pub fn end_element(&mut self, handle: *mut RsvgHandle, name: &str) {
        let context = self.context.clone();

        assert!(context.element_name == name);

        match context.kind {
            ContextKind::Start => panic!("end_element: XML handler stack is empty!?"),
            ContextKind::ElementCreation => self.element_creation_end_element(handle),
            ContextKind::XInclude(_) => (),
            ContextKind::UnsupportedXIncludeChild => (),
            ContextKind::XIncludeFallback(_) => (),
        }

        // We can unwrap since start_element() always adds a context to the stack
        self.context = self.context_stack.pop().unwrap();
    }

    pub fn characters(&mut self, text: &str) {
        let context = self.context.clone();

        match context.kind {
            ContextKind::Start => panic!("characters: XML handler stack is empty!?"),
            ContextKind::ElementCreation => self.element_creation_characters(text),
            ContextKind::XInclude(_) => (),
            ContextKind::UnsupportedXIncludeChild => (),
            ContextKind::XIncludeFallback(ref ctx) => self.xinclude_fallback_characters(&ctx, text),
        }
    }

    fn element_creation_start_element(
        &mut self,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        match name {
            "include" => self.xinclude_start_element(handle, name, pbag),
            _ => {
                let node = self.create_node(self.current_node.as_ref(), handle, name, pbag);
                if self.current_node.is_none() {
                    self.set_root(&node);
                }
                self.current_node = Some(node);

                Context {
                    element_name: name.to_string(),
                    kind: ContextKind::ElementCreation,
                }
            }
        }
    }

    fn element_creation_end_element(&mut self, handle: *mut RsvgHandle) {
        let node = self.current_node.take().unwrap();

        // The "svg" node is special; it parses its style attributes
        // here, not during element creation.
        if node.get_type() == NodeType::Svg {
            node.with_impl(|svg: &NodeSvg| {
                svg.set_delayed_style(&node, handle);
            });
        }

        if node.get_type() == NodeType::Style {
            let css_data = node.with_impl(|style: &NodeStyle| style.get_css(&node));

            css::parse_into_handle(handle, &css_data);
        }

        self.current_node = node.get_parent();
    }

    fn element_creation_characters(&self, text: &str) {
        let node = self.current_node.as_ref().unwrap();

        if text.len() != 0 && node.accept_chars() {
            let chars_node = if let Some(child) = node.find_last_chars_child() {
                child
            } else {
                let child = node_new(
                    NodeType::Chars,
                    Some(node),
                    "rsvg-chars",
                    None,
                    None,
                    Box::new(NodeChars::new()),
                );
                node.add_child(&child);
                child
            };

            chars_node.with_impl(|chars: &NodeChars| {
                chars.append(text);
            });
        }
    }

    fn create_node(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Rc<Node> {
        let mut defs = handle::get_defs(handle);

        let new_node = rsvg_load_new_node(name, parent, pbag, &mut defs);

        if let Some(parent) = parent {
            parent.add_child(&new_node);
        }

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.set_style(handle, pbag);
        }

        new_node.set_overridden_properties();

        new_node
    }

    fn xinclude_start_element(
        &mut self,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        let mut href = None;
        let mut parse = None;
        let mut encoding = None;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::Href => href = Some(value),
                Attribute::Parse => parse = Some(value),
                Attribute::Encoding => encoding = Some(value),
                _ => (),
            }
        }

        let need_fallback = !self.acquire(handle, href, parse, encoding).is_ok();

        Context {
            element_name: name.to_string(),
            kind: ContextKind::XInclude(XIncludeContext { need_fallback }),
        }
    }

    fn inside_xinclude_start_element(&self, ctx: &XIncludeContext, name: &str) -> Context {
        // FIXME: we aren't using the xi: namespace
        if name == "fallback" {
            Context {
                element_name: name.to_string(),
                kind: ContextKind::XIncludeFallback(ctx.clone()),
            }
        } else {
            self.unsupported_xinclude_start_element(name)
        }
    }

    fn xinclude_fallback_start_element(
        &mut self,
        ctx: &XIncludeContext,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Context {
        if ctx.need_fallback {
            // FIXME: we aren't using the xi: namespace
            if name == "include" {
                self.xinclude_start_element(handle, name, pbag)
            } else {
                self.element_creation_start_element(handle, name, pbag)
            }
        } else {
            Context {
                element_name: name.to_string(),
                kind: ContextKind::UnsupportedXIncludeChild,
            }
        }
    }

    fn xinclude_fallback_characters(&mut self, ctx: &XIncludeContext, text: &str) {
        if ctx.need_fallback {
            self.element_creation_characters(text);
        }
    }

    fn acquire(
        &mut self,
        handle: *mut RsvgHandle,
        href: Option<&str>,
        parse: Option<&str>,
        encoding: Option<&str>,
    ) -> Result<(), ()> {
        if let Some(href) = href {
            if parse == Some("text") {
                self.acquire_text(handle, href, encoding)
            } else {
                self.acquire_xml(handle, href)
            }
        } else {
            Err(())
        }
    }

    fn acquire_text(
        &mut self,
        handle: *mut RsvgHandle,
        href: &str,
        encoding: Option<&str>,
    ) -> Result<(), ()> {
        let binary = handle::acquire_data(handle, href).map_err(|e| {
            rsvg_log!("could not acquire \"{}\": {}", href, e);
            ()
        })?;

        let encoding = encoding.unwrap_or("utf-8");

        let encoder = encoding_from_whatwg_label(encoding).ok_or_else(|| {
            rsvg_log!("unknown encoding \"{}\" for \"{}\"", encoding, href);
            ()
        })?;

        let utf8_data = encoder
            .decode(&binary.data, DecoderTrap::Strict)
            .map_err(|e| {
                rsvg_log!(
                    "could not convert contents of \"{}\" from character encoding \"{}\": {}",
                    href,
                    encoding,
                    e
                );
                ()
            })?;

        self.element_creation_characters(&utf8_data);
        Ok(())
    }

    fn acquire_xml(&self, handle: *mut RsvgHandle, href: &str) -> Result<(), ()> {
        if handle::load_xml_xinclude(handle, href) {
            Ok(())
        } else {
            Err(())
        }
    }

    fn unsupported_xinclude_start_element(&self, name: &str) -> Context {
        Context {
            element_name: name.to_string(),
            kind: ContextKind::UnsupportedXIncludeChild,
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_start_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.start_element(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_end_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.end_element(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.characters(utf8);
}
<|endoftext|>


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

//! Module for searching text.

use std::cmp::{min,max};

use xi_rope::delta::{Delta, DeltaRegion};
use xi_rope::find::{find, is_multiline_regex, CaseMatching};
use xi_rope::rope::{Rope, LinesMetric, RopeInfo};
use xi_rope::tree::Cursor;
use xi_rope::interval::Interval;
use selection::{Selection, SelRegion};
use xi_rope::tree::Metric;

/// Information about search queries and number of matches for find
#[derive(Serialize, Deserialize, Debug)]
pub struct FindStatus {
    /// The current search query.
    chars: Option<String>,

    /// Whether the active search is case matching.
    case_sensitive: Option<bool>,

    /// Whether the search query is considered as regular expression.
    is_regex: Option<bool>,

    /// Total number of matches.
    matches: usize
}

/// Contains logic to search text
pub struct Find {
    // todo: link to search query so that search results can be correlated back to query

    /// The occurrences, which determine the highlights, have been updated.
    hls_dirty: bool,
    /// The currently active search string
    search_string: Option<String>,
    /// The case matching setting for the currently active search
    case_matching: CaseMatching,
    /// The search query should be considered as regular expression
    is_regex: bool,
    /// The set of all known find occurrences (highlights)
    occurrences: Selection,
}

impl Find {
    pub fn new() -> Find {
        Find {
            hls_dirty: true,
            search_string: None,
            case_matching: CaseMatching::CaseInsensitive,
            is_regex: false,
            occurrences: Selection::new(),
        }
    }

    pub fn occurrences(&self) -> &Selection {
        &self.occurrences
    }

    pub fn hls_dirty(&self) -> bool {
        self.hls_dirty
    }

    pub fn find_status(&self, matches_only: bool) -> FindStatus {
        if matches_only {
            FindStatus {
                chars: None,
                case_sensitive: None,
                is_regex: None,
                matches: self.occurrences.len(),
            }
        } else {
            FindStatus {
                chars: self.search_string.clone(),
                case_sensitive: Some(self.case_matching == CaseMatching::Exact),
                is_regex: Some(self.is_regex),
                matches: self.occurrences.len(),
            }
        }
    }

    pub fn set_hls_dirty(&mut self, is_dirty: bool) {
        self.hls_dirty = is_dirty
    }

    pub fn update_highlights(&mut self, text: &Rope, delta: &Delta<RopeInfo>) {
        // update search highlights for changed regions
        if self.search_string.is_some() {
            // invalidate occurrences around deletion positions
            for DeltaRegion{ old_offset, new_offset: _, len } in delta.iter_deletions() {
                self.occurrences.delete_range(old_offset, old_offset + len, false);
            }

            self.occurrences = self.occurrences.apply_delta(delta, false, false);

            // invalidate occurrences around insert positions
            for DeltaRegion{ new_offset, len, .. } in delta.iter_inserts() {
                self.occurrences.delete_range(new_offset, new_offset + len, false);
            }

            // update find for the whole delta and everything after
            let (iv, _) = delta.summary();

            // get last valid occurrence that was unaffected by the delta
            let start = match self.occurrences.regions_in_range(0, iv.start()).last() {
                Some(reg) => reg.end,
                None => 0
            };

            // invalidate all search results from the point of the last valid search result until ...
            let is_multi_line = LinesMetric::next(self.search_string.as_ref().unwrap(), 0).is_some();
            let is_multi_line_regex = self.is_regex && is_multiline_regex(self.search_string.as_ref().unwrap());

            eprintln!("multi {:?}", is_multi_line_regex);
            if is_multi_line || is_multi_line_regex {
                // ... the end of the file
                self.occurrences.delete_range(iv.start(), text.len(), false);
                self.update_find(text, start, text.len(), true);
            } else {
                // ... the end of the line
                let mut cursor = Cursor::new(&text, iv.start());
                if let Some(end_of_line) = cursor.next::<LinesMetric>() {
                    self.occurrences.delete_range(iv.start(), end_of_line, false);
                    self.update_find(text, start, end_of_line, true);
                }
            }
        }
    }

    /// Set search parameters and executes the search.
    pub fn do_find(&mut self, text: &Rope, search_string: Option<String>, case_sensitive: bool,
                   is_regex: bool) {
        if search_string.is_none() {
            self.unset();
        }

        let search_string = search_string.unwrap();
        if search_string.len() == 0 {
            self.unset();
        }

        self.set_find(&search_string, case_sensitive, is_regex);
        self.update_find(text, 0, text.len(), false);
    }

    /// Unsets the search and removes all highlights from the view.
    pub fn unset(&mut self) {
        self.search_string = None;
        self.occurrences = Selection::new();
        self.hls_dirty = true;
    }

    /// Sets find parameters and search query.
    fn set_find(&mut self, search_string: &str, case_sensitive: bool, is_regex: bool) {
        let case_matching = if case_sensitive {
            CaseMatching::Exact
        } else {
            CaseMatching::CaseInsensitive
        };

        if let Some(ref s) = self.search_string {
            if s == search_string && case_matching == self.case_matching && self.is_regex == is_regex {
                // search parameters did not change
                return;
            }
        }

        self.unset();

        self.search_string = Some(search_string.to_string());
        self.case_matching = case_matching;
        self.is_regex = is_regex;
    }

    /// Execute the search on the provided text in the range provided by `start` and `end`.
    pub fn update_find(&mut self, text: &Rope, start: usize, end: usize, include_slop: bool)
    {
        if self.search_string.is_none() {
            return;
        }

        // extend the search by twice the string length (twice, because case matching may increase
        // the length of an occurrence)
        let slop = if include_slop { self.search_string.as_ref().unwrap().len() * 2 } else { 0 };

        let search_string = self.search_string.as_ref().unwrap();

        // expand region to be able to find occurrences around the region's edges
        let from = max(start, slop) - slop;
        let to = min(end + slop, text.len());

        // TODO: this interval might cut a unicode codepoint, make sure it is
        // aligned to codepoint boundaries.
        let sub_text = text.subseq(Interval::new_closed_open(0, to));
        let mut find_cursor = Cursor::new(&sub_text, from);
        let mut raw_lines = text.lines_raw(from, to);

        while let Some(start) = find(&mut find_cursor, &mut raw_lines, self.case_matching, &search_string, self.is_regex) {
            let end = find_cursor.pos();

            let region = SelRegion::new(start, end);
            let (_, e) = self.occurrences.add_range_distinct(region);
            // in case of ambiguous search results (e.g. search "aba" in "ababa"),
            // the search result closer to the beginning of the file wins
            if e != end {
                // Skip the search result and keep the occurrence that is closer to
                // the beginning of the file. Re-align the cursor to the kept
                // occurrence
                find_cursor.set(e);
                continue;
            }

            // in case current cursor matches search result (for example query a* matches)
            // all cursor positions, then cursor needs to be increased so that search
            // continues at next position. Otherwise, search will result in overflow since
            // search will always repeat at current cursor position.
            if start == end {
                // determine whether end of text is reached and stop search or increase
                // cursor manually
                if end + 1 >= text.len() {
                    break;
                } else {
                    find_cursor.set(end + 1);
                }
            }

            // update line iterator so that line starts at current cursor position
            raw_lines = sub_text.lines_raw(find_cursor.pos(), to);
        }

        self.hls_dirty = true;
    }

    /// Return the occurrence closest to the provided selection `sel`. If searched is reversed then
    /// the occurrence closest to the start of the selection is returned. `wrapped` indicates that
    /// if the end of the text is reached the search continues from the start.
    pub fn next_occurrence(&self, text: &Rope, reverse: bool, wrapped: bool, sel: (usize, usize)) -> Option<SelRegion> {
        let (sel_start, sel_end) = sel;

        if self.occurrences.len() == 0 {
            return None;
        }

        if reverse {
            let next_occurrence = match sel_start.checked_sub(1) {
                Some(search_end) => self.occurrences.regions_in_range(0, search_end).last(),
                None => None
            };

            if next_occurrence.is_none() && !wrapped {
                return self.occurrences.regions_in_range(0, text.len()).last().cloned();
            }

            next_occurrence.cloned()
        } else {
            let next_occurrence = self.occurrences.regions_in_range(sel_end + 1, text.len()).first();

            if next_occurrence.is_none() && !wrapped {
                return self.occurrences.regions_in_range(0, text.len()).first().cloned();
            }

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

//! Module for searching text.

use std::cmp::{min,max};

use xi_rope::delta::{Delta, DeltaRegion};
use xi_rope::find::{find, is_multiline_regex, CaseMatching};
use xi_rope::rope::{Rope, LinesMetric, RopeInfo};
use xi_rope::tree::Cursor;
use xi_rope::interval::Interval;
use selection::{Selection, SelRegion};
use xi_rope::tree::Metric;

/// Information about search queries and number of matches for find
#[derive(Serialize, Deserialize, Debug)]
pub struct FindStatus {
    /// The current search query.
    chars: Option<String>,

    /// Whether the active search is case matching.
    case_sensitive: Option<bool>,

    /// Whether the search query is considered as regular expression.
    is_regex: Option<bool>,

    /// Total number of matches.
    matches: usize
}

/// Contains logic to search text
pub struct Find {
    // todo: link to search query so that search results can be correlated back to query

    /// The occurrences, which determine the highlights, have been updated.
    hls_dirty: bool,
    /// The currently active search string
    search_string: Option<String>,
    /// The case matching setting for the currently active search
    case_matching: CaseMatching,
    /// The search query should be considered as regular expression
    is_regex: bool,
    /// The set of all known find occurrences (highlights)
    occurrences: Selection,
}

impl Find {
    pub fn new() -> Find {
        Find {
            hls_dirty: true,
            search_string: None,
            case_matching: CaseMatching::CaseInsensitive,
            is_regex: false,
            occurrences: Selection::new(),
        }
    }

    pub fn occurrences(&self) -> &Selection {
        &self.occurrences
    }

    pub fn hls_dirty(&self) -> bool {
        self.hls_dirty
    }

    pub fn find_status(&self, matches_only: bool) -> FindStatus {
        if matches_only {
            FindStatus {
                chars: None,
                case_sensitive: None,
                is_regex: None,
                matches: self.occurrences.len(),
            }
        } else {
            FindStatus {
                chars: self.search_string.clone(),
                case_sensitive: Some(self.case_matching == CaseMatching::Exact),
                is_regex: Some(self.is_regex),
                matches: self.occurrences.len(),
            }
        }
    }

    pub fn set_hls_dirty(&mut self, is_dirty: bool) {
        self.hls_dirty = is_dirty
    }

    pub fn update_highlights(&mut self, text: &Rope, delta: &Delta<RopeInfo>) {
        // update search highlights for changed regions
        if self.search_string.is_some() {
            // invalidate occurrences around deletion positions
            for DeltaRegion{ old_offset, new_offset: _, len } in delta.iter_deletions() {
                self.occurrences.delete_range(old_offset, old_offset + len, false);
            }

            self.occurrences = self.occurrences.apply_delta(delta, false, false);

            // invalidate occurrences around insert positions
            for DeltaRegion{ new_offset, len, .. } in delta.iter_inserts() {
                self.occurrences.delete_range(new_offset, new_offset + len, false);
            }

            // update find for the whole delta and everything after
            let (iv, _) = delta.summary();

            // get last valid occurrence that was unaffected by the delta
            let start = match self.occurrences.regions_in_range(0, iv.start()).last() {
                Some(reg) => reg.end,
                None => 0
            };

            // invalidate all search results from the point of the last valid search result until ...
            let is_multi_line = LinesMetric::next(self.search_string.as_ref().unwrap(), 0).is_some();
            let is_multi_line_regex = self.is_regex && is_multiline_regex(self.search_string.as_ref().unwrap());

            if is_multi_line || is_multi_line_regex {
                // ... the end of the file
                self.occurrences.delete_range(iv.start(), text.len(), false);
                self.update_find(text, start, text.len(), true);
            } else {
                // ... the end of the line
                let mut cursor = Cursor::new(&text, iv.start());
                if let Some(end_of_line) = cursor.next::<LinesMetric>() {
                    self.occurrences.delete_range(iv.start(), end_of_line, false);
                    self.update_find(text, start, end_of_line, true);
                }
            }
        }
    }

    /// Set search parameters and executes the search.
    pub fn do_find(&mut self, text: &Rope, search_string: Option<String>, case_sensitive: bool,
                   is_regex: bool) {
        if search_string.is_none() {
            self.unset();
        }

        let search_string = search_string.unwrap();
        if search_string.len() == 0 {
            self.unset();
        }

        self.set_find(&search_string, case_sensitive, is_regex);
        self.update_find(text, 0, text.len(), false);
    }

    /// Unsets the search and removes all highlights from the view.
    pub fn unset(&mut self) {
        self.search_string = None;
        self.occurrences = Selection::new();
        self.hls_dirty = true;
    }

    /// Sets find parameters and search query.
    fn set_find(&mut self, search_string: &str, case_sensitive: bool, is_regex: bool) {
        let case_matching = if case_sensitive {
            CaseMatching::Exact
        } else {
            CaseMatching::CaseInsensitive
        };

        if let Some(ref s) = self.search_string {
            if s == search_string && case_matching == self.case_matching && self.is_regex == is_regex {
                // search parameters did not change
                return;
            }
        }

        self.unset();

        self.search_string = Some(search_string.to_string());
        self.case_matching = case_matching;
        self.is_regex = is_regex;
    }

    /// Execute the search on the provided text in the range provided by `start` and `end`.
    pub fn update_find(&mut self, text: &Rope, start: usize, end: usize, include_slop: bool)
    {
        if self.search_string.is_none() {
            return;
        }

        // extend the search by twice the string length (twice, because case matching may increase
        // the length of an occurrence)
        let slop = if include_slop { self.search_string.as_ref().unwrap().len() * 2 } else { 0 };

        let search_string = self.search_string.as_ref().unwrap();

        // expand region to be able to find occurrences around the region's edges
        let from = max(start, slop) - slop;
        let to = min(end + slop, text.len());

        // TODO: this interval might cut a unicode codepoint, make sure it is
        // aligned to codepoint boundaries.
        let sub_text = text.subseq(Interval::new_closed_open(0, to));
        let mut find_cursor = Cursor::new(&sub_text, from);
        let mut raw_lines = text.lines_raw(from, to);

        while let Some(start) = find(&mut find_cursor, &mut raw_lines, self.case_matching, &search_string, self.is_regex) {
            let end = find_cursor.pos();

            let region = SelRegion::new(start, end);
            let (_, e) = self.occurrences.add_range_distinct(region);
            // in case of ambiguous search results (e.g. search "aba" in "ababa"),
            // the search result closer to the beginning of the file wins
            if e != end {
                // Skip the search result and keep the occurrence that is closer to
                // the beginning of the file. Re-align the cursor to the kept
                // occurrence
                find_cursor.set(e);
                continue;
            }

            // in case current cursor matches search result (for example query a* matches)
            // all cursor positions, then cursor needs to be increased so that search
            // continues at next position. Otherwise, search will result in overflow since
            // search will always repeat at current cursor position.
            if start == end {
                // determine whether end of text is reached and stop search or increase
                // cursor manually
                if end + 1 >= text.len() {
                    break;
                } else {
                    find_cursor.set(end + 1);
                }
            }

            // update line iterator so that line starts at current cursor position
            raw_lines = sub_text.lines_raw(find_cursor.pos(), to);
        }

        self.hls_dirty = true;
    }

    /// Return the occurrence closest to the provided selection `sel`. If searched is reversed then
    /// the occurrence closest to the start of the selection is returned. `wrapped` indicates that
    /// if the end of the text is reached the search continues from the start.
    pub fn next_occurrence(&self, text: &Rope, reverse: bool, wrapped: bool, sel: (usize, usize)) -> Option<SelRegion> {
        let (sel_start, sel_end) = sel;

        if self.occurrences.len() == 0 {
            return None;
        }

        if reverse {
            let next_occurrence = match sel_start.checked_sub(1) {
                Some(search_end) => self.occurrences.regions_in_range(0, search_end).last(),
                None => None
            };

            if next_occurrence.is_none() && !wrapped {
                return self.occurrences.regions_in_range(0, text.len()).last().cloned();
            }

            next_occurrence.cloned()
        } else {
            let next_occurrence = self.occurrences.regions_in_range(sel_end + 1, text.len()).first();

            if next_occurrence.is_none() && !wrapped {
                return self.occurrences.regions_in_range(0, text.len()).first().cloned();
            }

            next_occurrence.cloned()
        }
    }
}<|endoftext|>


<commit_before>///Script to calculate checksums
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use crypto::sha1::Sha1;
use crypto::sha2::{Sha256, Sha512};

use std::env::args as cmd_args;
use std::fs::{read_dir, metadata};
use std::io::Read;

macro_rules! is_file {
    ($path:expr) => { std::fs::metadata($path).unwrap().is_file() }
}

macro_rules! input {
    ($msg:expr) => {{
        use std::io::{Read, Write};
        print!($msg);
        std::io::stdout().flush().unwrap();
        std::io::stdin().bytes().next();
    }}
}

#[inline(always)]
fn usage() {
    println!("Usage: hash_check [file/dir]");
}

#[inline(always)]
fn calc_checksum(path: &str) {
    if let Ok(mut file) = std::fs::File::open(&path) {
        let mut file_content: Vec<u8> = vec!();
        let mut md5_sum = Md5::new();
        let mut sha1_sum = Sha1::new();
        let mut sha256_sum = Sha256::new();
        let mut sha512_sum = Sha512::new();

        println!(">>>{}:", &path);
        file.read_to_end(&mut file_content).unwrap();
        md5_sum.input(&file_content);
        sha1_sum.input(&file_content);
        sha256_sum.input(&file_content);
        sha512_sum.input(&file_content);
        println!("MD5:   {}", md5_sum.result_str());
        println!("SHA1:  {}", sha1_sum.result_str());
        println!("SHA256:{}", sha256_sum.result_str());
        println!("SHA512:{}", sha512_sum.result_str());
        println!("=======================================================\n");
    }
    else {
        println!(">>>{}: failed to open", &path);
    }
}

fn main() {
    if cmd_args().len() < 2 { return usage(); }

    for arg in cmd_args().skip(1) {
        if let Ok(arg_meta_data) = metadata(&arg) {
            if arg_meta_data.is_file() {
                calc_checksum(&arg);
            }
            else if let Ok(dir_content) = read_dir(&arg) {
                for entry_path in dir_content.map(|entry| entry.unwrap().path()) {
                    if is_file!(&entry_path) { calc_checksum(&entry_path.to_str().unwrap()); }
                }
            }
            else {
                println!(">>>{}: cannot access content of this dir", &arg);
                continue;
            }
        }
        else {
            println!(">>>{}: cannot access file/directory", &arg);
            continue;
        }
    }

    input!("Press Enter to exit...");
}
<commit_msg>hash_sum update with partial file download<commit_after>///Script to calculate checksums
extern crate crypto;

use crypto::digest::Digest;
use crypto::md5::Md5;
use crypto::sha1::Sha1;
use crypto::sha2::{Sha256, Sha512};

use std::env::args as cmd_args;
use std::fs::{read_dir, metadata};
use std::io::{Read, BufReader};

//Buffer size 10kbs
const BUFFER_SIZE: usize = 10000;

macro_rules! is_file {
    ($path:expr) => { std::fs::metadata($path).unwrap().is_file() }
}

macro_rules! input {
    ($msg:expr) => {{
        use std::io::{Read, Write};
        print!($msg);
        std::io::stdout().flush().unwrap();
        std::io::stdin().bytes().next();
    }}
}

#[inline(always)]
fn usage() {
    println!("Usage: hash_check [file/dir]");
}

#[inline(always)]
fn calc_checksum(path: &str) {
    if let Ok(file) = std::fs::File::open(&path) {
        let mut file = BufReader::new(file);
        let mut md5_sum = Md5::new();
        let mut sha1_sum = Sha1::new();
        let mut sha256_sum = Sha256::new();
        let mut sha512_sum = Sha512::new();

        println!(">>>{}:", &path);
        loop {
            let mut file_content: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
            let read_bytes = file.read(&mut file_content).unwrap();
            if read_bytes == 0 { break; }

            //In case read is unable to fill buffer completely.
            let slice_content = &file_content[..read_bytes];
            md5_sum.input(slice_content);
            sha1_sum.input(slice_content);
            sha256_sum.input(slice_content);
            sha512_sum.input(slice_content);
        }
        println!("MD5:   {}", md5_sum.result_str());
        println!("SHA1:  {}", sha1_sum.result_str());
        println!("SHA256:{}", sha256_sum.result_str());
        println!("SHA512:{}", sha512_sum.result_str());
        println!("=======================================================\n");
    }
    else {
        println!(">>>{}: failed to open", &path);
    }
}

fn main() {
    if cmd_args().len() < 2 { return usage(); }

    for arg in cmd_args().skip(1) {
        if let Ok(arg_meta_data) = metadata(&arg) {
            if arg_meta_data.is_file() {
                calc_checksum(&arg);
            }
            else if let Ok(dir_content) = read_dir(&arg) {
                for entry_path in dir_content.map(|entry| entry.unwrap().path()) {
                    if is_file!(&entry_path) { calc_checksum(&entry_path.to_str().unwrap()); }
                }
            }
            else {
                println!(">>>{}: cannot access content of this dir", &arg);
                continue;
            }
        }
        else {
            println!(">>>{}: cannot access file/directory", &arg);
            continue;
        }
    }

    input!("Press Enter to exit...");
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Debug, Formatter};
use std::iter::FromIterator;
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

#[derive(Clone)]
pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl Debug for PathVec {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut f = f.debug_list();
        for p in self.iter() {
            f.entry(p);
        }
        f.finish()
    }
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.clone().unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item = &PathBuf> {
        self.vec.iter()
    }

    pub fn unique(self) -> Self {
        Self::from_iter(IndexSet::<_>::from_iter(self.vec))
    }

    pub fn no_version_managers(self) -> Self {
        self.vec
            .into_iter()
            .filter(|p| !p.ends_with(".pyenv/shims") && !p.ends_with(".rbenv/shims"))
            .collect()
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        let unparsed = input.as_ref();
        if !unparsed.is_empty() {
            env::split_paths(unparsed).filter(|p| p.len() > 0).collect()
        } else {
            Self::new()
        }
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl FromIterator<PathBuf> for PathVec {
    fn from_iter<T: IntoIterator<Item = PathBuf>>(iter: T) -> Self {
        Self {
            vec: FromIterator::from_iter(iter),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::new());
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::new());
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add two items to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        ps.push_back(BAR.to_string());
        let actual = ps.make();
        let expected = OsString::from(format!("{}:{}", FOO, BAR));
        assert_eq!(actual, expected);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // should fix following cases
        let ps = PathVec::parse(OsString::from(":/foo"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");
        let ps = PathVec::parse(OsString::from("/foo:"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }

    #[test]
    fn test_unique() {
        let input = OsString::from("/a:/b:/a");
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a:/b"))
    }
}
<commit_msg>more readable parsing<commit_after>use std::collections::VecDeque;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Debug, Formatter};
use std::iter::FromIterator;
use std::path::PathBuf;

use indexmap::IndexSet;
use nix::NixPath;

#[derive(Clone)]
pub struct PathVec {
    vec: VecDeque<PathBuf>,
}

impl Debug for PathVec {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut f = f.debug_list();
        for p in self.iter() {
            f.entry(p);
        }
        f.finish()
    }
}

impl PathVec {
    pub fn make(&self) -> OsString {
        return env::join_paths(self.clone().unique()).expect("join path error");
    }

    pub fn iter(&self) -> impl Iterator<Item = &PathBuf> {
        self.vec.iter()
    }

    pub fn unique(self) -> Self {
        Self::from_iter(IndexSet::<_>::from_iter(self.vec))
    }

    pub fn no_version_managers(self) -> Self {
        self.vec
            .into_iter()
            .filter(|p| !p.ends_with(".pyenv/shims") && !p.ends_with(".rbenv/shims"))
            .collect()
    }

    pub fn push_front<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_front(path.into())
    }

    #[allow(dead_code)]
    pub fn push_back<T: Into<PathBuf>>(&mut self, path: T) {
        self.vec.push_back(path.into())
    }

    pub fn parse<T: AsRef<OsStr>>(input: T) -> Self {
        env::split_paths(input.as_ref())
            .filter(|p| p.len() > 0)
            .collect()
    }

    pub fn new() -> Self {
        Self {
            vec: VecDeque::new(),
        }
    }
}

impl FromIterator<PathBuf> for PathVec {
    fn from_iter<T: IntoIterator<Item = PathBuf>>(iter: T) -> Self {
        Self {
            vec: FromIterator::from_iter(iter),
        }
    }
}

impl IntoIterator for PathVec {
    type Item = PathBuf;
    type IntoIter = std::collections::vec_deque::IntoIter<PathBuf>;

    fn into_iter(self) -> Self::IntoIter {
        self.vec.into_iter()
    }
}

#[cfg(test)]
mod tests {
    // Note this useful idiom: importing names from outer (for mod tests) scope.
    use super::*;

    const FOO: &str = "/foo";
    const BAR: &str = "/bar";

    #[test]
    fn test() {
        // no item
        let ps = PathVec::parse(OsString::new());
        let actual = ps.make();
        assert_eq!(actual, "");

        // no item add one to front
        let mut ps = PathVec::parse(OsString::new());
        ps.push_front(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add one to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // no item add two items to back
        let mut ps = PathVec::parse(OsString::new());
        ps.push_back(FOO.to_string());
        ps.push_back(BAR.to_string());
        let actual = ps.make();
        let expected = OsString::from(format!("{}:{}", FOO, BAR));
        assert_eq!(actual, expected);

        // one item
        let ps = PathVec::parse(OsString::from(FOO));
        let actual = ps.make();
        assert_eq!(actual, FOO);

        // should fix following cases
        let ps = PathVec::parse(OsString::from(":/foo"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");
        let ps = PathVec::parse(OsString::from("/foo:"));
        let actual = ps.make();
        assert_eq!(actual, "/foo");

        // two items
        let input = OsString::from(format!("{}:{}", FOO, BAR));
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, input);

        // move order correctly
        let input = OsString::from("/a:/b:/c");
        let mut ps = PathVec::parse(&input);
        ps.push_front("/c".to_string());
        let actual = ps.make();
        let expect = OsString::from("/c:/a:/b");
        assert_eq!(actual, expect);

        // remove pyenv, rbenv, and node path
        let input = OsString::from("/a:/home/.pyenv/shims:/home/.rbenv/shims");
        let ps = PathVec::parse(&input).no_version_managers();
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a"))
    }

    #[test]
    fn test_unique() {
        let input = OsString::from("/a:/b:/a");
        let ps = PathVec::parse(&input);
        let actual = ps.make();
        assert_eq!(actual, OsString::from("/a:/b"))
    }
}
<|endoftext|>


<commit_before>pub type EntryContent = String;
<commit_msg>content.rs: Add documentation<commit_after>/**
 * EntryContent type
 */
pub type EntryContent = String;
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not
    /// specified.
    pub fn into_pathbuf(self) -> Result<PathBuf> {
        let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError.into_error()));
        base.push(self.id);
        Ok(base)
    }

    pub fn exists(&self) -> bool {
        // TODO: hiding error here.
        self.clone().into_pathbuf().map(|pb| pb.exists()).unwrap_or(false)
    }

    pub fn to_str(&self) -> Result<String> {
        self.base
            .as_ref()
            .cloned()
            .map(|mut base| { base.push(self.id.clone()); base })
            .unwrap_or_else(|| self.id.clone())
            .to_str()
            .map(String::from)
            .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<commit_msg>Impl PartialEq for StoreId<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::Deref;
use std::path::Path;
use std::path::PathBuf;

use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use error::MapErrInto;
use store::Result;

/// The Index into the Store
#[derive(Debug, Clone, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl PartialEq for StoreId {
    fn eq(&self, other: &StoreId) -> bool {
        self.id == other.id
    }
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    /// Try to create a StoreId object from a filesystem-absolute path.
    ///
    /// Automatically creates a StoreId object which has a `base` set to `store_part` if stripping
    /// the `store_part` from the `full_path` succeeded.
    ///
    /// Returns a `StoreErrorKind::StoreIdBuildFromFullPathError` if stripping failes.
    pub fn from_full_path<D>(store_part: &PathBuf, full_path: D) -> Result<StoreId>
        where D: Deref<Target = Path>
    {
        let p = try!(
            full_path.strip_prefix(store_part).map_err_into(SEK::StoreIdBuildFromFullPathError)
        );
        StoreId::new(Some(store_part.clone()), PathBuf::from(p))
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    /// Transform the StoreId object into a PathBuf, error if the base of the StoreId is not
    /// specified.
    pub fn into_pathbuf(self) -> Result<PathBuf> {
        let mut base = try!(self.base.ok_or(SEK::StoreIdHasNoBaseError.into_error()));
        base.push(self.id);
        Ok(base)
    }

    pub fn exists(&self) -> bool {
        // TODO: hiding error here.
        self.clone().into_pathbuf().map(|pb| pb.exists()).unwrap_or(false)
    }

    pub fn to_str(&self) -> Result<String> {
        self.base
            .as_ref()
            .cloned()
            .map(|mut base| { base.push(self.id.clone()); base })
            .unwrap_or_else(|| self.id.clone())
            .to_str()
            .map(String::from)
            .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

    /// Get the _local_ part of a StoreId object, as in "the part from the store root to the entry".
    pub fn local(&self) -> &PathBuf {
        &self.id
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> Result<StoreId> {
        StoreId::new_baseless(self)
    }
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(name);
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test");
    }

}
<|endoftext|>


<commit_before>use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};

impl Error for fmt::Error {
    fn custom<T: Display>(_msg: T) -> Self {
        fmt::Error
    }
}

macro_rules! fmt_primitives {
    ($($f:ident: $t:ty,)*) => {
        $(
            fn $f(self, v: $t) -> fmt::Result {
                write!(self, "{}", v)
            }
        )*
    };
}

impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
    type Ok = ();
    type Error = fmt::Error;
    type SerializeSeq = Impossible<(), fmt::Error>;
    type SerializeTuple = Impossible<(), fmt::Error>;
    type SerializeTupleStruct = Impossible<(), fmt::Error>;
    type SerializeTupleVariant = Impossible<(), fmt::Error>;
    type SerializeMap = Impossible<(), fmt::Error>;
    type SerializeStruct = Impossible<(), fmt::Error>;
    type SerializeStructVariant = Impossible<(), fmt::Error>;

    fmt_primitives! {
        serialize_bool: bool,
        serialize_i8: i8,
        serialize_i16: i16,
        serialize_i32: i32,
        serialize_i64: i64,
        serialize_u8: u8,
        serialize_u16: u16,
        serialize_u32: u32,
        serialize_u64: u64,
        serialize_f32: f32,
        serialize_f64: f64,
        serialize_char: char,
        serialize_str: &str,
        serialize_unit_struct: &'static str,
    }

    fn serialize_unit(self) -> fmt::Result {
        Ok(())
    }

    fn serialize_unit_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> fmt::Result {
        write!(self, "{}", variant)
    }

    fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_none(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _value: &T,
    ) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
    where
        T: Display,
    {
        Display::fmt(value, self)
    }
}
<commit_msg>Remove serialize_unit from Formatter's impl<commit_after>use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};

impl Error for fmt::Error {
    fn custom<T: Display>(_msg: T) -> Self {
        fmt::Error
    }
}

macro_rules! fmt_primitives {
    ($($f:ident: $t:ty,)*) => {
        $(
            fn $f(self, v: $t) -> fmt::Result {
                write!(self, "{}", v)
            }
        )*
    };
}

impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
    type Ok = ();
    type Error = fmt::Error;
    type SerializeSeq = Impossible<(), fmt::Error>;
    type SerializeTuple = Impossible<(), fmt::Error>;
    type SerializeTupleStruct = Impossible<(), fmt::Error>;
    type SerializeTupleVariant = Impossible<(), fmt::Error>;
    type SerializeMap = Impossible<(), fmt::Error>;
    type SerializeStruct = Impossible<(), fmt::Error>;
    type SerializeStructVariant = Impossible<(), fmt::Error>;

    fmt_primitives! {
        serialize_bool: bool,
        serialize_i8: i8,
        serialize_i16: i16,
        serialize_i32: i32,
        serialize_i64: i64,
        serialize_u8: u8,
        serialize_u16: u16,
        serialize_u32: u32,
        serialize_u64: u64,
        serialize_f32: f32,
        serialize_f64: f64,
        serialize_char: char,
        serialize_str: &str,
        serialize_unit_struct: &'static str,
    }

    fn serialize_unit_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> fmt::Result {
        write!(self, "{}", variant)
    }

    fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_none(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_unit(self) -> fmt::Result {
        Err(fmt::Error)
    }

    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, _value: &T) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _value: &T,
    ) -> fmt::Result
    where
        T: Serialize,
    {
        Err(fmt::Error)
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_tuple_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeTupleVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct(
        self,
        _name: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStruct, fmt::Error> {
        Err(fmt::Error)
    }

    fn serialize_struct_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        _variant: &'static str,
        _len: usize,
    ) -> Result<Self::SerializeStructVariant, fmt::Error> {
        Err(fmt::Error)
    }

    fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
    where
        T: Display,
    {
        Display::fmt(value, self)
    }
}
<|endoftext|>


<commit_before>fn main() {
    let mre = mre::mre(
        // Create a zeromq context that MRE will use to talk to Mongrel2.
        alt zmq::init(1) {
          ok(ctx) { ctx }
          err(e) { fail e.to_str() }
        },

        // A UUID for this Mongrel2 backend.
        some("E4B7CE14-E7F7-43EE-A3E6-DB7B0A0C106F"),

        // The addresses to receive requests from.
        ~["tcp://127.0.0.1:9996"],

        // The addresses to send responses to.
        ~["tcp://127.0.0.1:9997"],

        // Create our middleware, which preproceses requests and
        // responses. For now we'll just use the logger.
        ~[mre::middleware::logger(io::stdout())],

        // A function to create per-request data. This can be used by
        // middleware like middleware::session to automatically look
        // up the current user and session data in the database. We don't
        // need it for this example, so just return a unit value.
        { || () }
    );

    // Route our responses.
    do mre.get("^/$") |_req, rep, _m| {
        rep.reply_html(200u,
            "\n" +
            "\n" +
            "
Hello world!
\n" +
            "\n" +
            "")
    }

    // Finally, start the MRE event loop.
    mre.run();
}
<commit_msg>Whitespace cleanup<commit_after>fn main() {
    let mre = mre::mre(
        // Create a zeromq context that MRE will use to talk to Mongrel2.
        alt zmq::init(1) {
          ok(ctx) { ctx }
          err(e) { fail e.to_str() }
        },

        // A UUID for this Mongrel2 backend.
        some("E4B7CE14-E7F7-43EE-A3E6-DB7B0A0C106F"),

        // The addresses to receive requests from.
        ~["tcp://127.0.0.1:9996"],

        // The addresses to send responses to.
        ~["tcp://127.0.0.1:9997"],

        // Create our middleware, which preproceses requests and
        // responses. For now we'll just use the logger.
        ~[mre::middleware::logger(io::stdout())],

        // A function to create per-request data. This can be used by
        // middleware like middleware::session to automatically look
        // up the current user and session data in the database. We don't
        // need it for this example, so just return a unit value.
        || { () }
    );

    // Route our responses.
    do mre.get("^/$") |_req, rep, _m| {
        rep.reply_html(200u,
            "\n" +
            "\n" +
            "
Hello world!
\n" +
            "\n" +
            "")
    }

    // Finally, start the MRE event loop.
    mre.run();
}
<|endoftext|>