<commit_before>mod problem27 {
    // palindrome detector for Strings
    pub fn palindrome(s: &str) -> bool {
        let c = s.chars();
        // c.collect::<Vec<_>>() == c.rev().collect::<Vec<_>>()
        c.clone().eq(c.rev())
    }
}

mod problem28 {
    // flatten for vectors
    #[derive(Debug,Clone)]
    pub enum Seq<T> {
        Item(T),
        Sequence(Vec<Seq<T>>)
    }

    pub fn flatten<T>(s: Seq<T>) -> Vec<T> {
        let mut res = vec![];
        fn inner<T>(s: Seq<T>, acc: &mut Vec<T>) {
            match s {
                Seq::Item(a) => acc.push(a),
                Seq::Sequence(ss) => { for i in ss { inner(i, acc) } },
            }
        }
        inner(s, &mut res);
        res
    }
}

mod problem29 {
    // Given a string, keep its capital letters:
    // "Hello World!" -> "HW"
    fn is_capital(&c: &char) -> bool {
        c >= 'A' && c <= 'Z'
    }

    pub fn capitals(s:&str) -> String {
        s.chars().filter(is_capital).collect()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn problem27() {
        use problem27::palindrome;
        assert_eq!(true, palindrome("racecar"));
        assert_eq!(false, palindrome("adad"));
        assert_eq!(true, palindrome("人人為我,我為人人"));
        assert_eq!(true, palindrome("아들딸들아"));
        assert_eq!(false, palindrome("Я иду с мечем, судия"));
    }

    #[test]
    fn problem28() {
        use problem28::{flatten, Seq};
        // ["a", ["b", "c"], "d"]
        let s1 = Seq::Sequence(vec![Seq::Item("a"), Seq::Sequence(vec![Seq::Item("b"), Seq::Item("c")]), Seq::Item("d")]);
        println!("flatten({:?}) = {:?}", s1, flatten(s1.clone()));
        assert_eq!(flatten(s1),
                   vec!["a", "b", "c", "d"])
    }

    #[test]
    fn problem29() {
        use problem29::capitals;
        assert_eq!(capitals("HeLlO, WoRlD!"), "HLOWRD".to_owned());
        assert_eq!(capitals("nothing"), "".to_owned());
        assert_eq!(capitals("$#A(*&987Zf"), "AZ".to_owned());
    }
}
<commit_msg>WIP: Problem 30<commit_after>mod problem27 {
    // palindrome detector for Strings
    pub fn palindrome(s: &str) -> bool {
        let c = s.chars();
        // c.collect::<Vec<_>>() == c.rev().collect::<Vec<_>>()
        c.clone().eq(c.rev())
    }
}

mod problem28 {
    // flatten for vectors
    #[derive(Debug,Clone)]
    pub enum Seq<T> {
        Item(T),
        Sequence(Vec<Seq<T>>)
    }

    pub fn flatten<T>(s: Seq<T>) -> Vec<T> {
        let mut res = vec![];
        fn inner<T>(s: Seq<T>, acc: &mut Vec<T>) {
            match s {
                Seq::Item(a) => acc.push(a),
                Seq::Sequence(ss) => { for i in ss { inner(i, acc) } },
            }
        }
        inner(s, &mut res);
        res
    }
}

mod problem29 {
    // Given a string, keep its capital letters:
    // "Hello World!" -> "HW"
    fn is_capital(&c: &char) -> bool {
        c >= 'A' && c <= 'Z'
    }

    pub fn capitals(s:&str) -> String {
        s.chars().filter(is_capital).collect()
    }
}

mod problem30 {
    pub fn deduped<T: PartialEq, I: Iterator<Item=T>>(mut i: I) -> Vec<T> {
        let mut res: Vec<T> = Vec::new();
        if let Some(mut old) = i.next() {
            // res.push(old);
            loop {
                match i.next() {
                    Some(new) => { if old != new { res.push(old); } old = new; }
                    None => { res.push(old); break; }
                }
            }
        }
        res
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn problem27() {
        use problem27::palindrome;
        assert_eq!(true, palindrome("racecar"));
        assert_eq!(false, palindrome("adad"));
        assert_eq!(true, palindrome("人人為我,我為人人"));
        assert_eq!(true, palindrome("아들딸들아"));
        assert_eq!(false, palindrome("Я иду с мечем, судия"));
    }

    #[test]
    fn problem28() {
        use problem28::{flatten, Seq};
        // ["a", ["b", "c"], "d"]
        let s1 = Seq::Sequence(vec![Seq::Item("a"), Seq::Sequence(vec![Seq::Item("b"), Seq::Item("c")]), Seq::Item("d")]);
        println!("flatten({:?}) = {:?}", s1, flatten(s1.clone()));
        assert_eq!(flatten(s1),
                   vec!["a", "b", "c", "d"])
    }

    #[test]
    fn problem29() {
        use problem29::capitals;
        assert_eq!(capitals("HeLlO, WoRlD!"), "HLOWRD".to_owned());
        assert_eq!(capitals("nothing"), "".to_owned());
        assert_eq!(capitals("$#A(*&987Zf"), "AZ".to_owned());
    }

    #[test]
    fn problem30() {
        use problem30::{deduped};
        use std::iter::FromIterator;
        println!("{:?}", deduped(vec![1, 1, 2, 3, 3, 2, 2, 3].iter()));
        assert_eq!("Leroy" , String::from_iter(deduped("Leeeeeerrroyyy".chars()).into_iter()));

    }
}
<|endoftext|>


<commit_before>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]

extern crate goblin;

use goblin::{elf, mach};
use std::cmp::Ordering;
use std::io::Cursor;

/// An object file.
pub struct File<'a> {
    kind: ObjectKind<'a>,
    data: &'a [u8],
}

enum ObjectKind<'a> {
    Elf(elf::Elf<'a>),
    MachO(mach::MachO<'a>),
}

/// The kind of a sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionKind {
    /// The section kind is unknown.
    Unknown,
    /// An executable code section.
    Text,
    /// A data section.
    Data,
    /// A read only data section.
    ReadOnlyData,
    /// An uninitialized data section.
    UninitializedData,
    /// Some other type of text or data section.
    Other,
}

/// A symbol table entry.
pub struct Symbol<'a> {
    kind: SymbolKind,
    section: usize,
    section_kind: Option<SectionKind>,
    global: bool,
    name: &'a [u8],
    address: u64,
    size: u64,
}

/// The kind of a symbol.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolKind {
    /// The symbol kind is unknown.
    Unknown,
    /// The symbol is for executable code.
    Text,
    /// The symbol is for a data object.
    Data,
    /// The symbol is for a section.
    Section,
    /// The symbol is the name of a file. It precedes symbols within that file.
    File,
    /// The symbol is for an uninitialized common block.
    Common,
    /// The symbol is for a thread local storage entity.
    Tls,
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor).map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => {
                let elf = elf::Elf::parse(data).map_err(|_| "Could not parse ELF header")?;
                ObjectKind::Elf(elf)
            }
            goblin::Hint::Mach(_) => {
                let macho =
                    mach::MachO::parse(data, 0).map_err(|_| "Could not parse Mach-O header")?;
                ObjectKind::MachO(macho)
            }
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind, data })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_section(elf, section_name, self.data),
            ObjectKind::MachO(ref macho) => macho_get_section(macho, section_name),
        }
    }

    /// Get a `Vec` of the symbols defined in the file.
    pub fn get_symbols(&self) -> Vec<Symbol<'a>> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_symbols(elf),
            ObjectKind::MachO(ref macho) => macho_get_symbols(macho),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.little_endian,
            ObjectKind::MachO(ref macho) => macho.header.is_little_endian(),
        }
    }
}

impl<'a> Symbol<'a> {
    /// Return the kind of this symbol.
    pub fn kind(&self) -> SymbolKind {
        self.kind
    }

    /// Returns the section kind for the symbol, or `None` if the symbol is undefnined.
    pub fn section_kind(&self) -> Option<SectionKind> {
        self.section_kind
    }

    /// Return true if the symbol is undefined.
    pub fn is_undefined(&self) -> bool {
        self.section_kind.is_none()
    }

    /// Return true if the symbol is global.
    pub fn is_global(&self) -> bool {
        self.global
    }

    /// Return true if the symbol is local.
    pub fn is_local(&self) -> bool {
        !self.global
    }

    /// The name of the symbol.
    pub fn name(&self) -> &'a [u8] {
        self.name
    }

    /// The address of the symbol. May be zero if the address is unknown.
    pub fn address(&self) -> u64 {
        self.address
    }

    /// The size of the symbol. May be zero if the size is unknown.
    pub fn size(&self) -> u64 {
        self.size
    }
}

fn elf_get_section<'a>(elf: &elf::Elf<'a>, section_name: &str, data: &'a [u8]) -> Option<&'a [u8]> {
    for header in &elf.section_headers {
        if let Some(Ok(name)) = elf.shdr_strtab.get(header.sh_name) {
            if name == section_name {
                return Some(&data[header.sh_offset as usize..][..header.sh_size as usize]);
            }
        }
    }
    None
}

