<commit_before>//! "Nlist" style symbols in this binary - beware, like most symbol tables in most binary formats, they are strippable, and should not be relied upon, see the imports and exports modules for something more permanent.
//!
//! Symbols are essentially a type, offset, and the symbol name

use scroll::{self, ctx, Pread};
use scroll::ctx::SizeWith;
use error;
use container::{self, Container};
use mach::load_command;
use core::fmt::{self, Debug};

// TODO: add/find NO_SECT value

pub const NLIST_TYPE_MASK: u8 = 0xe;
pub const NLIST_TYPE_GLOBAL: u8 = 0x1;
pub const NLIST_TYPE_LOCAL: u8 = 0x0;

#[repr(C)]
#[derive(Clone, Copy, Pread, Pwrite, SizeWith)]
pub struct Nlist32 {
    /// index into the string table
    pub n_strx: u32,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: u8,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u32,
}

pub const SIZEOF_NLIST_32: usize = 12;

impl Debug for Nlist32 {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "strx: {:04} type: {:#02x} sect: {:#x} desc: {:#03x} value: {:#x}",
               self.n_strx,
               self.n_type,
               self.n_sect,
               self.n_desc,
               self.n_value,
        )
    }
}

#[repr(C)]
#[derive(Clone, Copy, Pread, Pwrite, SizeWith)]
pub struct Nlist64 {
    /// index into the string table
    pub n_strx: u32,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: u8,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u64,
}

pub const SIZEOF_NLIST_64: usize = 16;

impl Debug for Nlist64 {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "strx: {:04} type: {:#02x} sect: {:#x} desc: {:#03x} value: {:#x}",
               self.n_strx,
               self.n_type,
               self.n_sect,
               self.n_desc,
               self.n_value,
        )
    }
}

#[derive(Debug, Clone)]
pub struct Nlist {
    /// index into the string table
    pub n_strx: usize,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: usize,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u64,
}

impl Nlist {
    /// Whether this symbol is global or not
    pub fn is_global(&self) -> bool {
        self.n_type & !NLIST_TYPE_MASK == NLIST_TYPE_GLOBAL
    }
    /// Whether this symbol is undefined or not
    pub fn is_undefined(&self) -> bool {
        self.n_sect == 0 && self.n_type & NLIST_TYPE_MASK == 0
    }
}

impl ctx::SizeWith<container::Ctx> for Nlist {
    type Units = usize;
    fn size_with(ctx: &container::Ctx) -> usize {
        use container::Container;
        match ctx.container {
            Container::Little => {
                SIZEOF_NLIST_32
            },
            Container::Big => {
                SIZEOF_NLIST_64
            },
        }
    }
}

impl From<Nlist32> for Nlist {
    fn from(nlist: Nlist32) -> Self {
        Nlist {
            n_strx: nlist.n_strx as usize,
            n_type: nlist.n_type,
            n_sect: nlist.n_sect as usize,
            n_desc: nlist.n_desc,
            n_value: nlist.n_value as u64,
        }
    }
}

impl From<Nlist64> for Nlist {
    fn from(nlist: Nlist64) -> Self {
        Nlist {
            n_strx: nlist.n_strx as usize,
            n_type: nlist.n_type,
            n_sect: nlist.n_sect as usize,
            n_desc: nlist.n_desc,
            n_value: nlist.n_value,
        }
    }
}

impl<'a> ctx::TryFromCtx<'a, container::Ctx> for Nlist {
    type Error = scroll::Error;
    type Size = usize;
    fn try_from_ctx(bytes: &'a [u8], container::Ctx { container, le }: container::Ctx) -> scroll::Result<(Self, Self::Size)> {
        let nlist = match container {
            Container::Little => {
                (bytes.pread_with::<Nlist32>(0, le)?.into(), SIZEOF_NLIST_32)
            },
            Container::Big => {
                (bytes.pread_with::<Nlist64>(0, le)?.into(), SIZEOF_NLIST_64)
            },
        };
        Ok(nlist)
    }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct SymbolsCtx {
    pub nsyms: usize,
    pub strtab: usize,
    pub ctx: container::Ctx,
}

impl<'a, T: ?Sized> ctx::TryFromCtx<'a, SymbolsCtx, T> for Symbols<'a> where T: AsRef<[u8]> {
    type Error = scroll::Error;
    type Size = usize;
    fn try_from_ctx(bytes: &'a T, SymbolsCtx {
        nsyms, strtab, ctx
    }: SymbolsCtx) -> scroll::Result<(Self, Self::Size)> {
        let data = bytes.as_ref();
        Ok ((Symbols {
            data: data,
            start: 0,
            nsyms: nsyms,
            strtab: strtab,
            ctx: ctx,
        }, data.len()))
    }
}

#[derive(Default)]
pub struct SymbolIterator<'a> {
    data: &'a [u8],
    nsyms: usize,
    offset: usize,
    count: usize,
    ctx: container::Ctx,
    strtab: usize,
}

impl<'a> Iterator for SymbolIterator<'a> {
    type Item = error::Result<(&'a str, Nlist)>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.count >= self.nsyms {
            None
        } else {
            self.count += 1;
            match self.data.gread_with::<Nlist>(&mut self.offset, self.ctx) {
                Ok(symbol) => {
                    match self.data.pread(self.strtab + symbol.n_strx) {
                        Ok(name) => {
                            Some(Ok((name, symbol)))
                        },
                        Err(e) => return Some(Err(e.into()))
                    }
                },
                Err(e) => return Some(Err(e.into()))
            }
        }
    }
}

/// A zero-copy "nlist" style symbol table ("stab"), including the string table
pub struct Symbols<'a> {
    data: &'a [u8],
    start: usize,
    nsyms: usize,
    // TODO: we can use an actual strtab here and tie it to symbols lifetime
    strtab: usize,
    ctx: container::Ctx,
}

impl<'a, 'b> IntoIterator for &'b Symbols<'a> {
    type Item = <SymbolIterator<'a> as Iterator>::Item;
    type IntoIter = SymbolIterator<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> Symbols<'a> {
    /// Creates a new symbol table with `count` elements, from the `start` offset, using the string table at `strtab`, with a _default_ ctx.
    ////
    /// **Beware**, this will provide incorrect results if you construct this on a 32-bit mach binary, using a 64-bit machine; use `parse` instead if you want 32/64 bit support
    pub fn new(bytes: &'a [u8], start: usize, count: usize, strtab: usize) -> error::Result<Symbols<'a>> {
        let nsyms = count;
        Ok (Symbols {
            data: bytes,
            start: start,
            nsyms: nsyms,
            strtab: strtab,
            ctx: container::Ctx::default(),
        })
    }
    pub fn parse(bytes: &'a [u8], symtab: &load_command::SymtabCommand, ctx: container::Ctx) -> error::Result<Symbols<'a>> {
        // we need to normalize the strtab offset before we receive the truncated bytes in pread_with
        let strtab = symtab.stroff - symtab.symoff;
        Ok(bytes.pread_with(symtab.symoff as usize, SymbolsCtx { nsyms: symtab.nsyms as usize, strtab: strtab as usize, ctx: ctx })?)
    }

    pub fn iter(&self) -> SymbolIterator<'a> {
        SymbolIterator {
            offset: self.start as usize,
            nsyms: self.nsyms as usize,
            count: 0,
            data: self.data,
            ctx: self.ctx,
            strtab: self.strtab,
        }
    }

    /// Parses a single Nlist symbol from the binary, with its accompanying name
    pub fn get(&self, index: usize) -> scroll::Result<(&'a str, Nlist)> {
        let sym: Nlist = self.data.pread_with(self.start + (index * Nlist::size_with(&self.ctx)), self.ctx)?;
        let name = self.data.pread(self.strtab + sym.n_strx)?;
        Ok((name, sym))
    }
}

impl<'a> Debug for Symbols<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        writeln!(fmt, "Data: {} start: {:#?}, nsyms: {} strtab: {:#x}", self.data.len(), self.start, self.nsyms, self.strtab)?;
        writeln!(fmt, "Symbols: {{")?;
        for (i, res) in self.iter().enumerate() {
            match res {
                Ok((name, nlist)) => {
                    writeln!(fmt, "{: >10x} {} sect: {:#x} type: {:#02x} desc: {:#03x}", nlist.n_value, name, nlist.n_sect, nlist.n_type, nlist.n_desc)?;
                },
                Err(error) => {
                    writeln!(fmt, "  Bad symbol, index: {}, sym: {:?}", i, error)?;
                }
            }
        }
        writeln!(fmt, "}}")
    }
}
<commit_msg>mach.symbols: add constants and to_str and get_type helper methods<commit_after>//! "Nlist" style symbols in this binary - beware, like most symbol tables in most binary formats, they are strippable, and should not be relied upon, see the imports and exports modules for something more permanent.
//!
//! Symbols are essentially a type, offset, and the symbol name

