<commit_before>extern crate tokio_io;
extern crate futures;

use futures::future::ok;
use std::rc::Rc;
use std::cell::RefCell;

use super::{Peer, BoxedNewPeerFuture};

use tokio_io::{AsyncRead,AsyncWrite};
use std::io::{Read, Write, Error as IoError};

use futures::{Future,Poll,Async};
use super::{once,Specifier,Handle,ProgramState,PeerConstructor,wouldblock};

#[derive(Debug)]
pub struct AutoReconnect(pub Rc<Specifier>);
impl Specifier for AutoReconnect {
    fn construct(&self, h:&Handle, _ps: &mut ProgramState) -> PeerConstructor {
        let mut subspec_globalstate = false;

        for i in self.0.get_info().collect() {
            if i.uses_global_state {
                subspec_globalstate = true;
            }
        }

        if subspec_globalstate {
            let e : Box<::std::error::Error>
            = "Can't use autoreconnect on a specifier that uses global state".to_owned().into();
            once(Box::new(::futures::future::err(e)) as BoxedNewPeerFuture)
        } else {
            //let inner = self.0.construct(h, ps).get_only_first_conn();
            once(autoreconnector(h.clone(), self.0.clone()))
        }
    }
    specifier_boilerplate!(singleconnect noglobalstate has_subspec typ=Other);
    self_0_is_subspecifier!(...);
}

struct State {
    s : Rc<Specifier>,
    p : Option<Peer>,
    n : Option<BoxedNewPeerFuture>,
    h : Handle,
}

/// This implementation's poll is to be reused many times, both after returning item and error
impl /*Future for */ State {
    //type Item = &'mut Peer;
    //type Error = Box<::std::error::Error>;

    fn poll(&mut self) -> Poll<&mut Peer, Box<::std::error::Error>> {
        let pp = &mut self.p;
        let nn = &mut self.n;

        loop {
            if let Some(ref mut p) = pp {
                return Ok(Async::Ready(p));
            }

            // Peer is not present: trying to create a new one

            if let Some(ref mut bnpf) = nn {
                match bnpf.poll() {
                    Ok(Async::Ready(p)) => {
                        *pp = Some(p);
                        *nn = None;
                        continue;
                    },
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(x) => return Err(x),
                }
            }

            let mut fake_ps : ProgramState = Default::default();
            let pc : PeerConstructor = self.s.construct(&self.h, &mut fake_ps);
            *nn = Some(pc.get_only_first_conn());
        }
    }
}

#[derive(Clone)]
struct PeerHandle(Rc<RefCell<State>>);

macro_rules! getpeer {
    ($state:ident -> $p:ident) => {
        let $p : &mut Peer =
        match $state.poll() {
            Ok(Async::Ready(p)) => p,
            Ok(Async::NotReady) => return wouldblock(),
            Err(e) => {
                let e1 : Box<::std::error::Error+Send+Sync+'static> = format!("{}",e).into();
                let e2 = ::std::io::Error::new(::std::io::ErrorKind::Other,e1);
                return Err(e2);
            },
        };
    }
}

impl State {
    fn reconnect(&mut self) {
        info!("Reconnect");
        self.p = None;
    }
}

macro_rules! main_loop {
    ($state:ident, $p:ident, bytes $e:expr) => {
        main_loop!(qqq $state, $p, do_reconnect, {
            match $e {
                Ok(0) => { do_reconnect = true; }
                Err(e) => {
                    if e.kind() == ::std::io::ErrorKind::WouldBlock {
                        return Err(e);
                    }
                    warn!("{}", e);
                    do_reconnect = true;
                }
                Ok(x) => return Ok(x),
            }
        });
    };
    ($state:ident, $p:ident, none $e:expr) => {
        main_loop!(qqq $state, $p, do_reconnect, {
            match $e {
                Err(e) => {
                    if e.kind() == ::std::io::ErrorKind::WouldBlock {
                        return Err(e);
                    }
                    warn!("{}", e);
                    do_reconnect = true;
                }
                Ok(()) => return Ok(()),
            }
        });
    };
    (qqq $state:ident, $p:ident, $do_reconnect:ident, $the_match:expr) => {
        let mut $do_reconnect = false;
        loop {
            if $do_reconnect {
                $state.reconnect();
                $do_reconnect = false;
            } else {
                getpeer!($state -> $p);
                $the_match
            }
        }
    }
}

impl Read for PeerHandle {
    fn read (&mut self, b:&mut [u8]) -> Result<usize, IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, bytes p.0.read(b));
    }
}
impl AsyncRead for PeerHandle {}

impl Write for PeerHandle {
    fn write (&mut self, b: &[u8]) -> Result<usize, IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, bytes p.1.write(b));
    }
    fn flush (&mut self) -> Result<(), IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, none p.1.flush());
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(),IoError> {
       let mut state = self.0.borrow_mut();
       state.p = None;
       Ok(Async::Ready(()))
    }
}

pub fn autoreconnector(h: Handle, s: Rc<Specifier>) -> BoxedNewPeerFuture
{
    let s = Rc::new(RefCell::new(State{h, s, p : None, n: None}));
    let ph1 = PeerHandle(s.clone());
    let ph2 = PeerHandle(s);
    let peer = Peer::new(ph1, ph2);
    Box::new(ok(peer)) as BoxedNewPeerFuture
}
<commit_msg>Reconnect even though errors<commit_after>extern crate tokio_io;
extern crate futures;

use futures::future::ok;
use std::rc::Rc;
use std::cell::RefCell;

use super::{Peer, BoxedNewPeerFuture};

use tokio_io::{AsyncRead,AsyncWrite};
use std::io::{Read, Write, Error as IoError};

use futures::{Future,Poll,Async};
use super::{once,Specifier,Handle,ProgramState,PeerConstructor,wouldblock};

// TODO: shutdown write part if out writing part is shut down
// TODO: stop if writing part and reading parts are closed (shutdown)?

#[derive(Debug)]
pub struct AutoReconnect(pub Rc<Specifier>);
impl Specifier for AutoReconnect {
    fn construct(&self, h:&Handle, _ps: &mut ProgramState) -> PeerConstructor {
        let mut subspec_globalstate = false;

        for i in self.0.get_info().collect() {
            if i.uses_global_state {
                subspec_globalstate = true;
            }
        }

        if subspec_globalstate {
            let e : Box<::std::error::Error>
            = "Can't use autoreconnect on a specifier that uses global state".to_owned().into();
            once(Box::new(::futures::future::err(e)) as BoxedNewPeerFuture)
        } else {
            //let inner = self.0.construct(h, ps).get_only_first_conn();
            once(autoreconnector(h.clone(), self.0.clone()))
        }
    }
    specifier_boilerplate!(singleconnect noglobalstate has_subspec typ=Other);
    self_0_is_subspecifier!(...);
}