fn elf_get_symbols<'a>(elf: &elf::Elf<'a>) -> Vec<Symbol<'a>> {
    // Determine section kinds.
    // The section kinds are inherited by symbols in those sections.
    let mut section_kinds = Vec::new();
    for sh in &elf.section_headers {
        let kind = match sh.sh_type {
            elf::section_header::SHT_PROGBITS => {
                if sh.sh_flags & elf::section_header::SHF_EXECINSTR as u64 != 0 {
                    SectionKind::Text
                } else if sh.sh_flags & elf::section_header::SHF_WRITE as u64 != 0 {
                    SectionKind::Data
                } else {
                    SectionKind::ReadOnlyData
                }
            }
            elf::section_header::SHT_NOBITS => SectionKind::UninitializedData,
            _ => SectionKind::Unknown,
        };
        section_kinds.push(kind);
    }

    let mut symbols = Vec::new();
    // Skip undefined symbol index.
    for sym in elf.syms.iter().skip(1) {
        let kind = match elf::sym::st_type(sym.st_info) {
            elf::sym::STT_OBJECT => SymbolKind::Data,
            elf::sym::STT_FUNC => SymbolKind::Text,
            elf::sym::STT_SECTION => SymbolKind::Section,
            elf::sym::STT_FILE => SymbolKind::File,
            elf::sym::STT_COMMON => SymbolKind::Common,
            elf::sym::STT_TLS => SymbolKind::Tls,
            _ => SymbolKind::Unknown,
        };
        let global = elf::sym::st_bind(sym.st_info) != elf::sym::STB_LOCAL;
        let section_kind = if sym.st_shndx == elf::section_header::SHN_UNDEF as usize
            || sym.st_shndx >= section_kinds.len()
        {
            None
        } else {
            Some(section_kinds[sym.st_shndx])
        };
        let name = match elf.strtab.get(sym.st_name) {
            Some(Ok(name)) => name.as_bytes(),
            _ => continue,
        };
        symbols.push(Symbol {
            kind,
            section: sym.st_shndx,
            section_kind,
            global,
            name,
            address: sym.st_value,
            size: sym.st_size,
        });
    }
    symbols
}

fn macho_get_section<'a>(macho: &mach::MachO<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = if section_name == ".eh_frame" {
        "__TEXT"
    } else {
        "__DWARF"
    };
    let section_name = macho_translate_section_name(section_name);

    for segment in &macho.segments {
        if let Ok(name) = segment.name() {
            if name == segment_name {
                for section in segment {
                    if let Ok((section, data)) = section {
                        if let Ok(name) = section.name() {
                            if name.as_bytes() == &*section_name {
                                return Some(data);
                            }
                        }
                    }
                }
            }
        }
    }
    None
}

// Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
// ".debug_info" to "__debug_info".
fn macho_translate_section_name(section_name: &str) -> Vec<u8> {
    let mut name = Vec::with_capacity(section_name.len() + 1);
    name.push(b'_');
    name.push(b'_');
    for ch in &section_name.as_bytes()[1..] {
        name.push(*ch);
    }
    name
}

fn macho_get_symbols<'a>(macho: &mach::MachO<'a>) -> Vec<Symbol<'a>> {
    // Determine section kinds and end addresses.
    // The section kinds are inherited by symbols in those sections.
    // The section end addresses are needed for calculating symbol sizes.
    let mut section_kinds = Vec::new();
    let mut section_ends = Vec::new();
    for segment in &macho.segments {
        for section in segment {
            if let Ok((section, _)) = section {
                let sectname = section
                    .name()
                    .map(str::as_bytes)
                    .unwrap_or(&section.sectname[..]);
                let segname = section
                    .segname()
                    .map(str::as_bytes)
                    .unwrap_or(&section.segname[..]);
                let (section_kind, symbol_kind) = if segname == b"__TEXT" && sectname == b"__text" {
                    (SectionKind::Text, SymbolKind::Text)
                } else if segname == b"__DATA" && sectname == b"__data" {
                    (SectionKind::Data, SymbolKind::Data)
                } else if segname == b"__DATA" && sectname == b"__bss" {
                    (SectionKind::UninitializedData, SymbolKind::Data)
                } else {
                    (SectionKind::Other, SymbolKind::Unknown)
                };
                let section_index = section_kinds.len();
                section_kinds.push((section_kind, symbol_kind));
                section_ends.push(Symbol {
                    kind: SymbolKind::Section,
                    section: section_index + 1,
                    section_kind: Some(section_kind),
                    global: false,
                    name: &[],
                    address: section.addr + section.size,
                    size: 0,
                });
            } else {
                // Add placeholder so that indexing works.
                section_kinds.push((SectionKind::Unknown, SymbolKind::Unknown));
            }
        }
    }

    let mut symbols = Vec::new();
    for sym in macho.symbols() {
        if let Ok((name, nlist)) = sym {
            // Skip STAB debugging symbols.
            if nlist.n_type & 0xe0 != 0 {
                continue;
            }
            let n_type = nlist.n_type & mach::symbols::NLIST_TYPE_MASK;
            let (section_kind, kind) = if n_type == mach::symbols::N_SECT {
                if nlist.n_sect == 0 || nlist.n_sect - 1 >= section_kinds.len() {
                    (None, SymbolKind::Unknown)
                } else {
                    let (section_kind, kind) = section_kinds[nlist.n_sect - 1];
                    (Some(section_kind), kind)
                }
            } else {
                (None, SymbolKind::Unknown)
            };
            symbols.push(Symbol {
                kind,
                section: nlist.n_sect,
                section_kind,
                global: nlist.is_global(),
                name: name.as_bytes(),
                address: nlist.n_value,
                size: 0,
            });
        }
    }

    {
        // Calculate symbol sizes by sorting and finding the next symbol.
        let mut symbol_refs = Vec::with_capacity(symbols.len() + section_ends.len());
        symbol_refs.extend(symbols.iter_mut().filter(|s| !s.is_undefined()));
        symbol_refs.extend(section_ends.iter_mut());
        symbol_refs.sort_by(|a, b| {
            let ord = a.section.cmp(&b.section);
            if ord != Ordering::Equal {
                return ord;
            }
            let ord = a.address.cmp(&b.address);
            if ord != Ordering::Equal {
                return ord;
            }
            // Place the dummy end of section symbols last.
            (a.kind == SymbolKind::Section).cmp(&(b.kind == SymbolKind::Section))
        });

        for i in 0..symbol_refs.len() {
            let (before, after) = symbol_refs.split_at_mut(i + 1);
            let sym = &mut before[i];
            if sym.kind != SymbolKind::Section {
                if let Some(next) = after
                    .iter()
                    .skip_while(|x| {
                        x.kind != SymbolKind::Section && x.address == sym.address
                    })
                    .next()
                {
                    sym.size = next.address - sym.address;
                }
            }
        }
    }

    symbols
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<commit_msg>Inline Symbol getters<commit_after>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]

extern crate goblin;

use goblin::{elf, mach};
use std::cmp::Ordering;
use std::io::Cursor;

/// An object file.
pub struct File<'a> {
    kind: ObjectKind<'a>,
    data: &'a [u8],
}

enum ObjectKind<'a> {
    Elf(elf::Elf<'a>),
    MachO(mach::MachO<'a>),
}

/// The kind of a sections.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionKind {
    /// The section kind is unknown.
    Unknown,
    /// An executable code section.
    Text,
    /// A data section.
    Data,
    /// A read only data section.
    ReadOnlyData,
    /// An uninitialized data section.
    UninitializedData,
    /// Some other type of text or data section.
    Other,
}

/// A symbol table entry.
pub struct Symbol<'a> {
    kind: SymbolKind,
    section: usize,
    section_kind: Option<SectionKind>,
    global: bool,
    name: &'a [u8],
    address: u64,
    size: u64,
}

/// The kind of a symbol.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolKind {
    /// The symbol kind is unknown.
    Unknown,
    /// The symbol is for executable code.
    Text,
    /// The symbol is for a data object.
    Data,
    /// The symbol is for a section.
    Section,
    /// The symbol is the name of a file. It precedes symbols within that file.
    File,
    /// The symbol is for an uninitialized common block.
    Common,
    /// The symbol is for a thread local storage entity.
    Tls,
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor).map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => {
                let elf = elf::Elf::parse(data).map_err(|_| "Could not parse ELF header")?;
                ObjectKind::Elf(elf)
            }
            goblin::Hint::Mach(_) => {
                let macho =
                    mach::MachO::parse(data, 0).map_err(|_| "Could not parse Mach-O header")?;
                ObjectKind::MachO(macho)
            }
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind, data })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_section(elf, section_name, self.data),
            ObjectKind::MachO(ref macho) => macho_get_section(macho, section_name),
        }
    }

    /// Get a `Vec` of the symbols defined in the file.
    pub fn get_symbols(&self) -> Vec<Symbol<'a>> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_symbols(elf),
            ObjectKind::MachO(ref macho) => macho_get_symbols(macho),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.little_endian,
            ObjectKind::MachO(ref macho) => macho.header.is_little_endian(),
        }
    }
}

impl<'a> Symbol<'a> {
    /// Return the kind of this symbol.
    #[inline]
    pub fn kind(&self) -> SymbolKind {
        self.kind
    }

    /// Returns the section kind for the symbol, or `None` if the symbol is undefnined.
    #[inline]
    pub fn section_kind(&self) -> Option<SectionKind> {
        self.section_kind
    }

    /// Return true if the symbol is undefined.
    #[inline]
    pub fn is_undefined(&self) -> bool {
        self.section_kind.is_none()
    }

    /// Return true if the symbol is global.
    #[inline]
    pub fn is_global(&self) -> bool {
        self.global
    }

    /// Return true if the symbol is local.
    #[inline]
    pub fn is_local(&self) -> bool {
        !self.global
    }