use scroll::{self, ctx, Pread};
use scroll::ctx::SizeWith;
use error;
use container::{self, Container};
use mach::load_command;
use core::fmt::{self, Debug};

// If the type is N_SECT then the n_sect field contains an ordinal of the
// section the symbol is defined in.  The sections are numbered from 1 and
// refer to sections in order they appear in the load commands for the file
// they are in.  This means the same ordinal may very well refer to different
// sections in different files.

// The n_value field for all symbol table entries (including N_STAB's) gets
// updated by the link editor based on the value of it's n_sect field and where
// the section n_sect references gets relocated.  If the value of the n_sect
// field is NO_SECT then it's n_value field is not changed by the link editor.
/// symbol is not in any section
pub const NO_SECT: u8 = 0;
/// 1 thru 255 inclusive
pub const MAX_SECT: u8 = 255;

/// undefined, n_sect == NO_SECT
pub const N_UNDF: u8 = 0x0;
/// absolute, n_sect == NO_SECT
pub const N_ABS:  u8 = 0x2;
/// defined in section number n_sect
pub const N_SECT: u8 = 0xe;
/// prebound undefined (defined in a dylib)
pub const N_PBUD: u8 = 0xc;
/// indirect
pub const N_INDR: u8 = 0xa;

pub const NLIST_TYPE_MASK: u8 = 0xe;
pub const NLIST_TYPE_GLOBAL: u8 = 0x1;
pub const NLIST_TYPE_LOCAL: u8 = 0x0;

pub fn n_type_to_str(n_type: u8) -> &'static str {
    match n_type {
        N_UNDF => "N_UNDF",
        N_ABS => "N_ABS",
        N_SECT => "N_SECT",
        N_PBUD => "N_PBUD",
        N_INDR => "N_INDR",
        _ => "UNKNOWN_N_TYPE"
    }
}

#[repr(C)]
#[derive(Clone, Copy, Pread, Pwrite, SizeWith)]
pub struct Nlist32 {
    /// index into the string table
    pub n_strx: u32,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: u8,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u32,
}

pub const SIZEOF_NLIST_32: usize = 12;

impl Debug for Nlist32 {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "strx: {:04} type: {:#02x} sect: {:#x} desc: {:#03x} value: {:#x}",
               self.n_strx,
               self.n_type,
               self.n_sect,
               self.n_desc,
               self.n_value,
        )
    }
}

#[repr(C)]
#[derive(Clone, Copy, Pread, Pwrite, SizeWith)]
pub struct Nlist64 {
    /// index into the string table
    pub n_strx: u32,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: u8,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u64,
}

pub const SIZEOF_NLIST_64: usize = 16;

impl Debug for Nlist64 {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "strx: {:04} type: {:#02x} sect: {:#x} desc: {:#03x} value: {:#x}",
               self.n_strx,
               self.n_type,
               self.n_sect,
               self.n_desc,
               self.n_value,
        )
    }
}

#[derive(Debug, Clone)]
pub struct Nlist {
    /// index into the string table
    pub n_strx: usize,
    /// type flag, see below
    pub n_type: u8,
    /// section number or NO_SECT
    pub n_sect: usize,
    /// see <mach-o/stab.h>
    pub n_desc: u16,
    /// value of this symbol (or stab offset)
    pub n_value: u64,
}

impl Nlist {
    /// Gets this symbol's type in bits 0xe
    pub fn get_type(&self) -> u8 {
        self.n_type & NLIST_TYPE_MASK
    }
    /// Gets the str representation of the type of this symbol
    pub fn type_str(&self) -> &'static str {
        n_type_to_str(self.get_type())
    }
    /// Whether this symbol is global or not
    pub fn is_global(&self) -> bool {
        self.n_type & !NLIST_TYPE_MASK == NLIST_TYPE_GLOBAL
    }
    /// Whether this symbol is undefined or not
    pub fn is_undefined(&self) -> bool {
        self.n_sect == 0 && self.n_type & NLIST_TYPE_MASK == 0
    }
}

impl ctx::SizeWith<container::Ctx> for Nlist {
    type Units = usize;
    fn size_with(ctx: &container::Ctx) -> usize {
        use container::Container;
        match ctx.container {
            Container::Little => {
                SIZEOF_NLIST_32
            },
            Container::Big => {
                SIZEOF_NLIST_64
            },
        }
    }
}

impl From<Nlist32> for Nlist {
    fn from(nlist: Nlist32) -> Self {
        Nlist {
            n_strx: nlist.n_strx as usize,
            n_type: nlist.n_type,
            n_sect: nlist.n_sect as usize,
            n_desc: nlist.n_desc,
            n_value: nlist.n_value as u64,
        }
    }
}

impl From<Nlist64> for Nlist {
    fn from(nlist: Nlist64) -> Self {
        Nlist {
            n_strx: nlist.n_strx as usize,
            n_type: nlist.n_type,
            n_sect: nlist.n_sect as usize,
            n_desc: nlist.n_desc,
            n_value: nlist.n_value,
        }
    }
}

impl<'a> ctx::TryFromCtx<'a, container::Ctx> for Nlist {
    type Error = scroll::Error;
    type Size = usize;
    fn try_from_ctx(bytes: &'a [u8], container::Ctx { container, le }: container::Ctx) -> scroll::Result<(Self, Self::Size)> {
        let nlist = match container {
            Container::Little => {
                (bytes.pread_with::<Nlist32>(0, le)?.into(), SIZEOF_NLIST_32)
            },
            Container::Big => {
                (bytes.pread_with::<Nlist64>(0, le)?.into(), SIZEOF_NLIST_64)
            },
        };
        Ok(nlist)
    }
}

#[derive(Debug, Clone, Copy, Default)]
pub struct SymbolsCtx {
    pub nsyms: usize,
    pub strtab: usize,
    pub ctx: container::Ctx,
}

impl<'a, T: ?Sized> ctx::TryFromCtx<'a, SymbolsCtx, T> for Symbols<'a> where T: AsRef<[u8]> {
    type Error = scroll::Error;
    type Size = usize;
    fn try_from_ctx(bytes: &'a T, SymbolsCtx {
        nsyms, strtab, ctx
    }: SymbolsCtx) -> scroll::Result<(Self, Self::Size)> {
        let data = bytes.as_ref();
        Ok ((Symbols {
            data: data,
            start: 0,
            nsyms: nsyms,
            strtab: strtab,
            ctx: ctx,
        }, data.len()))
    }
}

#[derive(Default)]
pub struct SymbolIterator<'a> {
    data: &'a [u8],
    nsyms: usize,
    offset: usize,
    count: usize,
    ctx: container::Ctx,
    strtab: usize,
}

impl<'a> Iterator for SymbolIterator<'a> {
    type Item = error::Result<(&'a str, Nlist)>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.count >= self.nsyms {
            None
        } else {
            self.count += 1;
            match self.data.gread_with::<Nlist>(&mut self.offset, self.ctx) {
                Ok(symbol) => {
                    match self.data.pread(self.strtab + symbol.n_strx) {
                        Ok(name) => {
                            Some(Ok((name, symbol)))
                        },
                        Err(e) => return Some(Err(e.into()))
                    }
                },
                Err(e) => return Some(Err(e.into()))
            }
        }
    }
}

/// A zero-copy "nlist" style symbol table ("stab"), including the string table
pub struct Symbols<'a> {
    data: &'a [u8],
    start: usize,
    nsyms: usize,
    // TODO: we can use an actual strtab here and tie it to symbols lifetime
    strtab: usize,
    ctx: container::Ctx,
}