#[derive(Default)]
struct State2 {
    already_warned : bool,
}

struct State {
    s : Rc<Specifier>,
    p : Option<Peer>,
    n : Option<BoxedNewPeerFuture>,
    h : Handle,
    aux : State2,
}

/// This implementation's poll is to be reused many times, both after returning item and error
impl /*Future for */ State {
    //type Item = &'mut Peer;
    //type Error = Box<::std::error::Error>;

    fn poll(&mut self) -> Poll<&mut Peer, Box<::std::error::Error>> {
        let pp = &mut self.p;
        let nn = &mut self.n;

        let aux = &mut self.aux;

        loop {
            if let Some(ref mut p) = pp {
                return Ok(Async::Ready(p));
            }

            // Peer is not present: trying to create a new one

            if let Some(ref mut bnpf) = nn {
                match bnpf.poll() {
                    Ok(Async::Ready(p)) => {
                        *pp = Some(p);
                        *nn = None;
                        continue;
                    },
                    Ok(Async::NotReady) => return Ok(Async::NotReady),
                    Err(_x) => {
                        // Stop on error:
                        //return Err(_x);

                        // Just reconnect again on error:
                        *nn = None;

                        if ! aux.already_warned {
                            aux.already_warned = true;
                            error!("Reconnecting failed. Trying again in tight endless loop.");
                        }
                    },
                }
            }

            let mut fake_ps : ProgramState = Default::default();
            let pc : PeerConstructor = self.s.construct(&self.h, &mut fake_ps);
            *nn = Some(pc.get_only_first_conn());
        }
    }
}

#[derive(Clone)]
struct PeerHandle(Rc<RefCell<State>>);

macro_rules! getpeer {
    ($state:ident -> $p:ident) => {
        let $p : &mut Peer =
        match $state.poll() {
            Ok(Async::Ready(p)) => p,
            Ok(Async::NotReady) => return wouldblock(),
            Err(e) => {
                let e1 : Box<::std::error::Error+Send+Sync+'static> = format!("{}",e).into();
                let e2 = ::std::io::Error::new(::std::io::ErrorKind::Other,e1);
                return Err(e2);
            },
        };
    }
}

impl State {
    fn reconnect(&mut self) {
        info!("Reconnect");
        self.p = None;
    }
}

macro_rules! main_loop {
    ($state:ident, $p:ident, bytes $e:expr) => {
        main_loop!(qqq $state, $p, do_reconnect, {
            match $e {
                Ok(0) => { do_reconnect = true; }
                Err(e) => {
                    if e.kind() == ::std::io::ErrorKind::WouldBlock {
                        return Err(e);
                    }
                    warn!("{}", e);
                    do_reconnect = true;
                }
                Ok(x) => return Ok(x),
            }
        });
    };
    ($state:ident, $p:ident, none $e:expr) => {
        main_loop!(qqq $state, $p, do_reconnect, {
            match $e {
                Err(e) => {
                    if e.kind() == ::std::io::ErrorKind::WouldBlock {
                        return Err(e);
                    }
                    warn!("{}", e);
                    do_reconnect = true;
                }
                Ok(()) => return Ok(()),
            }
        });
    };
    (qqq $state:ident, $p:ident, $do_reconnect:ident, $the_match:expr) => {
        let mut $do_reconnect = false;
        loop {
            if $do_reconnect {
                $state.reconnect();
                $do_reconnect = false;
            } else {
                getpeer!($state -> $p);
                $the_match
            }
        }
    }
}

impl Read for PeerHandle {
    fn read (&mut self, b:&mut [u8]) -> Result<usize, IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, bytes p.0.read(b));
    }
}
impl AsyncRead for PeerHandle {}

impl Write for PeerHandle {
    fn write (&mut self, b: &[u8]) -> Result<usize, IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, bytes p.1.write(b));
    }
    fn flush (&mut self) -> Result<(), IoError> {
        let mut state = self.0.borrow_mut();
        main_loop!(state, p, none p.1.flush());
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(),IoError> {
       let mut state = self.0.borrow_mut();
       state.p = None;
       Ok(Async::Ready(()))
    }
}

pub fn autoreconnector(h: Handle, s: Rc<Specifier>) -> BoxedNewPeerFuture
{
    let s = Rc::new(RefCell::new(
        State{
            h,
            s,
            p : None,
            n: None,
            aux: Default::default(),
    }));
    let ph1 = PeerHandle(s.clone());
    let ph2 = PeerHandle(s);
    let peer = Peer::new(ph1, ph2);
    Box::new(ok(peer)) as BoxedNewPeerFuture
}
<|endoftext|>


<commit_before>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use std::collections::BTreeSet;

use graph::vertex::Vertex;
use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    VertexNotFound,
    FormatError,
    Unexpected,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, false, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
    pub static ref NEXT_KEY_ID_VEC: Vec<u64> = vec![*NEXT_KEY_ID];
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    vertex_id: Id,
    field_id: u64
}