    /// The name of the symbol.
    #[inline]
    pub fn name(&self) -> &'a [u8] {
        self.name
    }

    /// The address of the symbol. May be zero if the address is unknown.
    #[inline]
    pub fn address(&self) -> u64 {
        self.address
    }

    /// The size of the symbol. May be zero if the size is unknown.
    #[inline]
    pub fn size(&self) -> u64 {
        self.size
    }
}

fn elf_get_section<'a>(elf: &elf::Elf<'a>, section_name: &str, data: &'a [u8]) -> Option<&'a [u8]> {
    for header in &elf.section_headers {
        if let Some(Ok(name)) = elf.shdr_strtab.get(header.sh_name) {
            if name == section_name {
                return Some(&data[header.sh_offset as usize..][..header.sh_size as usize]);
            }
        }
    }
    None
}

fn elf_get_symbols<'a>(elf: &elf::Elf<'a>) -> Vec<Symbol<'a>> {
    // Determine section kinds.
    // The section kinds are inherited by symbols in those sections.
    let mut section_kinds = Vec::new();
    for sh in &elf.section_headers {
        let kind = match sh.sh_type {
            elf::section_header::SHT_PROGBITS => {
                if sh.sh_flags & elf::section_header::SHF_EXECINSTR as u64 != 0 {
                    SectionKind::Text
                } else if sh.sh_flags & elf::section_header::SHF_WRITE as u64 != 0 {
                    SectionKind::Data
                } else {
                    SectionKind::ReadOnlyData
                }
            }
            elf::section_header::SHT_NOBITS => SectionKind::UninitializedData,
            _ => SectionKind::Unknown,
        };
        section_kinds.push(kind);
    }

    let mut symbols = Vec::new();
    // Skip undefined symbol index.
    for sym in elf.syms.iter().skip(1) {
        let kind = match elf::sym::st_type(sym.st_info) {
            elf::sym::STT_OBJECT => SymbolKind::Data,
            elf::sym::STT_FUNC => SymbolKind::Text,
            elf::sym::STT_SECTION => SymbolKind::Section,
            elf::sym::STT_FILE => SymbolKind::File,
            elf::sym::STT_COMMON => SymbolKind::Common,
            elf::sym::STT_TLS => SymbolKind::Tls,
            _ => SymbolKind::Unknown,
        };
        let global = elf::sym::st_bind(sym.st_info) != elf::sym::STB_LOCAL;
        let section_kind = if sym.st_shndx == elf::section_header::SHN_UNDEF as usize
            || sym.st_shndx >= section_kinds.len()
        {
            None
        } else {
            Some(section_kinds[sym.st_shndx])
        };
        let name = match elf.strtab.get(sym.st_name) {
            Some(Ok(name)) => name.as_bytes(),
            _ => continue,
        };
        symbols.push(Symbol {
            kind,
            section: sym.st_shndx,
            section_kind,
            global,
            name,
            address: sym.st_value,
            size: sym.st_size,
        });
    }
    symbols
}

fn macho_get_section<'a>(macho: &mach::MachO<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = if section_name == ".eh_frame" {
        "__TEXT"
    } else {
        "__DWARF"
    };
    let section_name = macho_translate_section_name(section_name);

    for segment in &macho.segments {
        if let Ok(name) = segment.name() {
            if name == segment_name {
                for section in segment {
                    if let Ok((section, data)) = section {
                        if let Ok(name) = section.name() {
                            if name.as_bytes() == &*section_name {
                                return Some(data);
                            }
                        }
                    }
                }
            }
        }
    }
    None
}

// Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
// ".debug_info" to "__debug_info".
fn macho_translate_section_name(section_name: &str) -> Vec<u8> {
    let mut name = Vec::with_capacity(section_name.len() + 1);
    name.push(b'_');
    name.push(b'_');
    for ch in &section_name.as_bytes()[1..] {
        name.push(*ch);
    }
    name
}

fn macho_get_symbols<'a>(macho: &mach::MachO<'a>) -> Vec<Symbol<'a>> {
    // Determine section kinds and end addresses.
    // The section kinds are inherited by symbols in those sections.
    // The section end addresses are needed for calculating symbol sizes.
    let mut section_kinds = Vec::new();
    let mut section_ends = Vec::new();
    for segment in &macho.segments {
        for section in segment {
            if let Ok((section, _)) = section {
                let sectname = section
                    .name()
                    .map(str::as_bytes)
                    .unwrap_or(&section.sectname[..]);
                let segname = section
                    .segname()
                    .map(str::as_bytes)
                    .unwrap_or(&section.segname[..]);
                let (section_kind, symbol_kind) = if segname == b"__TEXT" && sectname == b"__text" {
                    (SectionKind::Text, SymbolKind::Text)
                } else if segname == b"__DATA" && sectname == b"__data" {
                    (SectionKind::Data, SymbolKind::Data)
                } else if segname == b"__DATA" && sectname == b"__bss" {
                    (SectionKind::UninitializedData, SymbolKind::Data)
                } else {
                    (SectionKind::Other, SymbolKind::Unknown)
                };
                let section_index = section_kinds.len();
                section_kinds.push((section_kind, symbol_kind));
                section_ends.push(Symbol {
                    kind: SymbolKind::Section,
                    section: section_index + 1,
                    section_kind: Some(section_kind),
                    global: false,
                    name: &[],
                    address: section.addr + section.size,
                    size: 0,
                });
            } else {
                // Add placeholder so that indexing works.
                section_kinds.push((SectionKind::Unknown, SymbolKind::Unknown));
            }
        }
    }

    let mut symbols = Vec::new();
    for sym in macho.symbols() {
        if let Ok((name, nlist)) = sym {
            // Skip STAB debugging symbols.
            if nlist.n_type & 0xe0 != 0 {
                continue;
            }
            let n_type = nlist.n_type & mach::symbols::NLIST_TYPE_MASK;
            let (section_kind, kind) = if n_type == mach::symbols::N_SECT {
                if nlist.n_sect == 0 || nlist.n_sect - 1 >= section_kinds.len() {
                    (None, SymbolKind::Unknown)
                } else {
                    let (section_kind, kind) = section_kinds[nlist.n_sect - 1];
                    (Some(section_kind), kind)
                }
            } else {
                (None, SymbolKind::Unknown)
            };
            symbols.push(Symbol {
                kind,
                section: nlist.n_sect,
                section_kind,
                global: nlist.is_global(),
                name: name.as_bytes(),
                address: nlist.n_value,
                size: 0,
            });
        }
    }

    {
        // Calculate symbol sizes by sorting and finding the next symbol.
        let mut symbol_refs = Vec::with_capacity(symbols.len() + section_ends.len());
        symbol_refs.extend(symbols.iter_mut().filter(|s| !s.is_undefined()));
        symbol_refs.extend(section_ends.iter_mut());
        symbol_refs.sort_by(|a, b| {
            let ord = a.section.cmp(&b.section);
            if ord != Ordering::Equal {
                return ord;
            }
            let ord = a.address.cmp(&b.address);
            if ord != Ordering::Equal {
                return ord;
            }
            // Place the dummy end of section symbols last.
            (a.kind == SymbolKind::Section).cmp(&(b.kind == SymbolKind::Section))
        });

        for i in 0..symbol_refs.len() {
            let (before, after) = symbol_refs.split_at_mut(i + 1);
            let sym = &mut before[i];
            if sym.kind != SymbolKind::Section {
                if let Some(next) = after
                    .iter()
                    .skip_while(|x| {
                        x.kind != SymbolKind::Section && x.address == sym.address
                    })
                    .next()
                {
                    sym.size = next.address - sym.address;
                }
            }
        }
    }

    symbols
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<|endoftext|>


<commit_before>#[allow(missing_copy_implementations)]
extern crate libc;
use std::c_str::CString;
use std::vec::Vec;

#[repr(C)]
pub struct DemoStruct {
	a: i32,
	b: i32
}

//just to make rustc happy, we don't actually use this.
impl Copy for DemoStruct {}

#[no_mangle]
pub extern fn get_demo_struct() -> *mut DemoStruct {
	&mut DemoStruct{a: 0, b: 1337}
}

pub type Cstr = *const libc::c_char;

#[repr(C)]
pub struct CstrArr {
	len: u32,
	data: *const Cstr
}

#[no_mangle]
pub extern fn get_array_of_strings() -> *const CstrArr {
	let rust_vec = vec!["Hello","world","from","rust"];
	unsafe {
		&CstrArr {
			len: rust_vec.len().to_u32().unwrap(),
			data: Vec::from_fn(rust_vec.len(),
				|s| rust_vec[s].to_c_str().into_inner()).as_ptr()
		}
	}
}

#[no_mangle]
pub extern fn hello_world(c: *const libc::c_char) -> Cstr {
	let mut s = "Hello world (From rust). ".to_string();
	unsafe {
		let cs = CString::new(c, false);
		s = s + cs.as_str().unwrap();
		s.to_c_str().into_inner()
	}
}
<commit_msg>return const pointer DemoStruct<commit_after>#[allow(missing_copy_implementations)]
extern crate libc;
use std::c_str::CString;
use std::vec::Vec;

#[repr(C)]
pub struct DemoStruct {
	a: i32,
	b: i32
}

//just to make rustc happy, we don't actually use this.
impl Copy for DemoStruct {}

#[no_mangle]
pub extern fn get_demo_struct() -> *const DemoStruct {
	&DemoStruct{a: 0, b: 1337}
}