impl<'a, 'b> IntoIterator for &'b Symbols<'a> {
    type Item = <SymbolIterator<'a> as Iterator>::Item;
    type IntoIter = SymbolIterator<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> Symbols<'a> {
    /// Creates a new symbol table with `count` elements, from the `start` offset, using the string table at `strtab`, with a _default_ ctx.
    ////
    /// **Beware**, this will provide incorrect results if you construct this on a 32-bit mach binary, using a 64-bit machine; use `parse` instead if you want 32/64 bit support
    pub fn new(bytes: &'a [u8], start: usize, count: usize, strtab: usize) -> error::Result<Symbols<'a>> {
        let nsyms = count;
        Ok (Symbols {
            data: bytes,
            start: start,
            nsyms: nsyms,
            strtab: strtab,
            ctx: container::Ctx::default(),
        })
    }
    pub fn parse(bytes: &'a [u8], symtab: &load_command::SymtabCommand, ctx: container::Ctx) -> error::Result<Symbols<'a>> {
        // we need to normalize the strtab offset before we receive the truncated bytes in pread_with
        let strtab = symtab.stroff - symtab.symoff;
        Ok(bytes.pread_with(symtab.symoff as usize, SymbolsCtx { nsyms: symtab.nsyms as usize, strtab: strtab as usize, ctx: ctx })?)
    }

    pub fn iter(&self) -> SymbolIterator<'a> {
        SymbolIterator {
            offset: self.start as usize,
            nsyms: self.nsyms as usize,
            count: 0,
            data: self.data,
            ctx: self.ctx,
            strtab: self.strtab,
        }
    }

    /// Parses a single Nlist symbol from the binary, with its accompanying name
    pub fn get(&self, index: usize) -> scroll::Result<(&'a str, Nlist)> {
        let sym: Nlist = self.data.pread_with(self.start + (index * Nlist::size_with(&self.ctx)), self.ctx)?;
        let name = self.data.pread(self.strtab + sym.n_strx)?;
        Ok((name, sym))
    }
}

impl<'a> Debug for Symbols<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        writeln!(fmt, "Data: {} start: {:#?}, nsyms: {} strtab: {:#x}", self.data.len(), self.start, self.nsyms, self.strtab)?;
        writeln!(fmt, "Symbols: {{")?;
        for (i, res) in self.iter().enumerate() {
            match res {
                Ok((name, nlist)) => {
                    writeln!(fmt, "{: >10x} {} sect: {:#x} type: {:#02x} desc: {:#03x}", nlist.n_value, name, nlist.n_sect, nlist.n_type, nlist.n_desc)?;
                },
                Err(error) => {
                    writeln!(fmt, "  Bad symbol, index: {}, sym: {:?}", i, error)?;
                }
            }
        }
        writeln!(fmt, "}}")
    }
}
<|endoftext|>


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

/** Task-local reference counted smart pointers

Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
destruction. They are restricted to containing `Owned` types in order to prevent cycles.

*/

use core::libc::{c_void, size_t, malloc, free};
use core::unstable::intrinsics;
use core::util;

struct RcBox<T> {
    value: T,
    count: uint
}

/// Immutable reference counted pointer type
#[non_owned]
pub struct Rc<T> {
    priv ptr: *mut RcBox<T>,
}

pub impl<T: Owned> Rc<T> {
    fn new(value: T) -> Rc<T> {
        unsafe {
            let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
            assert!(!ptr::is_null(ptr));
            intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
            Rc{ptr: ptr}
        }
    }

    #[inline(always)]
    fn borrow<'r>(&'r self) -> &'r T {
        unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
    }
}

#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T: Owned> Drop for Rc<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, intrinsics::uninit());
                free(self.ptr as *c_void)
            }
        }
    }
}

#[unsafe_destructor]
#[cfg(stage0)]
impl<T: Owned> Drop for Rc<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, intrinsics::init());
                free(self.ptr as *c_void)
            }
        }
    }
}

impl<T: Owned> Clone for Rc<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> Rc<T> {
        unsafe {
            (*self.ptr).count += 1;
            Rc{ptr: self.ptr}
        }
    }
}

impl<T: Owned + DeepClone> DeepClone for Rc<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> Rc<T> {
        Rc::new(self.borrow().deep_clone())
    }
}

#[cfg(test)]
mod test_rc {
    use super::*;
    use core::cell::Cell;

    #[test]
    fn test_clone() {
        let x = Rc::new(Cell(5));
        let y = x.clone();
        do x.borrow().with_mut_ref |inner| {
            *inner = 20;
        }
        assert_eq!(y.borrow().take(), 20);
    }

    #[test]
    fn test_deep_clone() {
        let x = Rc::new(Cell(5));
        let y = x.deep_clone();
        do x.borrow().with_mut_ref |inner| {
            *inner = 20;
        }
        assert_eq!(y.borrow().take(), 5);
    }

    #[test]
    fn test_simple() {
        let x = Rc::new(5);
        assert_eq!(*x.borrow(), 5);
    }

    #[test]
    fn test_simple_clone() {
        let x = Rc::new(5);
        let y = x.clone();
        assert_eq!(*x.borrow(), 5);
        assert_eq!(*y.borrow(), 5);
    }

    #[test]
    fn test_destructor() {
        let x = Rc::new(~5);
        assert_eq!(**x.borrow(), 5);
    }
}

#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
    fn init<T>() -> T;
    #[cfg(not(stage0))]
    fn uninit<T>() -> T;
}

#[deriving(Eq)]
enum Borrow {
    Mutable,
    Immutable,
    Nothing
}

struct RcMutBox<T> {
    value: T,
    count: uint,
    borrow: Borrow
}

/// Mutable reference counted pointer type
#[non_owned]
#[mutable]
pub struct RcMut<T> {
    priv ptr: *mut RcMutBox<T>,
}

pub impl<T: Owned> RcMut<T> {
    fn new(value: T) -> RcMut<T> {
        unsafe {
            let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
            assert!(!ptr::is_null(ptr));
            intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
            RcMut{ptr: ptr}
        }
    }

    /// Fails if there is already a mutable borrow of the box
    #[inline]
    fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow != Mutable);
            let previous = (*self.ptr).borrow;
            (*self.ptr).borrow = Immutable;
            let res = f(&(*self.ptr).value);
            (*self.ptr).borrow = previous;
            res
        }
    }

    /// Fails if there is already a mutable or immutable borrow of the box
    #[inline]
    fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow == Nothing);
            (*self.ptr).borrow = Mutable;
            let res = f(&mut (*self.ptr).value);
            (*self.ptr).borrow = Nothing;
            res
        }
    }
}

#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T: Owned> Drop for RcMut<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, uninit());
                free(self.ptr as *c_void)
            }
        }
    }
}

#[unsafe_destructor]
#[cfg(stage0)]
impl<T: Owned> Drop for RcMut<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, init());
                free(self.ptr as *c_void)
            }
        }
    }
}

impl<T: Owned> Clone for RcMut<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> RcMut<T> {
        unsafe {
            (*self.ptr).count += 1;
            RcMut{ptr: self.ptr}
        }
    }
}

impl<T: Owned + DeepClone> DeepClone for RcMut<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> RcMut<T> {
        do self.with_borrow |x| {
            // FIXME: #6497: should avoid freeze (slow)
            RcMut::new(x.deep_clone())
        }
    }
}

#[cfg(test)]
mod test_rc_mut {
    use super::*;

    #[test]
    fn test_clone() {
        let x = RcMut::new(5);
        let y = x.clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        let x = RcMut::new(5);
        let y = x.deep_clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 5);
        }
    }

    #[test]
    fn borrow_many() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_borrow |a| {
            assert_eq!(*a, 5);
            do y.with_borrow |b| {
                assert_eq!(*b, 5);
                do x.with_borrow |c| {
                    assert_eq!(*c, 5);
                }
            }
        }
    }

    #[test]
    fn modify() {
        let x = RcMut::new(5);
        let y = x.clone();

        do y.with_mut_borrow |a| {
            assert_eq!(*a, 5);
            *a = 6;
        }

        do x.with_borrow |a| {
            assert_eq!(*a, 6);
        }
    }

    #[test]
    fn release_immutable() {
        let x = RcMut::new(5);
        do x.with_borrow |_| {}
        do x.with_mut_borrow |_| {}
    }

    #[test]
    fn release_mutable() {
        let x = RcMut::new(5);
        do x.with_mut_borrow |_| {}
        do x.with_borrow |_| {}
    }

    #[test]
    #[should_fail]
    fn frozen() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_dupe() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_freeze() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn restore_freeze() {
        let x = RcMut::new(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do x.with_borrow |_| {}
            do y.with_mut_borrow |_| {}
        }
    }
}
<commit_msg>allow constructing Rc/RcMut from Const types too<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/** Task-local reference counted smart pointers

Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
destruction. They are restricted to containing types that are either `Owned` or `Const` (or both) to
prevent cycles.

Neither `Rc<T>` or `RcMut<T>` is ever `Owned` and `RcMut<T>` is never `Const`. If `T` is `Const`, a
cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.

*/