fn empty_list_segment(vertex_id: &Id, level: usize) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", vertex_id.higher, vertex_id.lower, 1);
    let list_id = Id::new(vertex_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

fn count_cell_list(seg: &Cell) -> Result<usize, IdListError> {
    if let &Value::Map(ref map) = &seg.data {
        if let &Value::Array(ref array) = map.get_by_key_id(*LIST_KEY_ID) {
            Ok(array.len())
        } else {
            Err(IdListError::FormatError)
        }
    } else {
        Err(IdListError::FormatError)
    }
}

fn val_is_id(val: &Value, id: &Id) -> bool {
    if let &Value::Id(ref val_id) = val {
        return val_id != id;
    } else {
        return true;
    }
}

fn seg_cell_by_id(txn: &mut Transaction, id: Option<Id>) -> Result<Option<Cell>, IdListError> {
    match id {
        Some(id) => match txn.read(&id) {
            Ok(cell) => Ok(cell),
            Err(e) => Err(IdListError::TxnError(e))
        },
        None => Ok(None)
    }
}

impl<'a> IdList <'a> {
    pub fn from_txn_vertex(txn: &'a mut Transaction, vertex_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            vertex_id: *vertex_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_vertex: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.vertex_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    if id == Id::unit_id() && ensure_vertex {
                        let (list_id, list_value) = empty_list_segment(&self.vertex_id, 0);
                        let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                        match self.txn.write(&list_cell) {
                            Ok(()) => {},
                            Err(e) => return Err(IdListError::TxnError(e))
                        }
                        set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(list_id));
                        Ok(list_id)
                    } else {
                        Ok(id)
                    }
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                Err(IdListError::VertexNotFound)
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let current_seg = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: current_seg,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self, id: Id) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut list_level = 0;
        let mut last_seg = {
            let last_seg_id = {
                let mut segments = IdListSegmentIdIterator::new(&mut self.txn, list_root_id);
                let mut last_seg_id = None;
                for seg in segments {
                    list_level += 1;
                    last_seg_id = Some(seg);
                }
                last_seg_id
            };
            let last_seg = seg_cell_by_id(&mut self.txn, last_seg_id)?;
            if let Some(seg) = last_seg { seg } else { return Err(IdListError::Unexpected); }
        };
        if count_cell_list(&mut last_seg)? >= *LIST_CAPACITY { // create new segment to prevent cell overflow
            list_level += 1;
            let (next_seg_id, next_seg_value) = empty_list_segment(&self.vertex_id, list_level);
            let next_seg_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &next_seg_id, next_seg_value);
            match self.txn.write(&next_seg_cell) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
            set_map_by_key_id(&mut self.txn, &last_seg.id(), *NEXT_KEY_ID, Value::Id(next_seg_id));
            last_seg = next_seg_cell;
        }
        if let &mut Value::Map(ref mut map) = &mut last_seg.data {
            if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                array.push(Value::Id(id));
            } else {
                return Err(IdListError::FormatError);
            }
        } else {
            return Err(IdListError::FormatError);
        }
        match self.txn.update(&last_seg) {
            Ok(()) => Ok(()),
            Err(e) => Err(IdListError::TxnError(e))
        }
    }
    pub fn remove(&mut self, id: Id, all: bool) -> Result<(), IdListError> {
        let id_value = Value::Id(id);
        let mut contained_segs = { // collect affected segment cell ids
            let mut iter = self.iter()?;
            let mut seg_ids = BTreeSet::new();
            while true {
                if let Some(iter_id) = iter.next() {
                    if iter_id == id {
                        if let Some(ref seg) = iter.current_seg {
                            seg_ids.insert(seg.id());
                        } else {
                            return Err(IdListError::Unexpected);
                        }
                    }
                } else {
                    break;
                }
            }
            seg_ids
        };
        for seg_id in &contained_segs { // mutate cell array
            match self.txn.read(seg_id) {
                Ok(Some(mut seg)) => {
                    if let &mut Value::Map(ref mut map) = &mut seg.data {
                        if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                            if all {
                                array.retain(|v| { !val_is_id(v, &id) });
                            } else {
                                let index = match array.iter().position(|v| { val_is_id(v, &id) }) {
                                    Some(pos) => pos, None => return Err(IdListError::Unexpected)
                                };
                                array.remove(index);
                            }
                        } else {
                            return Err(IdListError::FormatError);
                        }
                    } else {
                        return Err(IdListError::FormatError);
                    }
                    self.txn.update(&seg);
                    if !all { break; }
                },
                Ok(None) => return Err(IdListError::Unexpected),
                Err(e) => return Err(IdListError::TxnError(e)),
            }
        }
        return Ok(());
    }
    pub fn clear(&mut self) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let segments: Vec<_> = IdListSegmentIdIterator::new(&mut self.txn, list_root_id).collect();
        for seg_id in segments {
            match self.txn.remove(&seg_id) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
        }
        set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(Id::unit_id()));
        return Ok(())
    }
}

pub struct IdListSegmentIdIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIdIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIdIterator<'a> {
        IdListSegmentIdIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIdIterator<'a> {

    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        if !self.next.is_unit_id() {
            match self.txn.read_selected(&self.next, &*NEXT_KEY_ID_VEC) {
                Ok(Some(fields)) => {
                    let current_id = self.next;
                    if let Some(&Value::Id(ref id)) = fields.get(0) {
                        self.next = *id;
                        self.level += 1;
                        return Some(current_id);
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListSegmentIterator<'a> {
    id_iter: IdListSegmentIdIterator<'a>
}

impl <'a>IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            id_iter: IdListSegmentIdIterator::new(txn, head_id)
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator <'a> {
    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let next_id = self.id_iter.next();
        if let Ok(Some(cell)) = seg_cell_by_id(self.id_iter.txn, next_id) {
            Some(cell)
        } else {
            None
        }
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<commit_msg>rename for generalize<commit_after>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use std::collections::BTreeSet;

use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    ContainerCellNotFound,
    FormatError,
    Unexpected,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, false, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
    pub static ref NEXT_KEY_ID_VEC: Vec<u64> = vec![*NEXT_KEY_ID];
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    container_id: Id,
    field_id: u64
}

fn empty_list_segment(container_id: &Id, level: usize) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", container_id.higher, container_id.lower, 1);
    let list_id = Id::new(container_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

fn count_cell_list(seg: &Cell) -> Result<usize, IdListError> {
    if let &Value::Map(ref map) = &seg.data {
        if let &Value::Array(ref array) = map.get_by_key_id(*LIST_KEY_ID) {
            Ok(array.len())
        } else {
            Err(IdListError::FormatError)
        }
    } else {
        Err(IdListError::FormatError)
    }
}

fn val_is_id(val: &Value, id: &Id) -> bool {
    if let &Value::Id(ref val_id) = val {
        return val_id != id;
    } else {
        return true;
    }
}

fn seg_cell_by_id(txn: &mut Transaction, id: Option<Id>) -> Result<Option<Cell>, IdListError> {
    match id {
        Some(id) => match txn.read(&id) {
            Ok(cell) => Ok(cell),
            Err(e) => Err(IdListError::TxnError(e))
        },
        None => Ok(None)
    }
}

impl<'a> IdList <'a> {
    pub fn from_txn_and_container(txn: &'a mut Transaction, container_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            container_id: *container_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_container: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.container_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    if id == Id::unit_id() && ensure_container {
                        let (list_id, list_value) = empty_list_segment(&self.container_id, 0);
                        let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                        match self.txn.write(&list_cell) {
                            Ok(()) => {},
                            Err(e) => return Err(IdListError::TxnError(e))
                        }
                        set_map_by_key_id(self.txn, &self.container_id, self.field_id, Value::Id(list_id));
                        Ok(list_id)
                    } else {
                        Ok(id)
                    }
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                Err(IdListError::ContainerCellNotFound)
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let current_seg = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: current_seg,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self, id: Id) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut list_level = 0;
        let mut last_seg = {
            let last_seg_id = {
                let mut segments = IdListSegmentIdIterator::new(&mut self.txn, list_root_id);
                let mut last_seg_id = None;
                for seg in segments {
                    list_level += 1;
                    last_seg_id = Some(seg);
                }
                last_seg_id
            };
            let last_seg = seg_cell_by_id(&mut self.txn, last_seg_id)?;
            if let Some(seg) = last_seg { seg } else { return Err(IdListError::Unexpected); }
        };
        if count_cell_list(&mut last_seg)? >= *LIST_CAPACITY { // create new segment to prevent cell overflow
            list_level += 1;
            let (next_seg_id, next_seg_value) = empty_list_segment(&self.container_id, list_level);
            let next_seg_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &next_seg_id, next_seg_value);
            match self.txn.write(&next_seg_cell) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
            set_map_by_key_id(&mut self.txn, &last_seg.id(), *NEXT_KEY_ID, Value::Id(next_seg_id));
            last_seg = next_seg_cell;
        }
        if let &mut Value::Map(ref mut map) = &mut last_seg.data {
            if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                array.push(Value::Id(id));
            } else {
                return Err(IdListError::FormatError);
            }
        } else {
            return Err(IdListError::FormatError);
        }
        match self.txn.update(&last_seg) {
            Ok(()) => Ok(()),
            Err(e) => Err(IdListError::TxnError(e))
        }
    }
    pub fn remove(&mut self, id: Id, all: bool) -> Result<(), IdListError> {
        let id_value = Value::Id(id);
        let mut contained_segs = { // collect affected segment cell ids
            let mut iter = self.iter()?;
            let mut seg_ids = BTreeSet::new();
            while true {
                if let Some(iter_id) = iter.next() {
                    if iter_id == id {
                        if let Some(ref seg) = iter.current_seg {
                            seg_ids.insert(seg.id());
                        } else {
                            return Err(IdListError::Unexpected);
                        }
                    }
                } else {
                    break;
                }
            }
            seg_ids
        };
        for seg_id in &contained_segs { // mutate cell array
            match self.txn.read(seg_id) {
                Ok(Some(mut seg)) => {
                    if let &mut Value::Map(ref mut map) = &mut seg.data {
                        if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                            if all {
                                array.retain(|v| { !val_is_id(v, &id) });
                            } else {
                                let index = match array.iter().position(|v| { val_is_id(v, &id) }) {
                                    Some(pos) => pos, None => return Err(IdListError::Unexpected)
                                };
                                array.remove(index);
                            }
                        } else {
                            return Err(IdListError::FormatError);
                        }
                    } else {
                        return Err(IdListError::FormatError);
                    }
                    self.txn.update(&seg);
                    if !all { break; }
                },
                Ok(None) => return Err(IdListError::Unexpected),
                Err(e) => return Err(IdListError::TxnError(e)),
            }
        }
        return Ok(());
    }
    pub fn clear(&mut self) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let segments: Vec<_> = IdListSegmentIdIterator::new(&mut self.txn, list_root_id).collect();
        for seg_id in segments {
            match self.txn.remove(&seg_id) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
        }
        set_map_by_key_id(self.txn, &self.container_id, self.field_id, Value::Id(Id::unit_id()));
        return Ok(())
    }
}