pub type Cstr = *const libc::c_char;

#[repr(C)]
pub struct CstrArr {
	len: u32,
	data: *const Cstr
}

#[no_mangle]
pub extern fn get_array_of_strings() -> *const CstrArr {
	let rust_vec = vec!["Hello","world","from","rust"];
	unsafe {
		&CstrArr {
			len: rust_vec.len().to_u32().unwrap(),
			data: Vec::from_fn(rust_vec.len(),
				|s| rust_vec[s].to_c_str().into_inner()).as_ptr()
		}
	}
}

#[no_mangle]
pub extern fn hello_world(c: *const libc::c_char) -> Cstr {
	let mut s = "Hello world (From rust). ".to_string();
	unsafe {
		let cs = CString::new(c, false);
		s = s + cs.as_str().unwrap();
		s.to_c_str().into_inner()
	}
}
<|endoftext|>


<commit_before>//! Provides undo-redo functionality with dynamic dispatch and automatic command merging.
//!
//! * [Record] provides a stack based undo-redo functionality.
//! * [History] provides a tree based undo-redo functionality that allows you to jump between different branches.
//! * [Queue] wraps a [Record] or [History] and provides batch queue functionality.
//! * [Checkpoint] wraps a [Record] or [History] and provides checkpoint functionality.
//! * Commands can be merged using the [`merge!`] macro or the [`merge`] method.
//!   When two commands are merged, undoing and redoing them are done in a single step.
//! * Configurable display formatting is provided when the `display` feature is enabled.
//! * Time stamps and time travel is provided when the `chrono` feature is enabled.
//!
//! [Record]: struct.Record.html
//! [History]: struct.History.html
//! [Queue]: struct.Queue.html
//! [Checkpoint]: struct.Checkpoint.html
//! [`merge!`]: macro.merge.html
//! [`merge`]: trait.Command.html#method.merge

#![doc(html_root_url = "https://docs.rs/undo/0.29.6")]
#![deny(
    bad_style,
    bare_trait_objects,
    missing_debug_implementations,
    missing_docs,
    unused_import_braces,
    unused_qualifications,
    unsafe_code,
    unstable_features
)]

mod checkpoint;
#[cfg(feature = "display")]
mod display;
mod history;
mod merge;
mod queue;
mod record;

#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};
use std::fmt;

pub use self::checkpoint::Checkpoint;
#[cfg(feature = "display")]
pub use self::display::Display;
pub use self::history::{History, HistoryBuilder};
pub use self::merge::Merged;
pub use self::queue::Queue;
pub use self::record::{Record, RecordBuilder};

/// A specialized Result type for undo-redo operations.
pub type Result<R> = std::result::Result<(), Error<R>>;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: fmt::Debug + Send + Sync {
    /// Applies the command on the receiver and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Restores the state of the receiver as it was before the command was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Reapplies the command on the receiver and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`] implementation.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.apply(receiver)
    }

    /// Used for automatic merging of commands.
    ///
    /// When commands are merged together, undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// # use std::error::Error;
    /// # use undo::{Command, Merge, Record};
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         self.0 = s.pop().ok_or("`s` is empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn merge(&self) -> Merge {
    ///         Merge::Always
    ///     }
    /// }
    ///
    /// fn main() -> undo::Result<String> {
    ///     let mut record = Record::default();
    ///     // The `a`, `b`, and `c` commands are merged.
    ///     record.apply(Add('a'))?;
    ///     record.apply(Add('b'))?;
    ///     record.apply(Add('c'))?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     Ok(())
    /// }
    /// ```
    #[inline]
    fn merge(&self) -> Merge {
        Merge::Never
    }
}

/// Base functionality for all commands.
#[cfg(feature = "display")]
pub trait Command<R>: fmt::Debug + fmt::Display + Send + Sync {
    /// Applies the command on the receiver and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Restores the state of the receiver as it was before the command was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Reapplies the command on the receiver and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`] implementation.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.apply(receiver)
    }

    /// Used for automatic merging of commands.
    ///
    /// When commands are merged together, undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// # use std::error::Error;
    /// # use undo::*;
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         self.0 = s.pop().ok_or("`s` is empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn merge(&self) -> Merge {
    ///         Merge::Always
    ///     }
    /// }
    ///
    /// fn main() -> Result<(), Box<dyn Error>> {
    ///     let mut record = Record::default();
    ///     // The `a`, `b`, and `c` commands are merged.
    ///     record.apply(Add('a'))?;
    ///     record.apply(Add('b'))?;
    ///     record.apply(Add('c'))?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     Ok(())
    /// }
    /// ```
    #[inline]
    fn merge(&self) -> Merge {
        Merge::Never
    }
}

/// The signal sent when the record, the history, or the receiver changes.
///
/// When one of these states changes, they will send a corresponding signal to the user.
/// For example, if the record can no longer redo any commands, it sends a `Redo(false)`
/// signal to tell the user.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub enum Signal {
    /// Says if the record can undo.
    ///
    /// This signal will be emitted when the records ability to undo changes.
    Undo(bool),
    /// Says if the record can redo.
    ///
    /// This signal will be emitted when the records ability to redo changes.
    Redo(bool),
    /// Says if the receiver is in a saved state.
    ///
    /// This signal will be emitted when the record enters or leaves its receivers saved state.
    Saved(bool),
    /// Says if the current command has changed.
    ///
    /// This signal will be emitted when the cursor has changed. This includes
    /// when two commands have been merged, in which case `old == new`.
    Cursor {
        /// The old cursor.
        old: usize,
        /// The new cursor.
        new: usize,
    },
    /// Says if the current branch, or root, has changed.
    ///
    /// This is only emitted from `History`.
    Root {
        /// The old root.
        old: usize,
        /// The new root.
        new: usize,
    },
}

/// Says if the command should merge with another command.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub enum Merge {
    /// Always merges.
    Always,
    /// Merges if the two commands have the same value.
    If(u32),
    /// Never merges.
    Never,
}

/// A position in a history tree.
#[derive(Copy, Clone, Debug, Default, Hash, Ord, PartialOrd, Eq, PartialEq)]
struct At {
    branch: usize,
    cursor: usize,
}

struct Meta<R> {
    command: Box<dyn Command<R> + 'static>,
    #[cfg(feature = "chrono")]
    timestamp: DateTime<Utc>,
}

impl<R> Meta<R> {
    #[inline]
    fn new(command: impl Command<R> + 'static) -> Meta<R> {
        Meta {
            command: Box::new(command),
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<R> From<Box<dyn Command<R> + 'static>> for Meta<R> {
    #[inline]
    fn from(command: Box<dyn Command<R> + 'static>) -> Self {
        Meta {
            command,
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<R> Command<R> for Meta<R> {
    #[inline]
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.apply(receiver)
    }

    #[inline]
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.undo(receiver)
    }

    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.redo(receiver)
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.command.merge()
    }
}

impl<R> fmt::Debug for Meta<R> {
    #[inline]
    #[cfg(not(feature = "chrono"))]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Meta")
            .field("command", &self.command)
            .finish()
    }

    #[inline]
    #[cfg(feature = "chrono")]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Meta")
            .field("command", &self.command)
            .field("timestamp", &self.timestamp)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Meta<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.command as &dyn fmt::Display).fmt(f)
    }
}

/// An error which holds the command that caused it.
pub struct Error<R> {
    meta: Meta<R>,
    error: Box<dyn std::error::Error + Send + Sync>,
}

impl<R> Error<R> {
    /// Returns a new error.
    #[inline]
    fn new(meta: Meta<R>, error: Box<dyn std::error::Error + Send + Sync>) -> Error<R> {
        Error { meta, error }
    }
}

impl<R> Error<R> {
    /// Returns a reference to the command that caused the error.
    #[inline]
    pub fn command(&self) -> &impl Command<R> {
        &self.meta
    }

    /// Returns the command that caused the error.
    #[inline]
    pub fn into_command(self) -> impl Command<R> {
        self.meta
    }
}

impl<R> fmt::Debug for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("meta", &self.meta)
            .field("error", &self.error)
            .finish()
    }
}

#[cfg(not(feature = "display"))]
impl<R> fmt::Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.error as &dyn fmt::Display).fmt(f)
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "`{error}` caused by `{command}`",
            error = self.error,
            command = self.meta
        )
    }
}

impl<R> std::error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.error.description()
    }

    #[inline]
    fn cause(&self) -> Option<&dyn std::error::Error> {
        self.error.cause()
    }
}
<commit_msg>Add example for Signal<commit_after>//! Provides undo-redo functionality with dynamic dispatch and automatic command merging.
//!
//! * [Record] provides a stack based undo-redo functionality.
//! * [History] provides a tree based undo-redo functionality that allows you to jump between different branches.
//! * [Queue] wraps a [Record] or [History] and provides batch queue functionality.
//! * [Checkpoint] wraps a [Record] or [History] and provides checkpoint functionality.
//! * Commands can be merged using the [`merge!`] macro or the [`merge`] method.
//!   When two commands are merged, undoing and redoing them are done in a single step.
//! * Configurable display formatting is provided when the `display` feature is enabled.
//! * Time stamps and time travel is provided when the `chrono` feature is enabled.
//!
//! [Record]: struct.Record.html
//! [History]: struct.History.html
//! [Queue]: struct.Queue.html
//! [Checkpoint]: struct.Checkpoint.html
//! [`merge!`]: macro.merge.html
//! [`merge`]: trait.Command.html#method.merge