use core::libc::{c_void, size_t, malloc, free};
use core::unstable::intrinsics;
use core::util;

struct RcBox<T> {
    value: T,
    count: uint
}

/// Immutable reference counted pointer type
#[non_owned]
pub struct Rc<T> {
    priv ptr: *mut RcBox<T>,
}

priv impl<T> Rc<T> {
    unsafe fn new(value: T) -> Rc<T> {
        let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
        assert!(!ptr::is_null(ptr));
        intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
        Rc{ptr: ptr}
    }
}

// FIXME: #6516: should be a static method
pub fn rc_from_owned<T: Owned>(value: T) -> Rc<T> {
    unsafe { Rc::new(value) }
}

// FIXME: #6516: should be a static method
pub fn rc_from_const<T: Const>(value: T) -> Rc<T> {
    unsafe { Rc::new(value) }
}

pub impl<T> Rc<T> {
    #[inline(always)]
    fn borrow<'r>(&'r self) -> &'r T {
        unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
    }
}

#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T> Drop for Rc<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, intrinsics::uninit());
                free(self.ptr as *c_void)
            }
        }
    }
}

#[unsafe_destructor]
#[cfg(stage0)]
impl<T> Drop for Rc<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, intrinsics::init());
                free(self.ptr as *c_void)
            }
        }
    }
}

impl<T> Clone for Rc<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> Rc<T> {
        unsafe {
            (*self.ptr).count += 1;
            Rc{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for Rc<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> Rc<T> {
        unsafe { Rc::new(self.borrow().deep_clone()) }
    }
}

#[cfg(test)]
mod test_rc {
    use super::*;
    use core::cell::Cell;

    #[test]
    fn test_clone() {
        let x = rc_from_owned(Cell(5));
        let y = x.clone();
        do x.borrow().with_mut_ref |inner| {
            *inner = 20;
        }
        assert_eq!(y.borrow().take(), 20);
    }

    #[test]
    fn test_deep_clone() {
        let x = rc_from_owned(Cell(5));
        let y = x.deep_clone();
        do x.borrow().with_mut_ref |inner| {
            *inner = 20;
        }
        assert_eq!(y.borrow().take(), 5);
    }

    #[test]
    fn test_simple() {
        let x = rc_from_const(5);
        assert_eq!(*x.borrow(), 5);
    }

    #[test]
    fn test_simple_clone() {
        let x = rc_from_const(5);
        let y = x.clone();
        assert_eq!(*x.borrow(), 5);
        assert_eq!(*y.borrow(), 5);
    }

    #[test]
    fn test_destructor() {
        let x = rc_from_owned(~5);
        assert_eq!(**x.borrow(), 5);
    }
}

#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
    fn init<T>() -> T;
    #[cfg(not(stage0))]
    fn uninit<T>() -> T;
}

#[deriving(Eq)]
enum Borrow {
    Mutable,
    Immutable,
    Nothing
}

struct RcMutBox<T> {
    value: T,
    count: uint,
    borrow: Borrow
}

/// Mutable reference counted pointer type
#[non_owned]
#[mutable]
pub struct RcMut<T> {
    priv ptr: *mut RcMutBox<T>,
}

priv impl<T> RcMut<T> {
    unsafe fn new(value: T) -> RcMut<T> {
        let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
        assert!(!ptr::is_null(ptr));
        intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
        RcMut{ptr: ptr}
    }
}

// FIXME: #6516: should be a static method
pub fn rc_mut_from_owned<T: Owned>(value: T) -> RcMut<T> {
    unsafe { RcMut::new(value) }
}

// FIXME: #6516: should be a static method
pub fn rc_mut_from_const<T: Const>(value: T) -> RcMut<T> {
    unsafe { RcMut::new(value) }
}

pub impl<T> RcMut<T> {
    /// Fails if there is already a mutable borrow of the box
    #[inline]
    fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow != Mutable);
            let previous = (*self.ptr).borrow;
            (*self.ptr).borrow = Immutable;
            let res = f(&(*self.ptr).value);
            (*self.ptr).borrow = previous;
            res
        }
    }

    /// Fails if there is already a mutable or immutable borrow of the box
    #[inline]
    fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
        unsafe {
            assert!((*self.ptr).borrow == Nothing);
            (*self.ptr).borrow = Mutable;
            let res = f(&mut (*self.ptr).value);
            (*self.ptr).borrow = Nothing;
            res
        }
    }
}

#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T> Drop for RcMut<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, uninit());
                free(self.ptr as *c_void)
            }
        }
    }
}

#[unsafe_destructor]
#[cfg(stage0)]
impl<T> Drop for RcMut<T> {
    fn finalize(&self) {
        unsafe {
            (*self.ptr).count -= 1;
            if (*self.ptr).count == 0 {
                util::replace_ptr(self.ptr, init());
                free(self.ptr as *c_void)
            }
        }
    }
}

impl<T> Clone for RcMut<T> {
    /// Return a shallow copy of the reference counted pointer.
    #[inline]
    fn clone(&self) -> RcMut<T> {
        unsafe {
            (*self.ptr).count += 1;
            RcMut{ptr: self.ptr}
        }
    }
}

impl<T: DeepClone> DeepClone for RcMut<T> {
    /// Return a deep copy of the reference counted pointer.
    #[inline]
    fn deep_clone(&self) -> RcMut<T> {
        do self.with_borrow |x| {
            // FIXME: #6497: should avoid freeze (slow)
            unsafe { RcMut::new(x.deep_clone()) }
        }
    }
}

#[cfg(test)]
mod test_rc_mut {
    use super::*;