pub struct IdListSegmentIdIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIdIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIdIterator<'a> {
        IdListSegmentIdIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIdIterator<'a> {

    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        if !self.next.is_unit_id() {
            match self.txn.read_selected(&self.next, &*NEXT_KEY_ID_VEC) {
                Ok(Some(fields)) => {
                    let current_id = self.next;
                    if let Some(&Value::Id(ref id)) = fields.get(0) {
                        self.next = *id;
                        self.level += 1;
                        return Some(current_id);
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListSegmentIterator<'a> {
    id_iter: IdListSegmentIdIterator<'a>
}

impl <'a>IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            id_iter: IdListSegmentIdIterator::new(txn, head_id)
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator <'a> {
    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let next_id = self.id_iter.next();
        if let Ok(Some(cell)) = seg_cell_by_id(self.id_iter.txn, next_id) {
            Some(cell)
        } else {
            None
        }
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utils for forming gzchunked streams.

mod read;
mod write;

pub use write::{Encoder, Compression};
pub use read::{Decoder};

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_encode_and_decode_empty() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        let encoded_block = encoder.next_chunk().unwrap();
        // This is because the block should at least contain gzip header.
        assert!(!encoded_block.is_empty());
        decoder.write(encoded_block.as_slice()).unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_all_in_one_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        encoder.write(&[]).unwrap();
        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        encoder.write(&[1]).unwrap();

        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_one_per_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_random() {
        use rand::{Rng as _, SeedableRng as _};
        let mut rng = rand::rngs::StdRng::seed_from_u64(20200509);

        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();
        let mut expected_data: Vec<Vec<u8>> = Vec::new();
        let mut decoded_data: Vec<Vec<u8>> = Vec::new();
        for _ in 0..256 {
            let size = rng.gen_range(128, 256);
            let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
            encoder.write(data.as_slice()).unwrap();
            if let Some(block) = encoder.try_next_chunk().unwrap() {
                decoder.write(block.as_slice()).unwrap();
                while let Some(data) = decoder.try_next_data() {
                    decoded_data.push(data);
                }
            }
            expected_data.push(data);
        }
        let last_block = encoder.next_chunk().unwrap();
        decoder.write(last_block.as_slice()).unwrap();
        while let Some(data) = decoder.try_next_data() {
            decoded_data.push(data);
        }
        assert_eq!(decoded_data, expected_data);
    }

    #[test]
    fn test_encode_and_decode_max_compression() {
        let mut encoder = Encoder::new(Compression::new(9));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_min_compression() {
        let mut encoder = Encoder::new(Compression::new(0));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    // Should panic because the underlying gzip only supports levels from 0 to 9.
    #[test]
    #[should_panic]
    fn test_huge_compression() {
        Encoder::new(Compression::new(100500));
    }
}
<commit_msg>Export gzchunked encoding and decoding utilities.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Utils for forming gzchunked streams.

mod read;
mod write;

pub use write::{Encoder, Compression};
pub use read::{Decoder};

pub use write::{encode, Encode, EncodeOpts};
pub use read::{decode};

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_encode_and_decode_empty() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        let encoded_block = encoder.next_chunk().unwrap();
        // This is because the block should at least contain gzip header.
        assert!(!encoded_block.is_empty());
        decoder.write(encoded_block.as_slice()).unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_all_in_one_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        encoder.write(&[]).unwrap();
        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        encoder.write(&[1]).unwrap();

        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();

        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_one_per_block() {
        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(Vec::new()));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4, 5, 6, 7, 8]));
        assert_eq!(decoder.try_next_data(), None);

        encoder.write(&[1]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_random() {
        use rand::{Rng as _, SeedableRng as _};
        let mut rng = rand::rngs::StdRng::seed_from_u64(20200509);

        let mut encoder = Encoder::new(Compression::default());
        let mut decoder = Decoder::new();
        let mut expected_data: Vec<Vec<u8>> = Vec::new();
        let mut decoded_data: Vec<Vec<u8>> = Vec::new();
        for _ in 0..256 {
            let size = rng.gen_range(128, 256);
            let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
            encoder.write(data.as_slice()).unwrap();
            if let Some(block) = encoder.try_next_chunk().unwrap() {
                decoder.write(block.as_slice()).unwrap();
                while let Some(data) = decoder.try_next_data() {
                    decoded_data.push(data);
                }
            }
            expected_data.push(data);
        }
        let last_block = encoder.next_chunk().unwrap();
        decoder.write(last_block.as_slice()).unwrap();
        while let Some(data) = decoder.try_next_data() {
            decoded_data.push(data);
        }
        assert_eq!(decoded_data, expected_data);
    }

    #[test]
    fn test_encode_and_decode_max_compression() {
        let mut encoder = Encoder::new(Compression::new(9));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    #[test]
    fn test_encode_and_decode_min_compression() {
        let mut encoder = Encoder::new(Compression::new(0));
        let mut decoder = Decoder::new();

        encoder.write(&[1, 2, 3, 4]).unwrap();
        let encoded_block = encoder.next_chunk().unwrap();
        decoder.write(encoded_block.as_slice()).unwrap();
        assert_eq!(decoder.try_next_data(), Some(vec![1, 2, 3, 4]));
        assert_eq!(decoder.try_next_data(), None);
    }

    // Should panic because the underlying gzip only supports levels from 0 to 9.
    #[test]
    #[should_panic]
    fn test_huge_compression() {
        Encoder::new(Compression::new(100500));
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(globs)]

extern crate router = "route_recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + 'static + Share>>>
}

macro_rules! method_map(
    ($method:ident => $variant:ty) => (
        pub fn $method<'a, H: 'static + Handler>(&'a mut self, pattern: &str, handler: H)
                                                -> &'a mut RouteBuilder
        {
            self.map(conduit::$variant, pattern, handler)
        }
    )
)

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + 'static + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: 'static + Handler + Share>(&'a mut self,
                                                 method: Method,
                                                 pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + 'static + Share>);
        }
        self
    }

    pub fn get<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                  handler: H)
                                                  -> &'a mut RouteBuilder
    {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                    handler: H)
                                                    -> &'a mut RouteBuilder
    {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                  handler: H)
                                                  -> &'a mut RouteBuilder
    {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            self.recognize(&method, path).unwrap()
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a mut Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a mut Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

//impl<T: Request> RequestParams for T {}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn as_conduit_handler() {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", handler1);
        router.get("/posts/:id", handler1);

        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "1, Get".to_str());

        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "10, Post".to_str());
    }

    fn handler1(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"]);
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<commit_msg>Don't fail for an unrecognized path<commit_after>#![feature(macro_rules)]
#![feature(globs)]

extern crate router = "route_recognizer";
extern crate conduit;

use std::collections::HashMap;
use std::any::{Any, AnyRefExt};
use std::fmt::Show;

use router::{Router, Match};
use conduit::{Method, Handler, Request, Response};

pub struct RouteBuilder {
    routers: HashMap<Method, Router<Box<Handler + 'static + Share>>>
}

macro_rules! method_map(
    ($method:ident => $variant:ty) => (
        pub fn $method<'a, H: 'static + Handler>(&'a mut self, pattern: &str, handler: H)
                                                -> &'a mut RouteBuilder
        {
            self.map(conduit::$variant, pattern, handler)
        }
    )
)

impl RouteBuilder {
    pub fn new() -> RouteBuilder {
        RouteBuilder { routers: HashMap::new() }
    }

    pub fn recognize<'a>(&'a self, method: &Method, path: &str)
                         -> Result<Match<&'a Box<Handler + 'static + Share>>, String>
    {
        match self.routers.find(method) {
            None => Err(format!("No router found for {}", method)),
            Some(router) => router.recognize(path)
        }
    }

    pub fn map<'a, H: 'static + Handler + Share>(&'a mut self,
                                                 method: Method,
                                                 pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        {
            let router = self.routers.find_or_insert_with(method, |_| Router::new());
            router.add(pattern, box handler as Box<Handler + 'static + Share>);
        }
        self
    }

    pub fn get<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        self.map(conduit::Get, pattern, handler)
    }

    pub fn post<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                  handler: H)
                                                  -> &'a mut RouteBuilder
    {
        self.map(conduit::Post, pattern, handler)
    }

    pub fn put<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                 handler: H)
                                                 -> &'a mut RouteBuilder
    {
        self.map(conduit::Put, pattern, handler)
    }

    pub fn delete<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                    handler: H)
                                                    -> &'a mut RouteBuilder
    {
        self.map(conduit::Delete, pattern, handler)
    }

    pub fn head<'a, H: 'static + Handler + Share>(&'a mut self, pattern: &str,
                                                  handler: H)
                                                  -> &'a mut RouteBuilder
    {
        self.map(conduit::Head, pattern, handler)
    }
}