#![doc(html_root_url = "https://docs.rs/undo/0.29.6")]
#![deny(
    bad_style,
    bare_trait_objects,
    missing_debug_implementations,
    missing_docs,
    unused_import_braces,
    unused_qualifications,
    unsafe_code,
    unstable_features
)]

mod checkpoint;
#[cfg(feature = "display")]
mod display;
mod history;
mod merge;
mod queue;
mod record;

#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};
use std::fmt;

pub use self::checkpoint::Checkpoint;
#[cfg(feature = "display")]
pub use self::display::Display;
pub use self::history::{History, HistoryBuilder};
pub use self::merge::Merged;
pub use self::queue::Queue;
pub use self::record::{Record, RecordBuilder};

/// A specialized Result type for undo-redo operations.
pub type Result<R> = std::result::Result<(), Error<R>>;

/// Base functionality for all commands.
#[cfg(not(feature = "display"))]
pub trait Command<R>: fmt::Debug + Send + Sync {
    /// Applies the command on the receiver and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Restores the state of the receiver as it was before the command was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Reapplies the command on the receiver and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`] implementation.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.apply(receiver)
    }

    /// Used for automatic merging of commands.
    ///
    /// When commands are merged together, undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// # use std::error::Error;
    /// # use undo::{Command, Merge, Record};
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         self.0 = s.pop().ok_or("`s` is empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn merge(&self) -> Merge {
    ///         Merge::Always
    ///     }
    /// }
    ///
    /// fn main() -> undo::Result<String> {
    ///     let mut record = Record::default();
    ///     // The `a`, `b`, and `c` commands are merged.
    ///     record.apply(Add('a'))?;
    ///     record.apply(Add('b'))?;
    ///     record.apply(Add('c'))?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     Ok(())
    /// }
    /// ```
    #[inline]
    fn merge(&self) -> Merge {
        Merge::Never
    }
}

/// Base functionality for all commands.
#[cfg(feature = "display")]
pub trait Command<R>: fmt::Debug + fmt::Display + Send + Sync {
    /// Applies the command on the receiver and returns `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Restores the state of the receiver as it was before the command was applied
    /// and returns `Ok` if everything went fine, and `Err` if something went wrong.
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>;

    /// Reapplies the command on the receiver and return `Ok` if everything went fine,
    /// and `Err` if something went wrong.
    ///
    /// The default implementation uses the [`apply`] implementation.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.apply(receiver)
    }

    /// Used for automatic merging of commands.
    ///
    /// When commands are merged together, undoing and redoing them are done in one step.
    ///
    /// # Examples
    /// ```
    /// # use std::error::Error;
    /// # use undo::*;
    /// #[derive(Debug)]
    /// struct Add(char);
    ///
    /// impl Command<String> for Add {
    ///     fn apply(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         s.push(self.0);
    ///         Ok(())
    ///     }
    ///
    ///     fn undo(&mut self, s: &mut String) -> Result<(), Box<dyn Error + Send + Sync>> {
    ///         self.0 = s.pop().ok_or("`s` is empty")?;
    ///         Ok(())
    ///     }
    ///
    ///     fn merge(&self) -> Merge {
    ///         Merge::Always
    ///     }
    /// }
    ///
    /// fn main() -> Result<(), Box<dyn Error>> {
    ///     let mut record = Record::default();
    ///     // The `a`, `b`, and `c` commands are merged.
    ///     record.apply(Add('a'))?;
    ///     record.apply(Add('b'))?;
    ///     record.apply(Add('c'))?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     // Calling `undo` once will undo all merged commands.
    ///     record.undo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "");
    ///     // Calling `redo` once will redo all merged commands.
    ///     record.redo().unwrap()?;
    ///     assert_eq!(record.as_receiver(), "abc");
    ///     Ok(())
    /// }
    /// ```
    #[inline]
    fn merge(&self) -> Merge {
        Merge::Never
    }
}

/// The signal sent when the record, the history, or the receiver changes.
///
/// When one of these states changes, they will send a corresponding signal to the user.
/// For example, if the record can no longer redo any commands, it sends a `Redo(false)`
/// signal to tell the user.
///
/// # Examples
/// ```
/// # use undo::{Record, Signal};
/// # fn foo() -> Record<String> {
/// let record = Record::builder()
///     .connect(|signal| match signal {
///         Signal::Undo(on) => println!("undo: {}", on),
///         Signal::Redo(on) => println!("redo: {}", on),
///         Signal::Saved(on) => println!("saved: {}", on),
///         Signal::Cursor { old, new } => println!("cursor: {} -> {}", old, new),
///         Signal::Root { old, new } => println!("root: {} -> {}", old, new),
///     })
///     .default();
/// # record
/// # }
/// ```
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub enum Signal {
    /// Says if the record can undo.
    ///
    /// This signal will be emitted when the records ability to undo changes.
    Undo(bool),
    /// Says if the record can redo.
    ///
    /// This signal will be emitted when the records ability to redo changes.
    Redo(bool),
    /// Says if the receiver is in a saved state.
    ///
    /// This signal will be emitted when the record enters or leaves its receivers saved state.
    Saved(bool),
    /// Says if the current command has changed.
    ///
    /// This signal will be emitted when the cursor has changed. This includes
    /// when two commands have been merged, in which case `old == new`.
    Cursor {
        /// The old cursor.
        old: usize,
        /// The new cursor.
        new: usize,
    },
    /// Says if the current branch, or root, has changed.
    ///
    /// This is only emitted from `History`.
    Root {
        /// The old root.
        old: usize,
        /// The new root.
        new: usize,
    },
}

/// Says if the command should merge with another command.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub enum Merge {
    /// Always merges.
    Always,
    /// Merges if the two commands have the same value.
    If(u32),
    /// Never merges.
    Never,
}

/// A position in a history tree.
#[derive(Copy, Clone, Debug, Default, Hash, Ord, PartialOrd, Eq, PartialEq)]
struct At {
    branch: usize,
    cursor: usize,
}

struct Meta<R> {
    command: Box<dyn Command<R> + 'static>,
    #[cfg(feature = "chrono")]
    timestamp: DateTime<Utc>,
}

impl<R> Meta<R> {
    #[inline]
    fn new(command: impl Command<R> + 'static) -> Meta<R> {
        Meta {
            command: Box::new(command),
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<R> From<Box<dyn Command<R> + 'static>> for Meta<R> {
    #[inline]
    fn from(command: Box<dyn Command<R> + 'static>) -> Self {
        Meta {
            command,
            #[cfg(feature = "chrono")]
            timestamp: Utc::now(),
        }
    }
}

impl<R> Command<R> for Meta<R> {
    #[inline]
    fn apply(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.apply(receiver)
    }

    #[inline]
    fn undo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.undo(receiver)
    }

    #[inline]
    fn redo(
        &mut self,
        receiver: &mut R,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        self.command.redo(receiver)
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.command.merge()
    }
}

impl<R> fmt::Debug for Meta<R> {
    #[inline]
    #[cfg(not(feature = "chrono"))]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Meta")
            .field("command", &self.command)
            .finish()
    }

    #[inline]
    #[cfg(feature = "chrono")]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Meta")
            .field("command", &self.command)
            .field("timestamp", &self.timestamp)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Meta<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.command as &dyn fmt::Display).fmt(f)
    }
}

/// An error which holds the command that caused it.
pub struct Error<R> {
    meta: Meta<R>,
    error: Box<dyn std::error::Error + Send + Sync>,
}

impl<R> Error<R> {
    /// Returns a new error.
    #[inline]
    fn new(meta: Meta<R>, error: Box<dyn std::error::Error + Send + Sync>) -> Error<R> {
        Error { meta, error }
    }
}

impl<R> Error<R> {
    /// Returns a reference to the command that caused the error.
    #[inline]
    pub fn command(&self) -> &impl Command<R> {
        &self.meta
    }

    /// Returns the command that caused the error.
    #[inline]
    pub fn into_command(self) -> impl Command<R> {
        self.meta
    }
}

impl<R> fmt::Debug for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("meta", &self.meta)
            .field("error", &self.error)
            .finish()
    }
}

#[cfg(not(feature = "display"))]
impl<R> fmt::Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (&self.error as &dyn fmt::Display).fmt(f)
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Error<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "`{error}` caused by `{command}`",
            error = self.error,
            command = self.meta
        )
    }
}

impl<R> std::error::Error for Error<R> {
    #[inline]
    fn description(&self) -> &str {
        self.error.description()
    }

    #[inline]
    fn cause(&self) -> Option<&dyn std::error::Error> {
        self.error.cause()
    }
}
<|endoftext|>


<commit_before>//! Idiomatic and safe APIs for interacting with the
//! [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/).

#![cfg_attr(test, feature(test))]

extern crate libc;
extern crate lmdb_sys as ffi;

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate tempdir;
#[cfg(test)] extern crate test;
#[macro_use] extern crate bitflags;

pub use cursor::{
    Cursor,
    RoCursor,
    RwCursor
};
pub use database::Database;
pub use environment::{Environment, EnvironmentBuilder};
pub use error::{Error, Result};
pub use flags::*;
pub use transaction::{
    InactiveTransaction,
    RoTransaction,
    RwTransaction,
    Transaction,
};

macro_rules! lmdb_try {
    ($expr:expr) => ({
        match $expr {
            ::ffi::MDB_SUCCESS => (),
            err_code => return Err(::Error::from_err_code(err_code)),
        }
    })
}