    #[test]
    fn test_clone() {
        let x = rc_mut_from_owned(5);
        let y = x.clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 20);
        }
    }

    #[test]
    fn test_deep_clone() {
        let x = rc_mut_from_const(5);
        let y = x.deep_clone();
        do x.with_mut_borrow |value| {
            *value = 20;
        }
        do y.with_borrow |value| {
            assert_eq!(*value, 5);
        }
    }

    #[test]
    fn borrow_many() {
        let x = rc_mut_from_owned(5);
        let y = x.clone();

        do x.with_borrow |a| {
            assert_eq!(*a, 5);
            do y.with_borrow |b| {
                assert_eq!(*b, 5);
                do x.with_borrow |c| {
                    assert_eq!(*c, 5);
                }
            }
        }
    }

    #[test]
    fn modify() {
        let x = rc_mut_from_const(5);
        let y = x.clone();

        do y.with_mut_borrow |a| {
            assert_eq!(*a, 5);
            *a = 6;
        }

        do x.with_borrow |a| {
            assert_eq!(*a, 6);
        }
    }

    #[test]
    fn release_immutable() {
        let x = rc_mut_from_owned(5);
        do x.with_borrow |_| {}
        do x.with_mut_borrow |_| {}
    }

    #[test]
    fn release_mutable() {
        let x = rc_mut_from_const(5);
        do x.with_mut_borrow |_| {}
        do x.with_borrow |_| {}
    }

    #[test]
    #[should_fail]
    fn frozen() {
        let x = rc_mut_from_owned(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_dupe() {
        let x = rc_mut_from_const(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_mut_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn mutable_freeze() {
        let x = rc_mut_from_owned(5);
        let y = x.clone();

        do x.with_mut_borrow |_| {
            do y.with_borrow |_| {
            }
        }
    }

    #[test]
    #[should_fail]
    fn restore_freeze() {
        let x = rc_mut_from_const(5);
        let y = x.clone();

        do x.with_borrow |_| {
            do x.with_borrow |_| {}
            do y.with_mut_borrow |_| {}
        }
    }
}
<|endoftext|>


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

use num::{One, Zero};
use point::Point2D;
use rect::Rect;
use size::Size2D;
use std::ops::{Add, Mul, Sub};

#[derive(Clone, Copy)]
pub struct Matrix2D<T> {
    m11: T, m12: T,
    m21: T, m22: T,
    m31: T, m32: T
}

impl<T:Add<T, Output=T> +
       Copy +
       Clone +
       Mul<T, Output=T> +
       One +
       PartialOrd +
       Sub<T, Output=T> +
       Zero> Matrix2D<T> {
    pub fn new(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Matrix2D<T> {
        Matrix2D {
            m11: m11, m12: m12,
            m21: m21, m22: m22,
            m31: m31, m32: m32
        }
    }

    pub fn mul(&self, m: &Matrix2D<T>) -> Matrix2D<T> {
        Matrix2D::new(m.m11*self.m11 + m.m12*self.m21,
                      m.m11*self.m12 + m.m12*self.m22,
                      m.m21*self.m11 + m.m22*self.m21,
                      m.m21*self.m12 + m.m22*self.m22,
                      m.m31*self.m11 + m.m32*self.m21 + self.m31,
                      m.m31*self.m12 + m.m32*self.m22 + self.m32)
    }

    pub fn translate(&self, x: T, y: T) -> Matrix2D<T> {
         let (_0, _1): (T, T) = (Zero::zero(), One::one());
         let matrix = Matrix2D::new(_1.clone(), _0.clone(),
                                    _0.clone(), _1.clone(),
                                    x, y);
        return self.mul(&matrix);
    }

    pub fn scale(&self, x: T, y: T) -> Matrix2D<T> {
        Matrix2D::new(self.m11 * x,     self.m12.clone(),
                      self.m21.clone(), self.m22 * y,
                      self.m31.clone(), self.m32.clone())
    }

    pub fn identity() -> Matrix2D<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        return Matrix2D::new(_1.clone(), _0.clone(),
                             _0.clone(), _1.clone(),
                             _0.clone(), _0.clone());
    }

    pub fn to_array(&self) -> [T; 6] {
        [
            self.m11.clone(), self.m12.clone(),
            self.m21.clone(), self.m22.clone(),
            self.m31.clone(), self.m32.clone()
        ]
    }

    /// Returns the given point transformed by this matrix.
    #[inline]
    pub fn transform_point(&self, point: &Point2D<T>) -> Point2D<T> {
        Point2D::new(point.x * self.m11 + point.y * self.m21 + self.m31,
                     point.x * self.m12 + point.y * self.m22 + self.m32)
    }

    /// Returns a rectangle that encompasses the result of transforming the given rectangle by this
    /// matrix.
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T>) -> Rect<T> {
        let top_left = self.transform_point(&rect.origin);
        let top_right = self.transform_point(&rect.top_right());
        let bottom_left = self.transform_point(&rect.bottom_left());
        let bottom_right = self.transform_point(&rect.bottom_right());
        let (mut min_x, mut min_y) = (top_left.x.clone(), top_left.y.clone());
        let (mut max_x, mut max_y) = (min_x.clone(), min_y.clone());
        for point in [ top_right, bottom_left, bottom_right ].iter() {
            if point.x < min_x {
                min_x = point.x.clone()
            }
            if point.x > max_x {
                max_x = point.x.clone()
            }
            if point.y < min_y {
                min_y = point.y.clone()
            }
            if point.y > max_y {
                max_y = point.y.clone()
            }
        }
        Rect::new(Point2D::new(min_x.clone(), min_y.clone()),
                  Size2D::new(max_x - min_x, max_y - min_y))
    }
}
<commit_msg>Auto merge of #97 - pcwalton:serde-matrix, r=glennw<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use num::{One, Zero};
use point::Point2D;
use rect::Rect;
use size::Size2D;
use std::ops::{Add, Mul, Sub};

#[derive(Clone, Copy, Deserialize, Serialize)]
pub struct Matrix2D<T> {
    m11: T, m12: T,
    m21: T, m22: T,
    m31: T, m32: T
}

impl<T:Add<T, Output=T> +
       Copy +
       Clone +
       Mul<T, Output=T> +
       One +
       PartialOrd +
       Sub<T, Output=T> +
       Zero> Matrix2D<T> {
    pub fn new(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Matrix2D<T> {
        Matrix2D {
            m11: m11, m12: m12,
            m21: m21, m22: m22,
            m31: m31, m32: m32
        }
    }

    pub fn mul(&self, m: &Matrix2D<T>) -> Matrix2D<T> {
        Matrix2D::new(m.m11*self.m11 + m.m12*self.m21,
                      m.m11*self.m12 + m.m12*self.m22,
                      m.m21*self.m11 + m.m22*self.m21,
                      m.m21*self.m12 + m.m22*self.m22,
                      m.m31*self.m11 + m.m32*self.m21 + self.m31,
                      m.m31*self.m12 + m.m32*self.m22 + self.m32)
    }

    pub fn translate(&self, x: T, y: T) -> Matrix2D<T> {
         let (_0, _1): (T, T) = (Zero::zero(), One::one());
         let matrix = Matrix2D::new(_1.clone(), _0.clone(),
                                    _0.clone(), _1.clone(),
                                    x, y);
        return self.mul(&matrix);
    }

    pub fn scale(&self, x: T, y: T) -> Matrix2D<T> {
        Matrix2D::new(self.m11 * x,     self.m12.clone(),
                      self.m21.clone(), self.m22 * y,
                      self.m31.clone(), self.m32.clone())
    }

    pub fn identity() -> Matrix2D<T> {
        let (_0, _1): (T, T) = (Zero::zero(), One::one());
        return Matrix2D::new(_1.clone(), _0.clone(),
                             _0.clone(), _1.clone(),
                             _0.clone(), _0.clone());
    }

    pub fn to_array(&self) -> [T; 6] {
        [
            self.m11.clone(), self.m12.clone(),
            self.m21.clone(), self.m22.clone(),
            self.m31.clone(), self.m32.clone()
        ]
    }

    /// Returns the given point transformed by this matrix.
    #[inline]
    pub fn transform_point(&self, point: &Point2D<T>) -> Point2D<T> {
        Point2D::new(point.x * self.m11 + point.y * self.m21 + self.m31,
                     point.x * self.m12 + point.y * self.m22 + self.m32)
    }

    /// Returns a rectangle that encompasses the result of transforming the given rectangle by this
    /// matrix.
    #[inline]
    pub fn transform_rect(&self, rect: &Rect<T>) -> Rect<T> {
        let top_left = self.transform_point(&rect.origin);
        let top_right = self.transform_point(&rect.top_right());
        let bottom_left = self.transform_point(&rect.bottom_left());
        let bottom_right = self.transform_point(&rect.bottom_right());
        let (mut min_x, mut min_y) = (top_left.x.clone(), top_left.y.clone());
        let (mut max_x, mut max_y) = (min_x.clone(), min_y.clone());
        for point in [ top_right, bottom_left, bottom_right ].iter() {
            if point.x < min_x {
                min_x = point.x.clone()
            }
            if point.x > max_x {
                max_x = point.x.clone()
            }
            if point.y < min_y {
                min_y = point.y.clone()
            }
            if point.y > max_y {
                max_y = point.y.clone()
            }
        }
        Rect::new(Point2D::new(min_x.clone(), min_y.clone()),
                  Size2D::new(max_x - min_x, max_y - min_y))
    }
}
<|endoftext|>


<commit_before>use std::mem;

use bytes::*;

// inefficient: https://github.com/carllerche/bytes/issues/85
#[allow(dead_code)]
pub fn bytes_concat(mut a: Bytes, b: Bytes) -> Bytes {
    if b.is_empty() {
        a
    } else if a.is_empty() {
        b
    } else {
        bytes_extend_with(&mut a, b);
        a
    }
}

pub fn bytes_extend_with_slice(target: &mut Bytes, append: &[u8]) {
    let mut bytes_mut = BytesMut::from(mem::replace(target, Bytes::new()));
    bytes_mut_extend_with_slice(&mut bytes_mut, append);
    mem::replace(target, bytes_mut.freeze());
}

pub fn bytes_extend_with(target: &mut Bytes, append: Bytes) {
    // TODO: optimize
    bytes_extend_with_slice(target, &append[..]);
}

// https://github.com/carllerche/bytes/pull/112
pub fn bytes_mut_extend_with_slice(target: &mut BytesMut, append: &[u8]) {
    target.reserve(append.len());
    target.put_slice(append);
}

#[cfg(test)]
mod test {
    use super::*;
    use bytes::*;

    #[test]
    fn test_bytes_concat() {
        let a = Bytes::from("aabb");
        let b = Bytes::from("ccddee");
        let r = bytes_concat(a, b);
        let e = Bytes::from("aabbccddee");
        assert_eq!(e, r);
    }
}
<commit_msg>Warnings<commit_after>use std::mem;

use bytes::*;

// inefficient: https://github.com/carllerche/bytes/issues/85
#[allow(dead_code)]
pub fn bytes_concat(mut a: Bytes, b: Bytes) -> Bytes {
    if b.is_empty() {
        a
    } else if a.is_empty() {
        b
    } else {
        bytes_extend_with(&mut a, b);
        a
    }
}

pub fn bytes_extend_with_slice(target: &mut Bytes, append: &[u8]) {
    let mut bytes_mut = BytesMut::from(mem::replace(target, Bytes::new()));
    bytes_mut_extend_with_slice(&mut bytes_mut, append);
    mem::replace(target, bytes_mut.freeze());
}

pub fn bytes_extend_with(target: &mut Bytes, append: Bytes) {
    // TODO: optimize
    bytes_extend_with_slice(target, &append[..]);
}

// https://github.com/carllerche/bytes/pull/112
pub fn bytes_mut_extend_with_slice(target: &mut BytesMut, append: &[u8]) {
    target.reserve(append.len());
    target.put_slice(append);
}

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

    #[test]
    fn test_bytes_concat() {
        let a = Bytes::from("aabb");
        let b = Bytes::from("ccddee");
        let r = bytes_concat(a, b);
        let e = Bytes::from("aabbccddee");
        assert_eq!(e, r);
    }
}
<|endoftext|>


<commit_before>use std::mem;

use bytes::*;

// https://github.com/carllerche/bytes/pull/111
pub fn bytes_into_mut(bytes: Bytes) -> BytesMut {
    match bytes.try_mut() {
        Ok(bytes_mut) => bytes_mut,
        Err(bytes) => BytesMut::from(&bytes[..]),
    }
}

// inefficient: https://github.com/carllerche/bytes/issues/85
#[allow(dead_code)]
pub fn bytes_concat(mut a: Bytes, b: Bytes) -> Bytes {
    if b.is_empty() {
        a
    } else if a.is_empty() {
        b
    } else {
        bytes_extend_with(&mut a, b);
        a
    }
}

pub fn bytes_extend_with_slice(target: &mut Bytes, append: &[u8]) {
    let mut bytes_mut = bytes_into_mut(mem::replace(target, Bytes::new()));
    bytes_mut_extend_with_slice(&mut bytes_mut, append);
    mem::replace(target, bytes_mut.freeze());
}

pub fn bytes_extend_with(target: &mut Bytes, append: Bytes) {
    // TODO: optimize
    bytes_extend_with_slice(target, &append[..]);
}

// https://github.com/carllerche/bytes/pull/112
pub fn bytes_mut_extend_with_slice(target: &mut BytesMut, append: &[u8]) {
    target.reserve(append.len());
    target.put_slice(append);
}

#[cfg(test)]
mod test {
    use super::*;
    use bytes::*;

    #[test]
    fn test_bytes_concat() {
        let a = Bytes::from("aabb");
        let b = Bytes::from("ccddee");
        let r = bytes_concat(a, b);
        let e = Bytes::from("aabbccddee");
        assert_eq!(e, r);
    }
}
<commit_msg>Use function from bytes crate<commit_after>use std::mem;

use bytes::*;

// inefficient: https://github.com/carllerche/bytes/issues/85
#[allow(dead_code)]
pub fn bytes_concat(mut a: Bytes, b: Bytes) -> Bytes {
    if b.is_empty() {
        a
    } else if a.is_empty() {
        b
    } else {
        bytes_extend_with(&mut a, b);
        a
    }
}

pub fn bytes_extend_with_slice(target: &mut Bytes, append: &[u8]) {
    let mut bytes_mut = BytesMut::from(mem::replace(target, Bytes::new()));
    bytes_mut_extend_with_slice(&mut bytes_mut, append);
    mem::replace(target, bytes_mut.freeze());
}

pub fn bytes_extend_with(target: &mut Bytes, append: Bytes) {
    // TODO: optimize
    bytes_extend_with_slice(target, &append[..]);
}

// https://github.com/carllerche/bytes/pull/112
pub fn bytes_mut_extend_with_slice(target: &mut BytesMut, append: &[u8]) {
    target.reserve(append.len());
    target.put_slice(append);
}

#[cfg(test)]
mod test {
    use super::*;
    use bytes::*;

    #[test]
    fn test_bytes_concat() {
        let a = Bytes::from("aabb");
        let b = Bytes::from("ccddee");
        let r = bytes_concat(a, b);
        let e = Bytes::from("aabbccddee");
        assert_eq!(e, r);
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic::{ATOMIC_BOOL_INIT, AtomicBool, Ordering};

static MESSAGES: AtomicBool = ATOMIC_BOOL_INIT;
static IGNORE_MESSAGES: AtomicBool = ATOMIC_BOOL_INIT;
static ERRORED: AtomicBool = ATOMIC_BOOL_INIT;

/// Emit a non-fatal error message, unless messages were disabled.
#[macro_export]
macro_rules! message {
    ($($tt:tt)*) => {
        if crate::messages::messages() {
            eprintln!($($tt)*);
        }
    }
}

/// Like message, but sets ripgrep's "errored" flag, which controls the exit
/// status.
#[macro_export]
macro_rules! err_message {
    ($($tt:tt)*) => {
        crate::messages::set_errored();
        message!($($tt)*);
    }
}

/// Emit a non-fatal ignore-related error message (like a parse error), unless
/// ignore-messages were disabled.
#[macro_export]
macro_rules! ignore_message {
    ($($tt:tt)*) => {
        if crate::messages::messages() && crate::messages::ignore_messages() {
            eprintln!($($tt)*);
        }
    }
}

/// Returns true if and only if messages should be shown.
pub fn messages() -> bool {
    MESSAGES.load(Ordering::SeqCst)
}

/// Set whether messages should be shown or not.
///
/// By default, they are not shown.
pub fn set_messages(yes: bool) {
    MESSAGES.store(yes, Ordering::SeqCst)
}

/// Returns true if and only if "ignore" related messages should be shown.
pub fn ignore_messages() -> bool {
    IGNORE_MESSAGES.load(Ordering::SeqCst)
}

/// Set whether "ignore" related messages should be shown or not.
///
/// By default, they are not shown.
///
/// Note that this is overridden if `messages` is disabled. Namely, if
/// `messages` is disabled, then "ignore" messages are never shown, regardless
/// of this setting.
pub fn set_ignore_messages(yes: bool) {
    IGNORE_MESSAGES.store(yes, Ordering::SeqCst)
}

/// Returns true if and only if ripgrep came across a non-fatal error.
pub fn errored() -> bool {
    ERRORED.load(Ordering::SeqCst)
}

/// Indicate that ripgrep has come across a non-fatal error.
pub fn set_errored() {
    ERRORED.store(true, Ordering::SeqCst);
}
<commit_msg>deprecated: remove use of ATOMIC_BOOL_INIT<commit_after>use std::sync::atomic::{AtomicBool, Ordering};

static MESSAGES: AtomicBool = AtomicBool::new(false);
static IGNORE_MESSAGES: AtomicBool = AtomicBool::new(false);
static ERRORED: AtomicBool = AtomicBool::new(false);

/// Emit a non-fatal error message, unless messages were disabled.
#[macro_export]
macro_rules! message {
    ($($tt:tt)*) => {
        if crate::messages::messages() {
            eprintln!($($tt)*);
        }
    }
}

/// Like message, but sets ripgrep's "errored" flag, which controls the exit
/// status.
#[macro_export]
macro_rules! err_message {
    ($($tt:tt)*) => {
        crate::messages::set_errored();
        message!($($tt)*);
    }
}

/// Emit a non-fatal ignore-related error message (like a parse error), unless
/// ignore-messages were disabled.
#[macro_export]
macro_rules! ignore_message {
    ($($tt:tt)*) => {
        if crate::messages::messages() && crate::messages::ignore_messages() {
            eprintln!($($tt)*);
        }
    }
}

/// Returns true if and only if messages should be shown.
pub fn messages() -> bool {
    MESSAGES.load(Ordering::SeqCst)
}

/// Set whether messages should be shown or not.
///
/// By default, they are not shown.
pub fn set_messages(yes: bool) {
    MESSAGES.store(yes, Ordering::SeqCst)
}

/// Returns true if and only if "ignore" related messages should be shown.
pub fn ignore_messages() -> bool {
    IGNORE_MESSAGES.load(Ordering::SeqCst)
}

/// Set whether "ignore" related messages should be shown or not.
///
/// By default, they are not shown.
///
/// Note that this is overridden if `messages` is disabled. Namely, if
/// `messages` is disabled, then "ignore" messages are never shown, regardless
/// of this setting.
pub fn set_ignore_messages(yes: bool) {
    IGNORE_MESSAGES.store(yes, Ordering::SeqCst)
}

/// Returns true if and only if ripgrep came across a non-fatal error.
pub fn errored() -> bool {
    ERRORED.load(Ordering::SeqCst)
}

/// Indicate that ripgrep has come across a non-fatal error.
pub fn set_errored() {
    ERRORED.store(true, Ordering::SeqCst);
}
<|endoftext|>


<commit_before>// TODO: add `MathmMl` struct.

/// `QueryResult` is the outer wrapper for all results from the query function.
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct QueryResult {
    // Attributes
    pub success: bool,
    pub error: bool,
    pub numpods: u32,
    pub version: String, // TODO: replace this with a better type.
    pub datatypes: String, // TODO: possibly replace this with an enum?
    pub timing: f64,
    pub timedout: String,
    pub timedoutpods: String,
    pub parsetiming: f64,
    pub parsetimedout: bool,
    pub recalculate: String,
    pub id: String,
    //pub host: String, // FIXME
    pub server: u32,
    pub related: String,

    pub pod: Vec<Pod>,
    pub assumptions: Option<Assumptions>,
    pub sources: Option<Sources>,
    // TODO: find a way to parse errors.
    // The naive method (uncommenting the following line) doesn't work as
    // `QueryResult` also contains an `error` attribute.
    //pub error: Option<Error>,
    pub tips: Option<Tips>,
    pub didyoumeans: Option<DidYouMeans>,
    pub languagemsg: Option<LanguageMsg>,
    pub futuretopic: Option<FutureTopic>,
    pub relatedexamples: Option<RelatedExamples>,
    pub examplepage: Option<ExamplePage>,
    pub generalization: Option<Generalization>,
    pub warnings: Option<Warnings>,
}

/// A series of `Assumption` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Assumptions {
    // Attributes
    pub count: u32,

    pub assumption: Vec<Assumption>,
}

/// A single assumption, typically about the meaning of a word or phrase.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Assumption {
    // Attributes
    #[serde(rename="type")]
    pub assumption_type: String,
    //pub desc: Option<String>,
    //pub word: Option<String>,
    //pub template: Option<String>,
    //pub current: Option<u32>,
    pub count: u32,

    pub value: Vec<Value>,
}

/// A series of `Tip` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Tips {
    // Attributes
    pub count: u32,

    pub tip: Vec<Tip>,
}

/// A single tip, typically regarding suggestions for fixing the query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Tip {
    // Attributes
    pub count: u32,

    pub tip: Vec<Tip>,
}