impl conduit::Handler for RouteBuilder {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let m = {
            let method = request.method();
            let path = request.path();

            match self.recognize(&method, path) {
                Ok(m) => m,
                Err(e) => return Err(box e as Box<Show>)
            }
        };

        {
            let extensions = request.mut_extensions();
            extensions.insert("router.params", box m.params.clone() as Box<Any>);
        }

        (*m.handler).call(request)
    }
}

pub trait RequestParams<'a> {
    fn params(self) -> &'a router::Params;
}

pub fn params<'a>(req: &'a mut Request) -> &'a router::Params {
    req.extensions().find(&"router.params")
        .and_then(|a| a.as_ref::<router::Params>())
        .expect("Missing params")
}

impl<'a> RequestParams<'a> for &'a mut Request {
    fn params(self) -> &'a router::Params {
        params(self)
    }
}

//impl<T: Request> RequestParams for T {}

#[cfg(test)]
mod tests {
    extern crate semver;
    use std::io::net::ip::IpAddr;
    use std::collections::HashMap;
    use std::io::MemReader;
    use super::*;

    use conduit;
    use conduit::{Handler, Method, Scheme, Host, Headers, Extensions};

    struct RequestSentinel {
        method: Method,
        path: String,
        extensions: conduit::Extensions
    }

    impl RequestSentinel {
        fn new(method: Method, path: &'static str) -> RequestSentinel {
            RequestSentinel {
                path: path.to_str(),
                extensions: HashMap::new(),
                method: method
            }
        }
    }