macro_rules! lmdb_try_with_cleanup {
    ($expr:expr, $cleanup:expr) => ({
        match $expr {
            ::ffi::MDB_SUCCESS => (),
            err_code => {
                let _ = $cleanup;
                return Err(::Error::from_err_code(err_code))
            },
        }
    })
}

mod flags;
mod cursor;
mod database;
mod environment;
mod error;
mod transaction;

#[cfg(test)]
mod test_utils {

    use tempdir::TempDir;

    use super::*;

    pub fn get_key(n: u32) -> String {
        format!("key{}", n)
    }

    pub fn get_data(n: u32) -> String {
        format!("data{}", n)
    }

    pub fn setup_bench_db<'a>(num_rows: u32) -> (TempDir, Environment) {
        let dir = TempDir::new("test").unwrap();
        let env = Environment::new().open(dir.path()).unwrap();

        {
            let db = env.open_db(None).unwrap();
            let mut txn = env.begin_rw_txn().unwrap();
            for i in 0..num_rows {
                txn.put(db, &get_key(i), &get_data(i), WriteFlags::empty()).unwrap();
            }
            txn.commit().unwrap();
        }
        (dir, env)
    }
}
<commit_msg>Expose lmdb::Iter publicly (#8)<commit_after>//! Idiomatic and safe APIs for interacting with the
//! [Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/).

#![cfg_attr(test, feature(test))]

extern crate libc;
extern crate lmdb_sys as ffi;

#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate tempdir;
#[cfg(test)] extern crate test;
#[macro_use] extern crate bitflags;

pub use cursor::{
    Cursor,
    RoCursor,
    RwCursor,
    Iter
};
pub use database::Database;
pub use environment::{Environment, EnvironmentBuilder};
pub use error::{Error, Result};
pub use flags::*;
pub use transaction::{
    InactiveTransaction,
    RoTransaction,
    RwTransaction,
    Transaction,
};

macro_rules! lmdb_try {
    ($expr:expr) => ({
        match $expr {
            ::ffi::MDB_SUCCESS => (),
            err_code => return Err(::Error::from_err_code(err_code)),
        }
    })
}

macro_rules! lmdb_try_with_cleanup {
    ($expr:expr, $cleanup:expr) => ({
        match $expr {
            ::ffi::MDB_SUCCESS => (),
            err_code => {
                let _ = $cleanup;
                return Err(::Error::from_err_code(err_code))
            },
        }
    })
}

mod flags;
mod cursor;
mod database;
mod environment;
mod error;
mod transaction;

#[cfg(test)]
mod test_utils {

    use tempdir::TempDir;

    use super::*;

    pub fn get_key(n: u32) -> String {
        format!("key{}", n)
    }

    pub fn get_data(n: u32) -> String {
        format!("data{}", n)
    }

    pub fn setup_bench_db<'a>(num_rows: u32) -> (TempDir, Environment) {
        let dir = TempDir::new("test").unwrap();
        let env = Environment::new().open(dir.path()).unwrap();

        {
            let db = env.open_db(None).unwrap();
            let mut txn = env.begin_rw_txn().unwrap();
            for i in 0..num_rows {
                txn.put(db, &get_key(i), &get_data(i), WriteFlags::empty()).unwrap();
            }
            txn.commit().unwrap();
        }
        (dir, env)
    }
}
<|endoftext|>


<commit_before>/// Extend `Option` with a fallible map method
///
/// This is useful for mapping fallible operations (i.e. operations that)
/// return `Result`, over an optional type. The result will be
/// `Result<Option<U>>`, which makes it easy to handle the errors that
/// originate from inside the closure that's being mapped.
///
/// # Type parameters
///
/// - `T`: The input `Option`'s value type
/// - `U`: The outputs `Option`'s value type
/// - `E`: The possible error during the mapping
pub trait FallibleMapExt<T, U, E> {

    /// Try to apply a fallible map function to the option
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>;

}

// Implementions

impl<T, U, E> FallibleMapExt<T, U, E> for Option<T> {
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>
    {
        match self {
            Some(x) => f(x).map(Some),
            None => Ok(None),
        }
    }
}

/// Extend `Option<Result<T>>` and Vec<Result<T>> with a `flip` method that scavenges the inner `Result`
/// type and brings it to the outernmost type for easy error handling.
///
/// This makes easy to `map`, `and_then` etc. with fallible (`Result`-returning)
/// functions over `Option` and then call `flip` to "surface" the `Result` for error handling.
///
/// # Type parameters
///
/// - `T`: The inner value type
/// - `E`: The error type of `Result`
pub trait FlipResultExt<T, E> {
    type InnerType;

    fn flip(self) -> Result<Self::InnerType, E>;
}

impl<T, E> FlipResultExt<T, E> for Option<Result<T, E>> {
    type InnerType = Option<T>;
    fn flip(self) -> Result<Option<T>, E>
    {
        match self {
            Some(r) => r.map(Some),
            None => Ok(None),
        }
    }
}

impl<T, E> FlipResultExt<T, E> for Vec<Result<T, E>> {
    type InnerType = Vec<T>;
    fn flip(self) -> Result<Vec<T>, E>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Ok(u) => result_vec.push(u),
                Err(e) => return Err(e),
            }
        }
        Ok(result_vec)
    }
}

#[cfg(test)]
mod tests {
    use FallibleMapExt;
    use FlipResultExt;

    #[test]
    fn test_try_map_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_try_map_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_try_map_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh foes") } else { Ok(x + 1) })?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_flip_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh foes") } else { Ok(x + 1) }).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_vec_1() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| Ok(x + 1)).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(vec![43, 101, 100, 2, 43, 10001]));
    }

    #[test]
    fn test_flip_vec_2() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| if true { Err("heatenings") } else { Ok(x + 1) }).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("heatenings"));
    }
}
<commit_msg>Implemented flip for Vec<Option<T>><commit_after>/// Extend `Option` with a fallible map method
///
/// This is useful for mapping fallible operations (i.e. operations that)
/// return `Result`, over an optional type. The result will be
/// `Result<Option<U>>`, which makes it easy to handle the errors that
/// originate from inside the closure that's being mapped.
///
/// # Type parameters
///
/// - `T`: The input `Option`'s value type
/// - `U`: The outputs `Option`'s value type
/// - `E`: The possible error during the mapping
pub trait FallibleMapExt<T, U, E> {

    /// Try to apply a fallible map function to the option
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>;

}

// Implementions

impl<T, U, E> FallibleMapExt<T, U, E> for Option<T> {
    fn try_map<F>(self, f: F) -> Result<Option<U>, E> where
        F: FnOnce(T) -> Result<U, E>
    {
        match self {
            Some(x) => f(x).map(Some),
            None => Ok(None),
        }
    }
}

/// Extend `Option<Result<T>>` and Vec<Result<T>> with a `flip` method that scavenges the inner `Result`
/// type and brings it to the outernmost type for easy error handling.
///
/// This makes easy to `map`, `and_then` etc. with fallible (`Result`-returning)
/// functions over `Option` and then call `flip` to "surface" the `Result` for error handling.
///
/// # Type parameters
///
/// - `T`: The inner value type
/// - `E`: The error type of `Result`
pub trait FlipResultExt<T, E> {
    type ReturnType;

    fn flip(self) -> Self::ReturnType;
}

impl<T, E> FlipResultExt<T, E> for Option<Result<T, E>> {
    type ReturnType = Result<Option<T>, E>;

    fn flip(self) -> Result<Option<T>, E>
    {
        match self {
            Some(r) => r.map(Some),
            None => Ok(None),
        }
    }
}

impl<T, E> FlipResultExt<T, E> for Vec<Result<T, E>> {
    type ReturnType = Result<Vec<T>, E>;
    fn flip(self) -> Result<Vec<T>, E>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Ok(u) => result_vec.push(u),
                Err(e) => return Err(e),
            }
        }
        Ok(result_vec)
    }
}

impl<T, E> FlipResultExt<T, E> for Vec<Option<T>> {
    type ReturnType = Option<Vec<T>>;
    fn flip(self) -> Option<Vec<T>>
    {
        let mut result_vec = Vec::with_capacity(self.len());
        for t in self {
            match t {
                Some(u) => result_vec.push(u),
                None => return None,
            }
        }
        Some(result_vec)
    }
}

#[cfg(test)]
mod tests {
    use FallibleMapExt;
    use FlipResultExt;

    #[test]
    fn test_try_map_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_try_map_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_try_map_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh noes") } else { Ok(x + 1) })?
                .try_map(|x| Ok(x + 1))?
                .try_map(|x| if true { Err("oh foes") } else { Ok(x + 1) })?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_1() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_2() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(Some(45)));
    }

    #[test]
    fn test_flip_3() {
        fn inner() -> Result<Option<i32>, &'static str> {
            let x = Some(42)
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh noes") } else { Ok(x + 1) }).flip()?
                .map(|x| Ok(x + 1)).flip()?
                .map(|x| if true { Err("oh foes") } else { Ok(x + 1) }).flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("oh noes"));
    }

    #[test]
    fn test_flip_vec_1() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| Ok(x + 1)).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Ok(vec![43, 101, 100, 2, 43, 10001]));
    }

    #[test]
    fn test_flip_vec_2() {
        fn inner() -> Result<Vec<i32>, &'static str> {
            let x = vec![42, 100, 99, 1, 42, 10000]
                .into_iter().map(|x| if true { Err("heatenings") } else { Ok(x + 1) }).collect::<Vec<_>>().flip()?;

            Ok(x)
        }
        assert_eq!(inner(), Err("heatenings"));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.