/// A series of `DidYouMean` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct DidYouMeans {
    // Attributes
    pub count: u32,

    pub didyoumean: Vec<DidYouMean>,
}

/// Provides a suggestion for a different query than the one provided.
pub type DidYouMean = String;

/// Generated when a foreign language is detected in a query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct LanguageMsg {
    // Attributes
    pub english: String,
    pub other: String,
}

/// Provides information for queries regarding a topic under development.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct FutureTopic {
    // Attributes
    pub topic: String,
    pub msg: String,
}

/// A series of `RelatedExample` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct RelatedExamples {
    // Attributes
    pub count: u32,

    #[serde(rename = "relatedexample")]
    pub related_example: Vec<RelatedExample>,
}

/// Provides a link to an HTML page of related examples on the requested topic.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct RelatedExample {
    // Attributes
    pub input: String,
    pub desc: String,
    pub category: String,
    pub categorythumb: Url,
    pub categorypage: Url,
}

/// Provides a link to an HTML page of sample queries on the requested topic.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct ExamplePage {
    // Attributes
    pub category: String,
    pub url: Url,
}

/// A series of `Warning` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Warnings {
    // Attributes
    pub count: u32,

    pub warning: Vec<Warnings>,
}

/// An enum representing all possible warning types.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Warning {
    Spellcheck {
        // Attributes
        word: String,
        suggestion: String,
        text: String,
    },
    Delimeters {
        // Attributes
        text: String,
    },
    Translation {
        // Attributes
        phrase: String,
        trans: String,
        lang: String,
        text: String,
    },
    Reinterpret {
        // Attributes
        text: String,

        alternative: Vec<Alternative>,
    },
}