    impl conduit::Request for RequestSentinel {
        fn http_version(&self) -> semver::Version { unimplemented!() }
        fn conduit_version(&self) -> semver::Version { unimplemented!() }
        fn method(&self) -> Method { self.method }
        fn scheme(&self) -> Scheme { unimplemented!() }
        fn host<'a>(&'a self) -> Host<'a> { unimplemented!() }
        fn virtual_root<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn path<'a>(&'a self) -> &'a str {
            self.path.as_slice()
        }
        fn query_string<'a>(&'a self) -> Option<&'a str> { unimplemented!() }
        fn remote_ip(&self) -> IpAddr { unimplemented!() }
        fn content_length(&self) -> Option<uint> { unimplemented!() }
        fn headers<'a>(&'a self) -> &'a Headers { unimplemented!() }
        fn body<'a>(&'a mut self) -> &'a mut Reader { unimplemented!() }
        fn extensions<'a>(&'a self) -> &'a Extensions {
            &self.extensions
        }
        fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
            &mut self.extensions
        }
    }

    #[test]
    fn as_conduit_handler() {
        let mut router = RouteBuilder::new();
        router.post("/posts/:id", handler1);
        router.get("/posts/:id", handler1);

        let mut req = RequestSentinel::new(conduit::Get, "/posts/1");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "1, Get".to_str());

        let mut req = RequestSentinel::new(conduit::Post, "/posts/10");
        let mut res = router.call(&mut req).ok().expect("No response");

        assert_eq!(res.status, (200, "OK"));
        assert_eq!(res.body.read_to_str().unwrap(), "10, Post".to_str());

        let mut req = RequestSentinel::new(conduit::Post, "/nonexistent");
        router.call(&mut req).err().expect("No response");
    }

    fn handler1(req: &mut conduit::Request) -> Result<conduit::Response, ()> {
        let mut res = vec!();
        res.push(req.params()["id"]);
        res.push(format!("{}", req.method()));

        Ok(conduit::Response {
            status: (200, "OK"),
            headers: HashMap::new(),
            body: box MemReader::new(res.connect(", ").into_bytes())
        })
    }
}
<|endoftext|>


<commit_before>macro_rules! elf_compression_header {
    () => {
        use plain;
        // Declare that this is a plain type.
        unsafe impl plain::Plain for CompressionHeader {}

        impl ::core::fmt::Debug for CompressionHeader {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                write!(f,
                       "ch_type: {} ch_size: 0x{} ch_addralign: 0x{:x}",
                       self.ch_type,
                       self.ch_size,
                       self.ch_addralign)
            }
        }
    }
}

/// ZLIB/DEFLATE algorithm.
pub const ELFCOMPRESS_ZLIB: u32 = 1;
/// Start of OS-specific.
pub const ELFCOMPRESS_LOOS: u32 = 0x60000000;
/// End of OS-specific.
pub const ELFCOMPRESS_HIOS: u32 = 0x6fffffff;
/// Start of processor-specific.
pub const ELFCOMPRESS_LOPROC: u32 = 0x70000000;
/// End of processor-specific.
pub const ELFCOMPRESS_HIPROC: u32 = 0x7fffffff;

macro_rules! elf_compression_header_std_impl { ($size:ty) => {

    #[cfg(test)]
    mod test {
        use super::*;
        #[test]
        fn size_of() {
            assert_eq!(::std::mem::size_of::<CompressionHeader>(), SIZEOF_CHDR);
        }
    }

    if_alloc! {
        use elf::compression_header::CompressionHeader as ElfCompressionHeader;

        use plain::Plain;

        if_std! {
            use error::Result;

            use std::fs::File;
            use std::io::{Read, Seek};
            use std::io::SeekFrom::Start;
        }

        impl From<CompressionHeader> for ElfCompressionHeader {
            fn from(ch: CompressionHeader) -> Self {
                ElfCompressionHeader {
                    ch_type: ch.ch_type,
                    ch_size: ch.ch_size as u64,
                    ch_addralign: ch.ch_addralign as u64,
                }
            }
        }

        impl CompressionHeader {
            pub fn from_bytes(bytes: &[u8]) -> CompressionHeader {
                let mut chdr = CompressionHeader::default();
                chdr.copy_from_bytes(bytes).expect("buffer is too short for header");
                chdr
            }

            #[cfg(feature = "std")]
            pub fn from_fd(fd: &mut File, offset: u64) -> Result<CompressionHeader> {
                let mut chdr = CompressionHeader::default();
                try!(fd.seek(Start(offset)));
                unsafe {
                    try!(fd.read(plain::as_mut_bytes(&mut chdr)));
                }
                Ok(chdr)
            }
        }
    } // end if_alloc
};}

pub mod compression_header32 {
    pub use elf::compression_header::*;

    #[repr(C)]
    #[derive(Copy, Clone, Eq, PartialEq, Default)]
    #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
    /// The compression header is used at the start of SHF_COMPRESSED sections
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        /// Uncompressed data size
        pub ch_size: u32,
        /// Uncompressed data alignment
        pub ch_addralign: u32,
    }

    elf_compression_header!();

    pub const SIZEOF_CHDR: usize = 12;

    elf_compression_header_std_impl!(u32);

    impl From<ElfCompressionHeader> for CompressionHeader {
        fn from(ch: ElfCompressionHeader) -> Self {
            CompressionHeader {
                ch_type: ch.ch_type,
                ch_size: ch.ch_size as u32,
                ch_addralign: ch.ch_addralign as u32,
            }
        }
    }
}

pub mod compression_header64 {
    pub use elf::compression_header::*;

    #[repr(C)]
    #[derive(Copy, Clone, Eq, PartialEq, Default)]
    #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
    /// The compression header is used at the start of SHF_COMPRESSED sections
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        pub ch_reserved: u32,
        /// Uncompressed data size
        pub ch_size: u64,
        /// Uncompressed data alignment
        pub ch_addralign: u64,
    }

    elf_compression_header!();

    pub const SIZEOF_CHDR: usize = 24;

    elf_compression_header_std_impl!(u64);

    impl From<ElfCompressionHeader> for CompressionHeader {
        fn from(ch: ElfCompressionHeader) -> Self {
            CompressionHeader {
                ch_type: ch.ch_type,
                ch_reserved: 0,
                ch_size: ch.ch_size as u64,
                ch_addralign: ch.ch_addralign as u64,
            }
        }
    }
}

///////////////////////////////
// Std/analysis/Unified Structs
///////////////////////////////