//!
//! # Example
//!
//!```
//! extern crate gj;
//! extern crate gjio;
//! use gj::{EventLoop, Promise};
//! use gjio::{AsyncRead, AsyncWrite, Slice};
//!
//! fn echo(mut stream: gjio::SocketStream, buf: Vec<u8>) -> Promise<(), ::std::io::Error> {
//!     stream.try_read(buf, 1).lift().then(move |(buf, n)| {
//!         if n == 0 { // EOF
//!             Promise::ok(())
//!         } else {
//!             stream.write(Slice::new(buf, n)).then(move |slice| {
//!                 echo(stream, slice.buf)
//!             })
//!         }
//!     })
//! }
//!
//! fn main() {
//!     EventLoop::top_level(|wait_scope| -> Result<(), ::std::io::Error> {
//!         let mut event_port = try!(gjio::EventPort::new());
//!         //let (stream1, stream2) = try!(unix::Stream::new_pair());
//!         //let promise1 = echo(stream1, vec![0; 5]); // Tiny buffer just to be difficult.
//!         //let promise2 = stream2.write(b"hello world").lift().then(|(stream, _)| {
//!         //    stream.read(vec![0; 11], 11).map(|(_, buf, _)| {
//!         //        assert_eq!(buf, b"hello world");
//!         //        Ok(())
//!         //    }).lift()
//!         //});
//!         //try!(Promise::all(vec![promise1, promise2].into_iter()).wait(wait_scope));
//!         Ok(())
//!     }).expect("top level");
//! }
//!```

#[macro_use] extern crate gj;
extern crate time;

extern crate nix;
extern crate miow;