/// An alternative interpretation of an element in a query.
pub type Alternative = String;

/// Provides a link to a generalization of the requested query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Generalization {
    pub topic: String,
    pub desc: String,
    pub url: Url,
}

/// A series of `Source` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sources {
    // Attributes
    pub count: u32,

    pub source: Vec<Source>,
}

/// A link to a web page of source information.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Source {
    // Attributes
    pub url: String,
    pub text: String,
}

/// The value of an assumption.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Value {
    // Attributes
    pub name: String,
    pub desc: String,
    pub input: String,
    //pub word: Option<String>,
}

/// `Pod` elements are subelements of `QueryResult`. Each contains the results
/// for a single pod.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Pod {
    // Attributes
    pub title: String,
    pub error: bool,
    pub position: u32,
    pub scanner: String,
    pub id: String,
    pub numsubpods: u32,
    //pub primary: Option<bool>, // TODO: unimplemented by `serde_xml`.

    pub subpod: Vec<Subpod>,
    pub states: Option<States>,
    pub infos: Option<Infos>,
    // TODO: find a way to parse errors.
    // The naive method (uncommenting the following line) doesn't work as `Pod`
    // also contains an `error` attribute.
    //pub error: Option<Error>,
    pub sounds: Option<Sounds>,
}

/// A series of `State` attributes.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct States {
    // Attributes
    pub count: u32,

    pub state: Vec<State>,
    pub statelist: Option<Vec<Statelist>>,
}

/// A series of `State` attributes, combined into a list.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Statelist {
    // Attributes
    pub count: u32,
    pub value: String,

    pub state: Vec<State>,
}

/// An alternative state which is available to a `Pod` or `Subpod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct State {
    // Attributes
    pub name: String,
    pub input: String,
}

/// A series of `Info` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Infos {
    // Attributes
    pub count: u32,

    pub info: Vec<Info>,
}

/// A container for extra information regarding the contents of a pod.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Info {
    // TODO: uncomment this once `serde-xml` implements `Option` deserialization
    // in this situation.
    //pub text: Option<String>,
    pub img: Option<Vec<Img>>,
    pub link: Option<Vec<Link>>,
    pub units: Option<Vec<Units>>,
}

/// A series of `Sound` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sounds {
    // Attributes
    pub count: u32,

    pub sound: Vec<Sound>,
}

/// Provides a link to a playable sound file.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sound {
    // Attributes
    pub url: Url,
    #[serde(rename = "type")]
    pub mimetype: String, // TODO: replace this with a Mimetype type.
}

/// A subelement of `Pod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Subpod {
    // Attributes
    pub title: String,

    pub img: Option<Img>,
    pub plaintext: Option<Plaintext>,
    pub states: Option<States>,
}

/// A textual representation of a single subpod.
pub type Plaintext = String;

/// An HTML img element suitable for direct inclusion in a web page.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Img {
    pub src: Url,
    //pub alt: Option<String>,
    //pub title: Option<String>,
    pub width: u32,
    pub height: u32,
}

/// An HTML image map.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct ImageMap {
    rect: Vec<Rect>,
}

/// A rectangular section of an HTML image map.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Rect {
    // Attributes
    pub left: u32,
    pub top: u32,
    pub right: u32,
    pub bottom: u32,
    pub query: String,
    pub assumptions: String,
    pub title: String,
}