if_alloc! {
    use error;
    use core::fmt;
    use core::result;
    use scroll::ctx;
    use container::{Container, Ctx};

    #[derive(Default, PartialEq, Clone)]
    /// A unified CompressionHeader - convertable to and from 32-bit and 64-bit variants
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        /// Uncompressed data size
        pub ch_size: u64,
        /// Uncompressed data alignment
        pub ch_addralign: u64,
    }

    impl CompressionHeader {
        /// Return the size of the underlying compression header, given a `container`
        #[inline]
        pub fn size(ctx: &Ctx) -> usize {
            use scroll::ctx::SizeWith;
            Self::size_with(ctx)
        }
        pub fn new() -> Self {
            CompressionHeader {
                ch_type: 0,
                ch_size: 0,
                ch_addralign: 2 << 8,
            }
        }
        /// Parse a compression header from `bytes` at `offset`, using the given `ctx`
        #[cfg(feature = "endian_fd")]
        pub fn parse(bytes: &[u8], mut offset: usize, ctx: Ctx) -> error::Result<CompressionHeader> {
            use scroll::Pread;
            bytes.gread_with(&mut offset, ctx)
        }
    }

    impl fmt::Debug for CompressionHeader {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f,
                   "ch_type: {} ch_size: 0x{} ch_addralign: 0x{:x}",
                   self.ch_type,
                   self.ch_size,
                   self.ch_addralign)
        }
    }

    impl ctx::SizeWith<Ctx> for CompressionHeader {
        type Units = usize;
        fn size_with( &Ctx { container, .. }: &Ctx) -> Self::Units {
            match container {
                Container::Little => {
                    compression_header32::SIZEOF_CHDR
                },
                Container::Big => {
                    compression_header64::SIZEOF_CHDR
                },
            }
        }
    }

    impl<'a> ctx::TryFromCtx<'a, Ctx> for CompressionHeader {
        type Error = ::error::Error;
        type Size = usize;
        fn try_from_ctx(bytes: &'a [u8], Ctx {container, le}: Ctx) -> result::Result<(Self, Self::Size), Self::Error> {
            use scroll::Pread;
            let res = match container {
                Container::Little => {
                    (bytes.pread_with::<compression_header32::CompressionHeader>(0, le)?.into(), compression_header32::SIZEOF_CHDR)
                },
                Container::Big => {
                    (bytes.pread_with::<compression_header64::CompressionHeader>(0, le)?.into(), compression_header64::SIZEOF_CHDR)
                }
            };
            Ok(res)
        }
    }

    impl ctx::TryIntoCtx<Ctx> for CompressionHeader {
        type Error = ::error::Error;
        type Size = usize;
        fn try_into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) -> result::Result<Self::Size, Self::Error> {
            use scroll::Pwrite;
            match container {
                Container::Little => {
                    let chdr: compression_header32::CompressionHeader = self.into();
                    Ok(bytes.pwrite_with(chdr, 0, le)?)
                },
                Container::Big => {
                    let chdr: compression_header64::CompressionHeader = self.into();
                    Ok(bytes.pwrite_with(chdr, 0, le)?)
                }
            }
        }
    }
    impl ctx::IntoCtx<Ctx> for CompressionHeader {
        fn into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) {
            use scroll::Pwrite;
            match container {
                Container::Little => {
                    let chdr: compression_header32::CompressionHeader = self.into();
                    bytes.pwrite_with(chdr, 0, le).unwrap();
                },
                Container::Big => {
                    let chdr: compression_header64::CompressionHeader = self.into();
                    bytes.pwrite_with(chdr, 0, le).unwrap();
                }
            }
        }
    }
} // end if_alloc
<commit_msg>elf: fix no_std build<commit_after>macro_rules! elf_compression_header {
    () => {
        use plain;
        // Declare that this is a plain type.
        unsafe impl plain::Plain for CompressionHeader {}

        impl ::core::fmt::Debug for CompressionHeader {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                write!(f,
                       "ch_type: {} ch_size: 0x{} ch_addralign: 0x{:x}",
                       self.ch_type,
                       self.ch_size,
                       self.ch_addralign)
            }
        }
    }
}

/// ZLIB/DEFLATE algorithm.
pub const ELFCOMPRESS_ZLIB: u32 = 1;
/// Start of OS-specific.
pub const ELFCOMPRESS_LOOS: u32 = 0x60000000;
/// End of OS-specific.
pub const ELFCOMPRESS_HIOS: u32 = 0x6fffffff;
/// Start of processor-specific.
pub const ELFCOMPRESS_LOPROC: u32 = 0x70000000;
/// End of processor-specific.
pub const ELFCOMPRESS_HIPROC: u32 = 0x7fffffff;

macro_rules! elf_compression_header_std_impl { ($size:ty) => {

    #[cfg(test)]
    mod test {
        use super::*;
        #[test]
        fn size_of() {
            assert_eq!(::std::mem::size_of::<CompressionHeader>(), SIZEOF_CHDR);
        }
    }

    if_alloc! {
        use elf::compression_header::CompressionHeader as ElfCompressionHeader;

        use plain::Plain;

        if_std! {
            use error::Result;

            use std::fs::File;
            use std::io::{Read, Seek};
            use std::io::SeekFrom::Start;
        }

        impl From<CompressionHeader> for ElfCompressionHeader {
            fn from(ch: CompressionHeader) -> Self {
                ElfCompressionHeader {
                    ch_type: ch.ch_type,
                    ch_size: ch.ch_size as u64,
                    ch_addralign: ch.ch_addralign as u64,
                }
            }
        }

        impl CompressionHeader {
            pub fn from_bytes(bytes: &[u8]) -> CompressionHeader {
                let mut chdr = CompressionHeader::default();
                chdr.copy_from_bytes(bytes).expect("buffer is too short for header");
                chdr
            }

            #[cfg(feature = "std")]
            pub fn from_fd(fd: &mut File, offset: u64) -> Result<CompressionHeader> {
                let mut chdr = CompressionHeader::default();
                try!(fd.seek(Start(offset)));
                unsafe {
                    try!(fd.read(plain::as_mut_bytes(&mut chdr)));
                }
                Ok(chdr)
            }
        }
    } // end if_alloc
};}

pub mod compression_header32 {
    pub use elf::compression_header::*;

    #[repr(C)]
    #[derive(Copy, Clone, Eq, PartialEq, Default)]
    #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
    /// The compression header is used at the start of SHF_COMPRESSED sections
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        /// Uncompressed data size
        pub ch_size: u32,
        /// Uncompressed data alignment
        pub ch_addralign: u32,
    }

    elf_compression_header!();

    pub const SIZEOF_CHDR: usize = 12;

    elf_compression_header_std_impl!(u32);

    if_alloc! {
        impl From<ElfCompressionHeader> for CompressionHeader {
            fn from(ch: ElfCompressionHeader) -> Self {
                CompressionHeader {
                    ch_type: ch.ch_type,
                    ch_size: ch.ch_size as u32,
                    ch_addralign: ch.ch_addralign as u32,
                }
            }
        }
    }
}

pub mod compression_header64 {
    pub use elf::compression_header::*;

    #[repr(C)]
    #[derive(Copy, Clone, Eq, PartialEq, Default)]
    #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))]
    /// The compression header is used at the start of SHF_COMPRESSED sections
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        pub ch_reserved: u32,
        /// Uncompressed data size
        pub ch_size: u64,
        /// Uncompressed data alignment
        pub ch_addralign: u64,
    }

    elf_compression_header!();

    pub const SIZEOF_CHDR: usize = 24;

    elf_compression_header_std_impl!(u64);

    if_alloc! {
        impl From<ElfCompressionHeader> for CompressionHeader {
            fn from(ch: ElfCompressionHeader) -> Self {
                CompressionHeader {
                    ch_type: ch.ch_type,
                    ch_reserved: 0,
                    ch_size: ch.ch_size as u64,
                    ch_addralign: ch.ch_addralign as u64,
                }
            }
        }
    }
}