use std::cell::{RefCell};
use std::rc::Rc;
use std::collections::BinaryHeap;
use gj::{Promise, PromiseFulfiller};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait AsyncRead {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        self.try_read(buf, min_bytes).map(move |(buf, n)| {
            if n < min_bytes {
                Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
            } else {
                Ok((buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

pub struct Slice<T> where T: AsRef<[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: AsRef<[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> AsRef<[u8]> for Slice<T> where T: AsRef<[u8]> {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf.as_ref()[0..self.end]
    }
}

#[cfg(unix)]
type RawDescriptor = ::std::os::unix::io::RawFd;

#[cfg(unix)]
type SocketAddressInner = sys::unix::SocketAddressInner;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
    timer_inner: Rc<RefCell<TimerInner>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
            timer_inner: Rc::new(RefCell::new(TimerInner::new())),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }

    pub fn get_timer(&self) -> Timer {
        Timer::new(self.timer_inner.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        let timeout = self.timer_inner.borrow_mut().get_wait_timeout();

        try!(self.reactor.borrow_mut().run_once(timeout));

        self.timer_inner.borrow_mut().update_current_time();
        self.timer_inner.borrow_mut().process();

        Ok(())
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    pub fn get_tcp_address(&self, addr: ::std::net::SocketAddr) -> SocketAddress {
        SocketAddress::new(SocketAddressInner::new_tcp(self.reactor.clone(), addr))
    }

    #[cfg(unix)]
    pub fn get_unix_address<P: AsRef<::std::path::Path>>(&self, addr: P)
                            -> Result<SocketAddress, ::std::io::Error>
    {
        Ok(SocketAddress::new(try!(SocketAddressInner::new_unix(self.reactor.clone(), addr))))
    }
}

#[cfg(unix)]
type SocketListenerInner = sys::unix::SocketListenerInner;

pub struct SocketAddress {
    inner: SocketAddressInner,
}

impl SocketAddress {
    fn new(inner: SocketAddressInner) -> SocketAddress {
        SocketAddress { inner: inner }
    }

    pub fn connect(&self) -> Promise<SocketStream, ::std::io::Error>
    {
        self.inner.connect().map(|s| Ok(SocketStream::new(s)))
    }

    pub fn listen(&mut self) -> Result<SocketListener, ::std::io::Error>
    {
        Ok(SocketListener::new(try!(self.inner.listen())))
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl Clone for SocketListener {
    fn clone(&self) -> SocketListener {
        SocketListener { inner: self.inner.clone() }
    }
}

impl SocketListener {
    fn new(inner: SocketListenerInner) -> SocketListener {
        SocketListener { inner: Rc::new(RefCell::new(inner)) }
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().queue.take();
        let promise = match maybe_queue {
            None => SocketListenerInner::accept_internal(inner2),
            Some(queue) => {
                queue.then_else(move |_| SocketListenerInner::accept_internal(inner2) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().queue = Some(p);

        promise.map(move |inner| {
            f.resolve(Ok(()));
            Ok(SocketStream::new(inner))
        })
    }
}

#[cfg(unix)]
type SocketStreamInner = sys::unix::SocketStreamInner;

pub struct SocketStream {
    inner: Rc<RefCell<SocketStreamInner>>,
}

impl Clone for SocketStream {
    fn clone(&self) -> SocketStream {
        SocketStream { inner: self.inner.clone() }
    }
}

impl SocketStream {
    fn new(inner: SocketStreamInner) -> SocketStream {
        SocketStream { inner: Rc::new(RefCell::new(inner)) }
    }
}

impl AsyncRead for SocketStream {
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().read_queue.take();
        let promise = match maybe_queue {
            None => SocketStreamInner::try_read_internal(inner2, buf, 0, min_bytes),
            Some(queue) => {
                queue.then_else(move |_| SocketStreamInner::try_read_internal(inner2, buf, 0, min_bytes) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().read_queue = Some(p);

        promise.map_else(move |r| {
            f.resolve(Ok(()));
            r
        })
    }
}

impl AsyncWrite for SocketStream {
    fn write<T>(&mut self, buf: T) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().write_queue.take();
        let promise = match maybe_queue {
            None => SocketStreamInner::write_internal(inner2, buf, 0),
            Some(queue) => {
                queue.then_else(move |_| SocketStreamInner::write_internal(inner2, buf, 0) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().write_queue = Some(p);

        promise.map_else(move |r| {
            f.resolve(Ok(()));
            r
        })
    }
}

struct AtTimeFulfiller {
    time: ::time::SteadyTime,
    fulfiller: PromiseFulfiller<(), ::std::io::Error>,
}

impl ::std::cmp::PartialEq for AtTimeFulfiller {
    fn eq(&self, other: &AtTimeFulfiller) -> bool {
        self.time == other.time
    }
}

impl ::std::cmp::Eq for AtTimeFulfiller {}

impl ::std::cmp::Ord for AtTimeFulfiller {
    fn cmp(&self, other: &AtTimeFulfiller) -> ::std::cmp::Ordering {
        if self.time > other.time { ::std::cmp::Ordering::Less }
        else if self.time < other.time { ::std::cmp::Ordering::Greater }
        else { ::std::cmp::Ordering::Equal }
    }
}

impl ::std::cmp::PartialOrd for AtTimeFulfiller {
    fn partial_cmp(&self, other: &AtTimeFulfiller) -> Option<::std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

struct TimerInner {
    heap: BinaryHeap<AtTimeFulfiller>,
    frozen_steady_time: ::time::SteadyTime,
}

impl TimerInner {
    fn new() -> TimerInner {
        TimerInner {
            heap: BinaryHeap::new(),
            frozen_steady_time: ::time::SteadyTime::now(),
        }
    }

    fn update_current_time(&mut self) {
        self.frozen_steady_time = ::time::SteadyTime::now();
    }

    fn get_wait_timeout(&self) -> Option<::time::Duration> {
        match self.heap.peek() {
            None => None,
            Some(ref at_time_fulfiller) => {
                Some(at_time_fulfiller.time - self.frozen_steady_time +
                     ::time::Duration::milliseconds(1))
            }
        }
    }

    fn process(&mut self) {
        loop {
            match self.heap.peek() {
                None => return,
                Some(ref at_time_fulfiller) => {
                    if at_time_fulfiller.time > self.frozen_steady_time {
                        return;
                    }
                }
            }

            match self.heap.pop() {
                None => unreachable!(),
                Some(AtTimeFulfiller { time : _, fulfiller }) => {
                    fulfiller.fulfill(());
                }
            }
        }
    }
}

pub struct Timer {
    inner: Rc<RefCell<TimerInner>>,
}

impl Timer {
    fn new(inner: Rc<RefCell<TimerInner>>) -> Timer {
        Timer { inner: inner }
    }

    pub fn after_delay(&self, delay: ::std::time::Duration) -> Promise<(), ::std::io::Error> {
        let delay = match ::time::Duration::from_std(delay) {
            Ok(d) => d,
            Err(e) => return Promise::err(
                ::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))),
        };
        let time = self.inner.borrow().frozen_steady_time + delay;
        let (p, f) = Promise::and_fulfiller();

        self.inner.borrow_mut().heap.push(AtTimeFulfiller { time: time, fulfiller: f });

        p
    }

   pub fn timeout_after<T>(&self, delay: ::std::time::Duration,
                            promise: Promise<T, ::std::io::Error>) -> Promise<T, ::std::io::Error>
    {
        promise.exclusive_join(self.after_delay(delay).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out"))
        }))
    }
}
<commit_msg>typedefs<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.
//!
//! # Example
//!
//!```
//! extern crate gj;
//! extern crate gjio;
//! use gj::{EventLoop, Promise};
//! use gjio::{AsyncRead, AsyncWrite, Slice};
//!
//! fn echo(mut stream: gjio::SocketStream, buf: Vec<u8>) -> Promise<(), ::std::io::Error> {
//!     stream.try_read(buf, 1).lift().then(move |(buf, n)| {
//!         if n == 0 { // EOF
//!             Promise::ok(())
//!         } else {
//!             stream.write(Slice::new(buf, n)).then(move |slice| {
//!                 echo(stream, slice.buf)
//!             })
//!         }
//!     })
//! }
//!
//! fn main() {
//!     EventLoop::top_level(|wait_scope| -> Result<(), ::std::io::Error> {
//!         let mut event_port = try!(gjio::EventPort::new());
//!         //let (stream1, stream2) = try!(unix::Stream::new_pair());
//!         //let promise1 = echo(stream1, vec![0; 5]); // Tiny buffer just to be difficult.
//!         //let promise2 = stream2.write(b"hello world").lift().then(|(stream, _)| {
//!         //    stream.read(vec![0; 11], 11).map(|(_, buf, _)| {
//!         //        assert_eq!(buf, b"hello world");
//!         //        Ok(())
//!         //    }).lift()
//!         //});
//!         //try!(Promise::all(vec![promise1, promise2].into_iter()).wait(wait_scope));
//!         Ok(())
//!     }).expect("top level");
//! }
//!```

#[macro_use] extern crate gj;
extern crate time;

extern crate nix;
extern crate miow;

use std::cell::{RefCell};
use std::rc::Rc;
use std::collections::BinaryHeap;
use gj::{Promise, PromiseFulfiller};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait AsyncRead {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        self.try_read(buf, min_bytes).map(move |(buf, n)| {
            if n < min_bytes {
                Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
            } else {
                Ok((buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

pub struct Slice<T> where T: AsRef<[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: AsRef<[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> AsRef<[u8]> for Slice<T> where T: AsRef<[u8]> {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf.as_ref()[0..self.end]
    }
}

#[cfg(unix)]
type RawDescriptor = ::std::os::unix::io::RawFd;

#[cfg(unix)]
type SocketAddressInner = sys::unix::SocketAddressInner;

#[cfg(target_os = "windows")]
type SocketAddressInner = sys::windows::SocketAddressInner;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
    timer_inner: Rc<RefCell<TimerInner>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
            timer_inner: Rc::new(RefCell::new(TimerInner::new())),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }

    pub fn get_timer(&self) -> Timer {
        Timer::new(self.timer_inner.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        let timeout = self.timer_inner.borrow_mut().get_wait_timeout();

        try!(self.reactor.borrow_mut().run_once(timeout));

        self.timer_inner.borrow_mut().update_current_time();
        self.timer_inner.borrow_mut().process();

        Ok(())
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    pub fn get_tcp_address(&self, addr: ::std::net::SocketAddr) -> SocketAddress {
        SocketAddress::new(SocketAddressInner::new_tcp(self.reactor.clone(), addr))
    }

    #[cfg(unix)]
    pub fn get_unix_address<P: AsRef<::std::path::Path>>(&self, addr: P)
                            -> Result<SocketAddress, ::std::io::Error>
    {
        Ok(SocketAddress::new(try!(SocketAddressInner::new_unix(self.reactor.clone(), addr))))
    }
}

#[cfg(unix)]
type SocketListenerInner = sys::unix::SocketListenerInner;

#[cfg(target_os = "windows")]
type SocketListenerInner = sys::windows::SocketListenerInner;

pub struct SocketAddress {
    inner: SocketAddressInner,
}

impl SocketAddress {
    fn new(inner: SocketAddressInner) -> SocketAddress {
        SocketAddress { inner: inner }
    }

    pub fn connect(&self) -> Promise<SocketStream, ::std::io::Error>
    {
        self.inner.connect().map(|s| Ok(SocketStream::new(s)))
    }

    pub fn listen(&mut self) -> Result<SocketListener, ::std::io::Error>
    {
        Ok(SocketListener::new(try!(self.inner.listen())))
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl Clone for SocketListener {
    fn clone(&self) -> SocketListener {
        SocketListener { inner: self.inner.clone() }
    }
}

impl SocketListener {
    fn new(inner: SocketListenerInner) -> SocketListener {
        SocketListener { inner: Rc::new(RefCell::new(inner)) }
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().queue.take();
        let promise = match maybe_queue {
            None => SocketListenerInner::accept_internal(inner2),
            Some(queue) => {
                queue.then_else(move |_| SocketListenerInner::accept_internal(inner2) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().queue = Some(p);

        promise.map(move |inner| {
            f.resolve(Ok(()));
            Ok(SocketStream::new(inner))
        })
    }
}

#[cfg(unix)]
type SocketStreamInner = sys::unix::SocketStreamInner;

#[cfg(target_os = "windows")]
type SocketStreamInner = sys::windows::SocketStreamInner;

pub struct SocketStream {
    inner: Rc<RefCell<SocketStreamInner>>,
}

impl Clone for SocketStream {
    fn clone(&self) -> SocketStream {
        SocketStream { inner: self.inner.clone() }
    }
}

impl SocketStream {
    fn new(inner: SocketStreamInner) -> SocketStream {
        SocketStream { inner: Rc::new(RefCell::new(inner)) }
    }
}

impl AsyncRead for SocketStream {
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().read_queue.take();
        let promise = match maybe_queue {
            None => SocketStreamInner::try_read_internal(inner2, buf, 0, min_bytes),
            Some(queue) => {
                queue.then_else(move |_| SocketStreamInner::try_read_internal(inner2, buf, 0, min_bytes) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().read_queue = Some(p);

        promise.map_else(move |r| {
            f.resolve(Ok(()));
            r
        })
    }
}

impl AsyncWrite for SocketStream {
    fn write<T>(&mut self, buf: T) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().write_queue.take();
        let promise = match maybe_queue {
            None => SocketStreamInner::write_internal(inner2, buf, 0),
            Some(queue) => {
                queue.then_else(move |_| SocketStreamInner::write_internal(inner2, buf, 0) )
            }
        };

        let (p, f) = Promise::and_fulfiller();
        inner.borrow_mut().write_queue = Some(p);

        promise.map_else(move |r| {
            f.resolve(Ok(()));
            r
        })
    }
}

struct AtTimeFulfiller {
    time: ::time::SteadyTime,
    fulfiller: PromiseFulfiller<(), ::std::io::Error>,
}

impl ::std::cmp::PartialEq for AtTimeFulfiller {
    fn eq(&self, other: &AtTimeFulfiller) -> bool {
        self.time == other.time
    }
}

impl ::std::cmp::Eq for AtTimeFulfiller {}

impl ::std::cmp::Ord for AtTimeFulfiller {
    fn cmp(&self, other: &AtTimeFulfiller) -> ::std::cmp::Ordering {
        if self.time > other.time { ::std::cmp::Ordering::Less }
        else if self.time < other.time { ::std::cmp::Ordering::Greater }
        else { ::std::cmp::Ordering::Equal }
    }
}

impl ::std::cmp::PartialOrd for AtTimeFulfiller {
    fn partial_cmp(&self, other: &AtTimeFulfiller) -> Option<::std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

struct TimerInner {
    heap: BinaryHeap<AtTimeFulfiller>,
    frozen_steady_time: ::time::SteadyTime,
}

impl TimerInner {
    fn new() -> TimerInner {
        TimerInner {
            heap: BinaryHeap::new(),
            frozen_steady_time: ::time::SteadyTime::now(),
        }
    }

    fn update_current_time(&mut self) {
        self.frozen_steady_time = ::time::SteadyTime::now();
    }

    fn get_wait_timeout(&self) -> Option<::time::Duration> {
        match self.heap.peek() {
            None => None,
            Some(ref at_time_fulfiller) => {
                Some(at_time_fulfiller.time - self.frozen_steady_time +
                     ::time::Duration::milliseconds(1))
            }
        }
    }

    fn process(&mut self) {
        loop {
            match self.heap.peek() {
                None => return,
                Some(ref at_time_fulfiller) => {
                    if at_time_fulfiller.time > self.frozen_steady_time {
                        return;
                    }
                }
            }

            match self.heap.pop() {
                None => unreachable!(),
                Some(AtTimeFulfiller { time : _, fulfiller }) => {
                    fulfiller.fulfill(());
                }
            }
        }
    }
}

pub struct Timer {
    inner: Rc<RefCell<TimerInner>>,
}

impl Timer {
    fn new(inner: Rc<RefCell<TimerInner>>) -> Timer {
        Timer { inner: inner }
    }

    pub fn after_delay(&self, delay: ::std::time::Duration) -> Promise<(), ::std::io::Error> {
        let delay = match ::time::Duration::from_std(delay) {
            Ok(d) => d,
            Err(e) => return Promise::err(
                ::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))),
        };
        let time = self.inner.borrow().frozen_steady_time + delay;
        let (p, f) = Promise::and_fulfiller();

        self.inner.borrow_mut().heap.push(AtTimeFulfiller { time: time, fulfiller: f });

        p
    }

   pub fn timeout_after<T>(&self, delay: ::std::time::Duration,
                            promise: Promise<T, ::std::io::Error>) -> Promise<T, ::std::io::Error>
    {
        promise.exclusive_join(self.after_delay(delay).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out"))
        }))
    }
}
<|endoftext|>