/// A series of `Unit` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Units {
    // Attributes
    pub count: u32,

    pub unit: Vec<Unit>,
    pub img: Img,
}

/// A table of unit abbreviations used inside a `Pod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Unit {
    // Attributes
    pub short: String,
    pub long: String,
}

/// A standard link of some text pointing to a URL.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Link {
    // Attributes
    pub url: String,
    pub text: String,
    //pub title: Option<String>,
}

/// `Error` elements provide a code and a description of an error which has
/// occured while performing a query to the API.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Error {
    pub code: u32,
    pub msg: String,
}
<commit_msg>impr: enable primary field for Pod struct<commit_after>// TODO: add `MathmMl` struct.

/// `QueryResult` is the outer wrapper for all results from the query function.
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct QueryResult {
    // Attributes
    pub success: bool,
    pub error: bool,
    pub numpods: u32,
    pub version: String, // TODO: replace this with a better type.
    pub datatypes: String, // TODO: possibly replace this with an enum?
    pub timing: f64,
    pub timedout: String,
    pub timedoutpods: String,
    pub parsetiming: f64,
    pub parsetimedout: bool,
    pub recalculate: String,
    pub id: String,
    //pub host: String, // FIXME
    pub server: u32,
    pub related: String,

    pub pod: Vec<Pod>,
    pub assumptions: Option<Assumptions>,
    pub sources: Option<Sources>,
    // TODO: find a way to parse errors.
    // The naive method (uncommenting the following line) doesn't work as
    // `QueryResult` also contains an `error` attribute.
    //pub error: Option<Error>,
    pub tips: Option<Tips>,
    pub didyoumeans: Option<DidYouMeans>,
    pub languagemsg: Option<LanguageMsg>,
    pub futuretopic: Option<FutureTopic>,
    pub relatedexamples: Option<RelatedExamples>,
    pub examplepage: Option<ExamplePage>,
    pub generalization: Option<Generalization>,
    pub warnings: Option<Warnings>,
}

/// A series of `Assumption` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Assumptions {
    // Attributes
    pub count: u32,

    pub assumption: Vec<Assumption>,
}

/// A single assumption, typically about the meaning of a word or phrase.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Assumption {
    // Attributes
    #[serde(rename="type")]
    pub assumption_type: String,
    //pub desc: Option<String>,
    //pub word: Option<String>,
    //pub template: Option<String>,
    //pub current: Option<u32>,
    pub count: u32,

    pub value: Vec<Value>,
}

/// A series of `Tip` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Tips {
    // Attributes
    pub count: u32,

    pub tip: Vec<Tip>,
}

/// A single tip, typically regarding suggestions for fixing the query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Tip {
    // Attributes
    pub count: u32,

    pub tip: Vec<Tip>,
}

/// A series of `DidYouMean` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct DidYouMeans {
    // Attributes
    pub count: u32,

    pub didyoumean: Vec<DidYouMean>,
}

/// Provides a suggestion for a different query than the one provided.
pub type DidYouMean = String;

/// Generated when a foreign language is detected in a query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct LanguageMsg {
    // Attributes
    pub english: String,
    pub other: String,
}

/// Provides information for queries regarding a topic under development.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct FutureTopic {
    // Attributes
    pub topic: String,
    pub msg: String,
}

/// A series of `RelatedExample` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct RelatedExamples {
    // Attributes
    pub count: u32,

    #[serde(rename = "relatedexample")]
    pub related_example: Vec<RelatedExample>,
}

/// Provides a link to an HTML page of related examples on the requested topic.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct RelatedExample {
    // Attributes
    pub input: String,
    pub desc: String,
    pub category: String,
    pub categorythumb: Url,
    pub categorypage: Url,
}

/// Provides a link to an HTML page of sample queries on the requested topic.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct ExamplePage {
    // Attributes
    pub category: String,
    pub url: Url,
}

/// A series of `Warning` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Warnings {
    // Attributes
    pub count: u32,

    pub warning: Vec<Warnings>,
}

/// An enum representing all possible warning types.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Warning {
    Spellcheck {
        // Attributes
        word: String,
        suggestion: String,
        text: String,
    },
    Delimeters {
        // Attributes
        text: String,
    },
    Translation {
        // Attributes
        phrase: String,
        trans: String,
        lang: String,
        text: String,
    },
    Reinterpret {
        // Attributes
        text: String,

        alternative: Vec<Alternative>,
    },
}

/// An alternative interpretation of an element in a query.
pub type Alternative = String;

/// Provides a link to a generalization of the requested query.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Generalization {
    pub topic: String,
    pub desc: String,
    pub url: Url,
}

/// A series of `Source` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sources {
    // Attributes
    pub count: u32,

    pub source: Vec<Source>,
}

/// A link to a web page of source information.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Source {
    // Attributes
    pub url: String,
    pub text: String,
}

/// The value of an assumption.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Value {
    // Attributes
    pub name: String,
    pub desc: String,
    pub input: String,
    //pub word: Option<String>,
}

/// `Pod` elements are subelements of `QueryResult`. Each contains the results
/// for a single pod.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Pod {
    // Attributes
    pub title: String,
    pub error: bool,
    pub position: u32,
    pub scanner: String,
    pub id: String,
    pub numsubpods: u32,
    pub primary: Option<bool>,

    pub subpod: Vec<Subpod>,
    pub states: Option<States>,
    pub infos: Option<Infos>,
    // TODO: find a way to parse errors.
    // The naive method (uncommenting the following line) doesn't work as `Pod`
    // also contains an `error` attribute.
    //pub error: Option<Error>,
    pub sounds: Option<Sounds>,
}

/// A series of `State` attributes.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct States {
    // Attributes
    pub count: u32,

    pub state: Vec<State>,
    pub statelist: Option<Vec<Statelist>>,
}

/// A series of `State` attributes, combined into a list.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Statelist {
    // Attributes
    pub count: u32,
    pub value: String,

    pub state: Vec<State>,
}

/// An alternative state which is available to a `Pod` or `Subpod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct State {
    // Attributes
    pub name: String,
    pub input: String,
}

/// A series of `Info` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Infos {
    // Attributes
    pub count: u32,

    pub info: Vec<Info>,
}

/// A container for extra information regarding the contents of a pod.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Info {
    // TODO: uncomment this once `serde-xml` implements `Option` deserialization
    // in this situation.
    //pub text: Option<String>,
    pub img: Option<Vec<Img>>,
    pub link: Option<Vec<Link>>,
    pub units: Option<Vec<Units>>,
}

/// A series of `Sound` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sounds {
    // Attributes
    pub count: u32,

    pub sound: Vec<Sound>,
}

/// Provides a link to a playable sound file.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Sound {
    // Attributes
    pub url: Url,
    #[serde(rename = "type")]
    pub mimetype: String, // TODO: replace this with a Mimetype type.
}

/// A subelement of `Pod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Subpod {
    // Attributes
    pub title: String,

    pub img: Option<Img>,
    pub plaintext: Option<Plaintext>,
    pub states: Option<States>,
}

/// A textual representation of a single subpod.
pub type Plaintext = String;

/// An HTML img element suitable for direct inclusion in a web page.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Img {
    pub src: Url,
    //pub alt: Option<String>,
    //pub title: Option<String>,
    pub width: u32,
    pub height: u32,
}

/// An HTML image map.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct ImageMap {
    rect: Vec<Rect>,
}

/// A rectangular section of an HTML image map.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Rect {
    // Attributes
    pub left: u32,
    pub top: u32,
    pub right: u32,
    pub bottom: u32,
    pub query: String,
    pub assumptions: String,
    pub title: String,
}

/// A series of `Unit` elements.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Units {
    // Attributes
    pub count: u32,

    pub unit: Vec<Unit>,
    pub img: Img,
}

/// A table of unit abbreviations used inside a `Pod`.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Unit {
    // Attributes
    pub short: String,
    pub long: String,
}

/// A standard link of some text pointing to a URL.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Link {
    // Attributes
    pub url: String,
    pub text: String,
    //pub title: Option<String>,
}

/// `Error` elements provide a code and a description of an error which has
/// occured while performing a query to the API.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct Error {
    pub code: u32,
    pub msg: String,
}
<|endoftext|>