///////////////////////////////
// Std/analysis/Unified Structs
///////////////////////////////

if_alloc! {
    use error;
    use core::fmt;
    use core::result;
    use scroll::ctx;
    use container::{Container, Ctx};

    #[derive(Default, PartialEq, Clone)]
    /// A unified CompressionHeader - convertable to and from 32-bit and 64-bit variants
    pub struct CompressionHeader {
        /// Compression format
        pub ch_type: u32,
        /// Uncompressed data size
        pub ch_size: u64,
        /// Uncompressed data alignment
        pub ch_addralign: u64,
    }

    impl CompressionHeader {
        /// Return the size of the underlying compression header, given a `container`
        #[inline]
        pub fn size(ctx: &Ctx) -> usize {
            use scroll::ctx::SizeWith;
            Self::size_with(ctx)
        }
        pub fn new() -> Self {
            CompressionHeader {
                ch_type: 0,
                ch_size: 0,
                ch_addralign: 2 << 8,
            }
        }
        /// Parse a compression header from `bytes` at `offset`, using the given `ctx`
        #[cfg(feature = "endian_fd")]
        pub fn parse(bytes: &[u8], mut offset: usize, ctx: Ctx) -> error::Result<CompressionHeader> {
            use scroll::Pread;
            bytes.gread_with(&mut offset, ctx)
        }
    }

    impl fmt::Debug for CompressionHeader {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f,
                   "ch_type: {} ch_size: 0x{} ch_addralign: 0x{:x}",
                   self.ch_type,
                   self.ch_size,
                   self.ch_addralign)
        }
    }

    impl ctx::SizeWith<Ctx> for CompressionHeader {
        type Units = usize;
        fn size_with( &Ctx { container, .. }: &Ctx) -> Self::Units {
            match container {
                Container::Little => {
                    compression_header32::SIZEOF_CHDR
                },
                Container::Big => {
                    compression_header64::SIZEOF_CHDR
                },
            }
        }
    }

    impl<'a> ctx::TryFromCtx<'a, Ctx> for CompressionHeader {
        type Error = ::error::Error;
        type Size = usize;
        fn try_from_ctx(bytes: &'a [u8], Ctx {container, le}: Ctx) -> result::Result<(Self, Self::Size), Self::Error> {
            use scroll::Pread;
            let res = match container {
                Container::Little => {
                    (bytes.pread_with::<compression_header32::CompressionHeader>(0, le)?.into(), compression_header32::SIZEOF_CHDR)
                },
                Container::Big => {
                    (bytes.pread_with::<compression_header64::CompressionHeader>(0, le)?.into(), compression_header64::SIZEOF_CHDR)
                }
            };
            Ok(res)
        }
    }

    impl ctx::TryIntoCtx<Ctx> for CompressionHeader {
        type Error = ::error::Error;
        type Size = usize;
        fn try_into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) -> result::Result<Self::Size, Self::Error> {
            use scroll::Pwrite;
            match container {
                Container::Little => {
                    let chdr: compression_header32::CompressionHeader = self.into();
                    Ok(bytes.pwrite_with(chdr, 0, le)?)
                },
                Container::Big => {
                    let chdr: compression_header64::CompressionHeader = self.into();
                    Ok(bytes.pwrite_with(chdr, 0, le)?)
                }
            }
        }
    }
    impl ctx::IntoCtx<Ctx> for CompressionHeader {
        fn into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) {
            use scroll::Pwrite;
            match container {
                Container::Little => {
                    let chdr: compression_header32::CompressionHeader = self.into();
                    bytes.pwrite_with(chdr, 0, le).unwrap();
                },
                Container::Big => {
                    let chdr: compression_header64::CompressionHeader = self.into();
                    bytes.pwrite_with(chdr, 0, le).unwrap();
                }
            }
        }
    }
} // end if_alloc
<|endoftext|>


<commit_before><commit_msg>implement SocketHandler for rustls' ServerSession<commit_after><|endoftext|>


<commit_before>mod mtl_command_buffer;
mod mtl_command_queue;
mod mtl_compute_pipeline_state;
mod mtl_device;
mod mtl_drawable;
mod mtl_function;
mod mtl_library;
mod mtl_texture;

pub use self::mtl_command_buffer::MTLCommandBuffer;
pub use self::mtl_command_queue::MTLCommandQueue;
pub use self::mtl_compute_pipeline_state::MTLComputePipelineState;
pub use self::mtl_device::MTLDevice;
pub use self::mtl_device::{MTLNewComputePipelineStateCompletionHandler,
                           MTLNewComputePipelineStateWithReflectionCompletionHandler,
                           MTLNewLibraryCompletionHandler,
                           MTLNewRenderPipelineStateWithReflectionCompletionHandler,
                           MTLNewRenderPipleineStateCompletionHandler};
pub use self::mtl_drawable::MTLDrawable;
pub use self::mtl_function::{MTLFunction, MTLFunctionType};
pub use self::mtl_library::MTLLibrary;
pub use self::mtl_library::{MTLLanguageVersion, MTLLibraryError, MTLLibraryErrorDomain,
                            MTLRenderPipelineError, MTLRenderPipelineErrorDomain};
pub use self::mtl_texture::{MTLTexture, MTLTextureType, MTLTextureUsage};
<commit_msg>format<commit_after>mod mtl_command_buffer;
mod mtl_command_queue;
mod mtl_compute_pipeline_state;
mod mtl_device;
mod mtl_drawable;
mod mtl_function;
mod mtl_library;
mod mtl_texture;

pub use self::mtl_command_buffer::MTLCommandBuffer;
pub use self::mtl_command_queue::MTLCommandQueue;
pub use self::mtl_compute_pipeline_state::MTLComputePipelineState;
pub use self::mtl_device::MTLDevice;
pub use self::mtl_device::{MTLNewComputePipelineStateCompletionHandler,
                           MTLNewComputePipelineStateWithReflectionCompletionHandler,
                           MTLNewLibraryCompletionHandler,
                           MTLNewRenderPipelineStateWithReflectionCompletionHandler,
                           MTLNewRenderPipleineStateCompletionHandler};
pub use self::mtl_drawable::MTLDrawable;
pub use self::mtl_function::{MTLFunction, MTLFunctionType};
pub use self::mtl_library::{MTLLanguageVersion, MTLLibrary, MTLLibraryError,
                            MTLLibraryErrorDomain, MTLRenderPipelineError,
                            MTLRenderPipelineErrorDomain};
pub use self::mtl_texture::{MTLTexture, MTLTextureType, MTLTextureUsage};
<|endoftext|>