<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::collections::BTreeMap;
use std::mem;

use bindgen::config::Config;
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
    AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use bindgen::library::Library;
use bindgen::monomorph::Monomorphs;

/// An item is any type of rust item besides a function
pub trait Item {
    fn path(&self) -> &Path;
    fn name(&self) -> &str {
        self.path().name()
    }
    fn export_name(&self) -> &str {
        self.name()
    }
    fn cfg(&self) -> Option<&Cfg>;
    fn annotations(&self) -> &AnnotationSet;
    fn annotations_mut(&mut self) -> &mut AnnotationSet;

    fn container(&self) -> ItemContainer;

    fn collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver) {
        unimplemented!()
    }
    fn resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver) {
        unimplemented!()
    }
    fn rename_for_config(&mut self, _config: &Config) {}
    fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
    fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) {
        unreachable!("Cannot instantiate {} as a generic.", self.name())
    }
}

#[derive(Debug, Clone)]
pub enum ItemContainer {
    Constant(Constant),
    Static(Static),
    OpaqueItem(OpaqueItem),
    Struct(Struct),
    Union(Union),
    Enum(Enum),
    Typedef(Typedef),
}

impl ItemContainer {
    pub fn deref(&self) -> &Item {
        match self {
            &ItemContainer::Constant(ref x) => x,
            &ItemContainer::Static(ref x) => x,
            &ItemContainer::OpaqueItem(ref x) => x,
            &ItemContainer::Struct(ref x) => x,
            &ItemContainer::Union(ref x) => x,
            &ItemContainer::Enum(ref x) => x,
            &ItemContainer::Typedef(ref x) => x,
        }
    }
}

#[derive(Debug, Clone)]
pub enum ItemValue<T: Item> {
    Cfg(Vec<T>),
    Single(T),
}

#[derive(Debug, Clone)]
pub struct ItemMap<T: Item> {
    data: BTreeMap<Path, ItemValue<T>>,
}

impl<T: Item + Clone> ItemMap<T> {
    pub fn new() -> ItemMap<T> {
        ItemMap {
            data: BTreeMap::new(),
        }
    }

    pub fn rebuild(&mut self) {
        let old = mem::replace(self, ItemMap::new());
        old.for_all_items(|x| {
            self.try_insert(x.clone());
        });
    }

    pub fn try_insert(&mut self, item: T) -> bool {
        match (item.cfg().is_some(), self.data.get_mut(item.path())) {
            (true, Some(&mut ItemValue::Cfg(ref mut items))) => {
                items.push(item);
                return true;
            }
            (false, Some(&mut ItemValue::Cfg(_))) => {
                return false;
            }
            (true, Some(&mut ItemValue::Single(_))) => {
                return false;
            }
            (false, Some(&mut ItemValue::Single(_))) => {
                return false;
            }
            _ => {}
        }

        let path = item.path().clone();
        if item.cfg().is_some() {
            self.data.insert(path, ItemValue::Cfg(vec![item]));
        } else {
            self.data.insert(path, ItemValue::Single(item));
        }

        true
    }

    pub fn extend_with(&mut self, other: &ItemMap<T>) {
        other.for_all_items(|x| {
            self.try_insert(x.clone());
        });
    }

    pub fn to_vec(&self) -> Vec<T> {
        let mut result = Vec::with_capacity(self.data.len());
        for container in self.data.values() {
            match container {
                &ItemValue::Cfg(ref items) => result.extend_from_slice(items),
                &ItemValue::Single(ref item) => {
                    result.push(item.clone());
                }
            }
        }
        result
    }

    pub fn get_items(&self, path: &Path) -> Option<Vec<ItemContainer>> {
        Some(match *self.data.get(path)? {
            ItemValue::Cfg(ref items) => items.iter().map(|x| x.container()).collect(),
            ItemValue::Single(ref item) => vec![item.container()],
        })
    }

    pub fn filter<F>(&mut self, callback: F)
    where
        F: Fn(&T) -> bool,
    {
        let data = mem::replace(&mut self.data, BTreeMap::new());

        for (name, container) in data {
            match container {
                ItemValue::Cfg(items) => {
                    let mut new_items = Vec::new();
                    for item in items {
                        if !callback(&item) {
                            new_items.push(item);
                        }
                    }
                    if new_items.len() > 0 {
                        self.data.insert(name, ItemValue::Cfg(new_items));
                    }
                }
                ItemValue::Single(item) => {
                    if !callback(&item) {
                        self.data.insert(name, ItemValue::Single(item));
                    }
                }
            }
        }
    }

    pub fn for_all_items<F>(&self, mut callback: F)
    where
        F: FnMut(&T),
    {
        for container in self.data.values() {
            match container {
                &ItemValue::Cfg(ref items) => {
                    for item in items {
                        callback(item);
                    }
                }
                &ItemValue::Single(ref item) => callback(item),
            }
        }
    }

    pub fn for_all_items_mut<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut T),
    {
        for container in self.data.values_mut() {
            match container {
                &mut ItemValue::Cfg(ref mut items) => {
                    for item in items {
                        callback(item);
                    }
                }
                &mut ItemValue::Single(ref mut item) => callback(item),
            }
        }
    }

    pub fn for_items<F>(&self, path: &Path, mut callback: F)
    where
        F: FnMut(&T),
    {
        match self.data.get(path) {
            Some(&ItemValue::Cfg(ref items)) => {
                for item in items {
                    callback(item);
                }
            }
            Some(&ItemValue::Single(ref item)) => {
                callback(item);
            }
            None => {}
        }
    }

    pub fn for_items_mut<F>(&mut self, path: &Path, mut callback: F)
    where
        F: FnMut(&mut T),
    {
        match self.data.get_mut(path) {
            Some(&mut ItemValue::Cfg(ref mut items)) => {
                for item in items {
                    callback(item);
                }
            }
            Some(&mut ItemValue::Single(ref mut item)) => {
                callback(item);
            }
            None => {}
        }
    }
}
<commit_msg>Update to use dyn when needed<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::collections::BTreeMap;
use std::mem;

use bindgen::config::Config;
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{
    AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use bindgen::library::Library;
use bindgen::monomorph::Monomorphs;

/// An item is any type of rust item besides a function
pub trait Item {
    fn path(&self) -> &Path;
    fn name(&self) -> &str {
        self.path().name()
    }
    fn export_name(&self) -> &str {
        self.name()
    }
    fn cfg(&self) -> Option<&Cfg>;
    fn annotations(&self) -> &AnnotationSet;
    fn annotations_mut(&mut self) -> &mut AnnotationSet;

    fn container(&self) -> ItemContainer;

    fn collect_declaration_types(&self, _resolver: &mut DeclarationTypeResolver) {
        unimplemented!()
    }
    fn resolve_declaration_types(&mut self, _resolver: &DeclarationTypeResolver) {
        unimplemented!()
    }
    fn rename_for_config(&mut self, _config: &Config) {}
    fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
    fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) {
        unreachable!("Cannot instantiate {} as a generic.", self.name())
    }
}

#[derive(Debug, Clone)]
pub enum ItemContainer {
    Constant(Constant),
    Static(Static),
    OpaqueItem(OpaqueItem),
    Struct(Struct),
    Union(Union),
    Enum(Enum),
    Typedef(Typedef),
}

impl ItemContainer {
    pub fn deref(&self) -> &dyn Item {
        match self {
            &ItemContainer::Constant(ref x) => x,
            &ItemContainer::Static(ref x) => x,
            &ItemContainer::OpaqueItem(ref x) => x,
            &ItemContainer::Struct(ref x) => x,
            &ItemContainer::Union(ref x) => x,
            &ItemContainer::Enum(ref x) => x,
            &ItemContainer::Typedef(ref x) => x,
        }
    }
}

#[derive(Debug, Clone)]
pub enum ItemValue<T: Item> {
    Cfg(Vec<T>),
    Single(T),
}

#[derive(Debug, Clone)]
pub struct ItemMap<T: Item> {
    data: BTreeMap<Path, ItemValue<T>>,
}

impl<T: Item + Clone> ItemMap<T> {
    pub fn new() -> ItemMap<T> {
        ItemMap {
            data: BTreeMap::new(),
        }
    }

    pub fn rebuild(&mut self) {
        let old = mem::replace(self, ItemMap::new());
        old.for_all_items(|x| {
            self.try_insert(x.clone());
        });
    }

    pub fn try_insert(&mut self, item: T) -> bool {
        match (item.cfg().is_some(), self.data.get_mut(item.path())) {
            (true, Some(&mut ItemValue::Cfg(ref mut items))) => {
                items.push(item);
                return true;
            }
            (false, Some(&mut ItemValue::Cfg(_))) => {
                return false;
            }
            (true, Some(&mut ItemValue::Single(_))) => {
                return false;
            }
            (false, Some(&mut ItemValue::Single(_))) => {
                return false;
            }
            _ => {}
        }

        let path = item.path().clone();
        if item.cfg().is_some() {
            self.data.insert(path, ItemValue::Cfg(vec![item]));
        } else {
            self.data.insert(path, ItemValue::Single(item));
        }

        true
    }

    pub fn extend_with(&mut self, other: &ItemMap<T>) {
        other.for_all_items(|x| {
            self.try_insert(x.clone());
        });
    }

    pub fn to_vec(&self) -> Vec<T> {
        let mut result = Vec::with_capacity(self.data.len());
        for container in self.data.values() {
            match container {
                &ItemValue::Cfg(ref items) => result.extend_from_slice(items),
                &ItemValue::Single(ref item) => {
                    result.push(item.clone());
                }
            }
        }
        result
    }

    pub fn get_items(&self, path: &Path) -> Option<Vec<ItemContainer>> {
        Some(match *self.data.get(path)? {
            ItemValue::Cfg(ref items) => items.iter().map(|x| x.container()).collect(),
            ItemValue::Single(ref item) => vec![item.container()],
        })
    }

    pub fn filter<F>(&mut self, callback: F)
    where
        F: Fn(&T) -> bool,
    {
        let data = mem::replace(&mut self.data, BTreeMap::new());

        for (name, container) in data {
            match container {
                ItemValue::Cfg(items) => {
                    let mut new_items = Vec::new();
                    for item in items {
                        if !callback(&item) {
                            new_items.push(item);
                        }
                    }
                    if new_items.len() > 0 {
                        self.data.insert(name, ItemValue::Cfg(new_items));
                    }
                }
                ItemValue::Single(item) => {
                    if !callback(&item) {
                        self.data.insert(name, ItemValue::Single(item));
                    }
                }
            }
        }
    }

    pub fn for_all_items<F>(&self, mut callback: F)
    where
        F: FnMut(&T),
    {
        for container in self.data.values() {
            match container {
                &ItemValue::Cfg(ref items) => {
                    for item in items {
                        callback(item);
                    }
                }
                &ItemValue::Single(ref item) => callback(item),
            }
        }
    }

    pub fn for_all_items_mut<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut T),
    {
        for container in self.data.values_mut() {
            match container {
                &mut ItemValue::Cfg(ref mut items) => {
                    for item in items {
                        callback(item);
                    }
                }
                &mut ItemValue::Single(ref mut item) => callback(item),
            }
        }
    }

    pub fn for_items<F>(&self, path: &Path, mut callback: F)
    where
        F: FnMut(&T),
    {
        match self.data.get(path) {
            Some(&ItemValue::Cfg(ref items)) => {
                for item in items {
                    callback(item);
                }
            }
            Some(&ItemValue::Single(ref item)) => {
                callback(item);
            }
            None => {}
        }
    }

    pub fn for_items_mut<F>(&mut self, path: &Path, mut callback: F)
    where
        F: FnMut(&mut T),
    {
        match self.data.get_mut(path) {
            Some(&mut ItemValue::Cfg(ref mut items)) => {
                for item in items {
                    callback(item);
                }
            }
            Some(&mut ItemValue::Single(ref mut item)) => {
                callback(item);
            }
            None => {}
        }
    }
}
<|endoftext|>


<commit_before>use errors::wallet::WalletError;

use services::wallet::WalletService;

use std::rc::Rc;

pub enum WalletCommand {
    Create(String, // pool name
           String, // wallet name
           Option<String>, // wallet type
           Option<String>, // wallet config
           Option<String>, // wallet credentials
           Box<Fn(Result<(), WalletError>) + Send>),
    Open(String, // wallet name
         Option<String>, // wallet runtime config
         Option<String>, // wallet credentials
         Box<Fn(Result<i32, WalletError>) + Send>),
    Close(i32, // handle
          Box<Fn(Result<(), WalletError>) + Send>),
    Delete(String, // name
           Option<String>, // wallet credentials
           Box<Fn(Result<(), WalletError>) + Send>),
    SetSeqNoForValue(i32, // wallet handle
                     String, // wallet key
                     i32, // sequence number
                     Box<Fn(Result<(), WalletError>) + Send>)
}

pub struct WalletCommandExecutor {
    wallet_service: Rc<WalletService>
}

impl WalletCommandExecutor {
    pub fn new(wallet_service: Rc<WalletService>) -> WalletCommandExecutor {
        WalletCommandExecutor {
            wallet_service: wallet_service
        }
    }

    pub fn execute(&self, command: WalletCommand) {
        match command {
            WalletCommand::Create(pool_name, name, xtype, config, credentials, cb) => {
                info!(target: "wallet_command_executor", "Create command received");
                self.create(&pool_name, &name, xtype.as_ref().map(String::as_str),
                            config.as_ref().map(String::as_str), credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::Open(name, runtime_config, credentials, cb) => {
                info!(target: "wallet_command_executor", "Open command received");
                self.open(&name, runtime_config.as_ref().map(String::as_str),
                          credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::Close(handle, cb) => {
                info!(target: "wallet_command_executor", "Close command received");
                self.close(handle, cb);
            }
            WalletCommand::Delete(name, credentials, cb) => {
                info!(target: "wallet_command_executor", "Delete command received");
                self.delete(&name, credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::SetSeqNoForValue(handle, key, seq_no, cb) => {
                info!(target: "wallet_command_executor", "SetSeqNoForValue command received");
                self.set_seq_no_for_value(handle, &key, seq_no, cb);
            }
        };
    }

    fn create(&self,
              pool_name: &str,
              name: &str,
              xtype: Option<&str>,
              config: Option<&str>,
              credentials: Option<&str>,
              cb: Box<Fn(Result<(), WalletError>) + Send>) {
        cb(self.wallet_service.create(pool_name, xtype, name, config, credentials));
    }

    fn open(&self,
            name: &str,
            runtime_config: Option<&str>,
            credentials: Option<&str>,
            cb: Box<Fn(Result<i32, WalletError>) + Send>) {
        cb(self.wallet_service.open(name, runtime_config, credentials));
    }

    fn close(&self,
             handle: i32,
             cb: Box<Fn(Result<(), WalletError>) + Send>) {
        cb(self.wallet_service.close(handle));
    }

    fn delete(&self,
              handle: &str,
              credentials: Option<&str>,
              cb: Box<Fn(Result<(), WalletError>) + Send>) {
        cb(self.wallet_service.delete(handle, credentials));
    }

    fn set_seq_no_for_value(&self,
                            handle: i32,
                            key: &str,
                            seq_no: i32,
                            cb: Box<Fn(Result<(), WalletError>) + Send>) {
        cb(self.wallet_service.set(handle, &format!("seq_no::{}", seq_no), key));
    }
}<commit_msg>wallet refactored<commit_after>use errors::sovrin::SovrinError;

use services::wallet::WalletService;

use std::rc::Rc;

pub enum WalletCommand {
    Create(String, // pool name
           String, // wallet name
           Option<String>, // wallet type
           Option<String>, // wallet config
           Option<String>, // wallet credentials
           Box<Fn(Result<(), SovrinError>) + Send>),
    Open(String, // wallet name
         Option<String>, // wallet runtime config
         Option<String>, // wallet credentials
         Box<Fn(Result<i32, SovrinError>) + Send>),
    Close(i32, // handle
          Box<Fn(Result<(), SovrinError>) + Send>),
    Delete(String, // name
           Option<String>, // wallet credentials
           Box<Fn(Result<(), SovrinError>) + Send>),
    SetSeqNoForValue(i32, // wallet handle
                     String, // wallet key
                     i32, // sequence number
                     Box<Fn(Result<(), SovrinError>) + Send>)
}

pub struct WalletCommandExecutor {
    wallet_service: Rc<WalletService>
}

impl WalletCommandExecutor {
    pub fn new(wallet_service: Rc<WalletService>) -> WalletCommandExecutor {
        WalletCommandExecutor {
            wallet_service: wallet_service
        }
    }

    pub fn execute(&self, command: WalletCommand) {
        match command {
            WalletCommand::Create(pool_name, name, xtype, config, credentials, cb) => {
                info!(target: "wallet_command_executor", "Create command received");
                self.create(&pool_name, &name, xtype.as_ref().map(String::as_str),
                            config.as_ref().map(String::as_str), credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::Open(name, runtime_config, credentials, cb) => {
                info!(target: "wallet_command_executor", "Open command received");
                self.open(&name, runtime_config.as_ref().map(String::as_str),
                          credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::Close(handle, cb) => {
                info!(target: "wallet_command_executor", "Close command received");
                self.close(handle, cb);
            }
            WalletCommand::Delete(name, credentials, cb) => {
                info!(target: "wallet_command_executor", "Delete command received");
                self.delete(&name, credentials.as_ref().map(String::as_str), cb);
            }
            WalletCommand::SetSeqNoForValue(handle, key, seq_no, cb) => {
                info!(target: "wallet_command_executor", "SetSeqNoForValue command received");
                self.set_seq_no_for_value(handle, &key, seq_no, cb);
            }
        };
    }

    fn create(&self,
              pool_name: &str,
              name: &str,
              xtype: Option<&str>,
              config: Option<&str>,
              credentials: Option<&str>,
              cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        cb(self.wallet_service.create(pool_name, xtype, name, config, credentials)
            .map_err(|err| SovrinError::WalletError(err)));
    }

    fn open(&self,
            name: &str,
            runtime_config: Option<&str>,
            credentials: Option<&str>,
            cb: Box<Fn(Result<i32, SovrinError>) + Send>) {
        cb(self.wallet_service.open(name, runtime_config, credentials)
            .map_err(|err| SovrinError::WalletError(err)));
    }

    fn close(&self,
             handle: i32,
             cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        cb(self.wallet_service.close(handle)
            .map_err(|err| SovrinError::WalletError(err)));
    }

    fn delete(&self,
              handle: &str,
              credentials: Option<&str>,
              cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        cb(self.wallet_service.delete(handle, credentials)
            .map_err(|err| SovrinError::WalletError(err)));
    }

    fn set_seq_no_for_value(&self,
                            handle: i32,
                            key: &str,
                            seq_no: i32,
                            cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        cb(self.wallet_service.set(handle, &format!("seq_no::{}", seq_no), key)
            .map_err(|err| SovrinError::WalletError(err)));
    }
}<|endoftext|>


<commit_before>//  notty is a new kind of terminal emulator.
//  Copyright (C) 2015 without boats
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
use std::mem;

use datatypes::{Area, Coords, Direction, Region, move_within};
use datatypes::Area::*;
use datatypes::Direction::*;
use datatypes::Movement::To;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct CoordsIter {
    point: Coords,
    back_point: Coords,
    region: Region,
    dir: Direction,
    fin: bool,
}

impl CoordsIter {

    pub fn from_area(area: Area, cursor: Coords, screen: Region, tab: u32) -> CoordsIter {
        match area {
            CursorCell              => CoordsIter {
                point: cursor,
                back_point: cursor,
                region: screen,
                dir: Right,
                fin: false
            },
            CursorRow               => CoordsIter {
                point: Coords {x: screen.left, y: cursor.y},
                back_point: Coords {x: screen.right - 1, y: cursor.y},
                region: screen,
                dir: Right,
                fin: false,
            },
            CursorColumn            => CoordsIter {
                point: Coords {x: cursor.x, y: screen.top},
                back_point: Coords {x: cursor.x, y: screen.bottom - 1},
                region: screen,
                dir: Down,
                fin: false,
            },
            CursorTo(mov)           => CoordsIter {
                point: cursor,
                back_point: move_within(cursor, mov, screen, tab),
                region: screen,
                dir: mov.direction(cursor),
                fin: false,
            },
            CursorBound(coords) if coords == cursor => {
                CoordsIter::from_area(CursorCell, cursor, screen, tab)
            }
            CursorBound(coords)     => {
                CoordsIter::from_region(Region::new(cursor.x, cursor.y, coords.x, coords.y))
            }
            WholeScreen             => CoordsIter::from_region(screen),
            Bound(region)           => CoordsIter::from_region(region),
            Rows(top, bottom)       => CoordsIter {
                point: Coords {x: screen.left, y: top },
                back_point: Coords {x: screen.right - 1, y: bottom - 1},
                region: screen,
                dir: Right,
                fin: !(top < bottom),
            },
            Columns(left, right)    => CoordsIter {
                point: Coords {x: left, y: screen.top},
                back_point: Coords {x: right - 1, y: screen.bottom - 1},
                region: screen,
                dir: Down,
                fin: !(left < right),
            },
            BelowCursor(true)       => {
                CoordsIter::from_region(Region { top: cursor.y, ..screen})
            }
            BelowCursor(false) if cursor.y == screen.bottom - 1 => {
                CoordsIter {
                    point: cursor,
                    back_point: cursor,
                    region: screen,
                    dir: Right,
                    fin: true,
                }
            }
            BelowCursor(false)       => {
                CoordsIter::from_region(Region { top: cursor.y + 1, ..screen })
            }
        }
    }

    pub fn from_region(region: Region) -> CoordsIter {
        CoordsIter {
            point: Coords {x: region.left, y: region.top},
            back_point: Coords {x: region.right-1, y: region.bottom-1},
            region: region,
            dir: Right,
            fin: false,
        }
    }

}

impl Iterator for CoordsIter {
    type Item = Coords;

    fn next(&mut self) -> Option<Coords> {
        match (self.point == self.back_point, self.fin) {
            (_, true)   => None,
            (true, _)   => {
                self.fin = true;
                Some(self.point)
            }
            (false, _)  => {
                let point = move_within(self.point, To(self.dir, 1, true), self.region, 0);
                Some(mem::replace(&mut self.point, point))
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len(), Some(self.len()))
    }

}

impl DoubleEndedIterator for CoordsIter {

    fn next_back(&mut self) -> Option<Coords> {
        match (self.point == self.back_point, self.fin) {
            (_, true)   => None,
            (true, _)   => {
                self.fin = true;
                Some(self.point)
            }
            (false, _)  => {
                let point = move_within(self.back_point, To(self.dir.rev(), 1, true), self.region,
                                        0);
                Some(mem::replace(&mut self.back_point, point))
            }
        }
    }
}

impl ExactSizeIterator for CoordsIter {

    fn len(&self) -> usize {

        match self.dir {
            Up if self.point.x == self.back_point.x     => {
                (self.point.y - self.back_point.y + 1) as usize
            }
            Up                                          => {
                let height = self.region.bottom - self.region.top;
                let first = self.point.y - self.region.top + 1;
                let mid = (self.point.x - self.back_point.x).saturating_sub(1) * height;
                let last = self.region.bottom - self.back_point.y;
                (first + mid + last) as usize
            }
            Down if self.point.x == self.back_point.x   => {
                (self.back_point.y - self.point.y + 1) as usize
            }
            Down                                        => {
                let height = self.region.bottom - self.region.top;
                let first = self.region.bottom - self.point.y;
                let mid = (self.back_point.x - self.point.x).saturating_sub(1) * height;
                let last = self.back_point.y - self.region.top + 1;
                (first + mid + last) as usize
            }
            Left if self.point.y == self.back_point.y   => {
                (self.point.x - self.back_point.x + 1) as usize
            }
            Left                                        => {
                let width = self.region.right - self.region.left;
                let first = self.point.x - self.region.left + 1;
                let mid = (self.point.y - self.back_point.y).saturating_sub(1) * width;
                let last = self.region.right - self.back_point.x;
                (first + mid + last) as usize
            }
            Right if self.point.y == self.back_point.y  => {
                (self.back_point.x - self.point.x + 1)  as usize
            }
            Right                                       => {
                let width = self.region.right - self.region.left;
                let first = self.region.right - self.point.x;
                let mid = (self.back_point.y - self.point.y).saturating_sub(1) * width;
                let last = self.back_point.x - self.region.left + 1;
                (first + mid + last) as usize
            }
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;
    use datatypes::{Coords, Region};
    use datatypes::Direction::*;

    macro_rules! iter {
        ($x1:expr, $y1:expr, $x2:expr, $y2:expr, $l:expr, $t: expr, $r:expr, $b:expr, $d:expr) =>
        (CoordsIter {
            point: Coords {x: $x1, y: $y1},
            back_point: Coords {x: $x2, y: $y2},
            region: Region {left: $l, top: $t, right: $r, bottom: $b},
            dir: $d,
            fin: false,
        });
    }

    macro_rules! array {
        [$(($x:expr,$y:expr)),*] => [
            &[$(Coords {x: $x, y: $y }),*]
        ];
    }

    static TEST_CASES: &'static [(CoordsIter, &'static [Coords])] = &[
        (iter!(1,1, 0,0, 0,0,2,2, Up),      array![(1,1), (1,0), (0,1), (0,0)]),
        (iter!(0,1, 0,0, 0,0,2,2, Up),      array![(0,1), (0,0)]),
        (iter!(1,0, 0,1, 0,0,2,2, Up),      array![(1,0), (0,1)]),
        (iter!(0,0, 1,1, 0,0,2,2, Down),    array![(0,0), (0,1), (1,0), (1,1)]),
        (iter!(0,0, 0,1, 0,0,2,2, Down),    array![(0,0), (0,1)]),
        (iter!(0,1, 1,0, 0,0,2,2, Down),    array![(0,1), (1,0)]),
        (iter!(1,1, 0,0, 0,0,2,2, Left),    array![(1,1), (0,1), (1,0), (0,0)]),
        (iter!(1,0, 0,0, 0,0,2,2, Left),    array![(1,0), (0,0)]),
        (iter!(0,1, 1,0, 0,0,2,2, Left),    array![(0,1), (1,0)]),
        (iter!(0,0, 1,1, 0,0,2,2, Right),   array![(0,0), (1,0), (0,1), (1,1)]),
        (iter!(0,0, 1,0, 0,0,2,2, Right),   array![(0,0), (1,0)]),
        (iter!(1,0, 0,1, 0,0,2,2, Right),   array![(1,0), (0,1)]),
    ];

    #[test]
    fn forward_iteration() {
        for &(iter, array) in TEST_CASES {
            assert_eq!(iter.collect::<Vec<_>>(), array.iter().cloned().collect::<Vec<_>>());
        }
    }

    #[test]
    fn backward_iteration() {
        for &(iter, array) in TEST_CASES {
            assert_eq!(iter.rev().collect::<Vec<_>>(),
                       array.iter().cloned().rev().collect::<Vec<_>>());
        }
    }

    #[test]
    fn length() {
        for &(iter, array) in TEST_CASES {
            assert!(iter.len() == array.len(), "{:?}; {} != {}", iter, iter.len(), array.len());
        }
    }
}
<commit_msg>Fix off-by-one error.<commit_after>//  notty is a new kind of terminal emulator.
//  Copyright (C) 2015 without boats
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
use std::cmp;
use std::mem;

use datatypes::{Area, Coords, Direction, Region, move_within};
use datatypes::Area::*;
use datatypes::Direction::*;
use datatypes::Movement::To;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct CoordsIter {
    point: Coords,
    back_point: Coords,
    region: Region,
    dir: Direction,
    fin: bool,
}

impl CoordsIter {

    pub fn from_area(area: Area, cursor: Coords, screen: Region, tab: u32) -> CoordsIter {
        match area {
            CursorCell              => CoordsIter {
                point: cursor,
                back_point: cursor,
                region: screen,
                dir: Right,
                fin: false
            },
            CursorRow               => CoordsIter {
                point: Coords {x: screen.left, y: cursor.y},
                back_point: Coords {x: screen.right - 1, y: cursor.y},
                region: screen,
                dir: Right,
                fin: false,
            },
            CursorColumn            => CoordsIter {
                point: Coords {x: cursor.x, y: screen.top},
                back_point: Coords {x: cursor.x, y: screen.bottom - 1},
                region: screen,
                dir: Down,
                fin: false,
            },
            CursorTo(mov)           => CoordsIter {
                point: cursor,
                back_point: move_within(cursor, mov, screen, tab),
                region: screen,
                dir: mov.direction(cursor),
                fin: false,
            },
            CursorBound(coords) if coords == cursor => {
                CoordsIter::from_area(CursorCell, cursor, screen, tab)
            }
            CursorBound(coords)     => {
                let (l, r) = (cmp::min(coords.x, cursor.x), cmp::max(coords.x, cursor.x) + 1);
                let (t, b) = (cmp::min(coords.y, cursor.y), cmp::max(coords.y, cursor.y) + 1);
                CoordsIter::from_region(Region::new(l, t, r, b))
            }
            WholeScreen             => CoordsIter::from_region(screen),
            Bound(region)           => CoordsIter::from_region(region),
            Rows(top, bottom)       => CoordsIter {
                point: Coords {x: screen.left, y: top },
                back_point: Coords {x: screen.right - 1, y: bottom - 1},
                region: screen,
                dir: Right,
                fin: !(top < bottom),
            },
            Columns(left, right)    => CoordsIter {
                point: Coords {x: left, y: screen.top},
                back_point: Coords {x: right - 1, y: screen.bottom - 1},
                region: screen,
                dir: Down,
                fin: !(left < right),
            },
            BelowCursor(true)       => {
                CoordsIter::from_region(Region { top: cursor.y, ..screen})
            }
            BelowCursor(false) if cursor.y == screen.bottom - 1 => {
                CoordsIter {
                    point: cursor,
                    back_point: cursor,
                    region: screen,
                    dir: Right,
                    fin: true,
                }
            }
            BelowCursor(false)       => {
                CoordsIter::from_region(Region { top: cursor.y + 1, ..screen })
            }
        }
    }

    pub fn from_region(region: Region) -> CoordsIter {
        CoordsIter {
            point: Coords {x: region.left, y: region.top},
            back_point: Coords {x: region.right-1, y: region.bottom-1},
            region: region,
            dir: Right,
            fin: false,
        }
    }

}

impl Iterator for CoordsIter {
    type Item = Coords;

    fn next(&mut self) -> Option<Coords> {
        match (self.point == self.back_point, self.fin) {
            (_, true)   => None,
            (true, _)   => {
                self.fin = true;
                Some(self.point)
            }
            (false, _)  => {
                let point = move_within(self.point, To(self.dir, 1, true), self.region, 0);
                Some(mem::replace(&mut self.point, point))
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len(), Some(self.len()))
    }

}

impl DoubleEndedIterator for CoordsIter {

    fn next_back(&mut self) -> Option<Coords> {
        match (self.point == self.back_point, self.fin) {
            (_, true)   => None,
            (true, _)   => {
                self.fin = true;
                Some(self.point)
            }
            (false, _)  => {
                let point = move_within(self.back_point, To(self.dir.rev(), 1, true), self.region,
                                        0);
                Some(mem::replace(&mut self.back_point, point))
            }
        }
    }
}

impl ExactSizeIterator for CoordsIter {

    fn len(&self) -> usize {

        match self.dir {
            Up if self.point.x == self.back_point.x     => {
                (self.point.y - self.back_point.y + 1) as usize
            }
            Up                                          => {
                let height = self.region.bottom - self.region.top;
                let first = self.point.y - self.region.top + 1;
                let mid = (self.point.x - self.back_point.x).saturating_sub(1) * height;
                let last = self.region.bottom - self.back_point.y;
                (first + mid + last) as usize
            }
            Down if self.point.x == self.back_point.x   => {
                (self.back_point.y - self.point.y + 1) as usize
            }
            Down                                        => {
                let height = self.region.bottom - self.region.top;
                let first = self.region.bottom - self.point.y;
                let mid = (self.back_point.x - self.point.x).saturating_sub(1) * height;
                let last = self.back_point.y - self.region.top + 1;
                (first + mid + last) as usize
            }
            Left if self.point.y == self.back_point.y   => {
                (self.point.x - self.back_point.x + 1) as usize
            }
            Left                                        => {
                let width = self.region.right - self.region.left;
                let first = self.point.x - self.region.left + 1;
                let mid = (self.point.y - self.back_point.y).saturating_sub(1) * width;
                let last = self.region.right - self.back_point.x;
                (first + mid + last) as usize
            }
            Right if self.point.y == self.back_point.y  => {
                (self.back_point.x - self.point.x + 1)  as usize
            }
            Right                                       => {
                let width = self.region.right - self.region.left;
                let first = self.region.right - self.point.x;
                let mid = (self.back_point.y - self.point.y).saturating_sub(1) * width;
                let last = self.back_point.x - self.region.left + 1;
                (first + mid + last) as usize
            }
        }
    }

}

#[cfg(test)]
mod tests {

    use super::*;
    use datatypes::{Coords, Region};
    use datatypes::Direction::*;

    macro_rules! iter {
        ($x1:expr, $y1:expr, $x2:expr, $y2:expr, $l:expr, $t: expr, $r:expr, $b:expr, $d:expr) =>
        (CoordsIter {
            point: Coords {x: $x1, y: $y1},
            back_point: Coords {x: $x2, y: $y2},
            region: Region {left: $l, top: $t, right: $r, bottom: $b},
            dir: $d,
            fin: false,
        });
    }

    macro_rules! array {
        [$(($x:expr,$y:expr)),*] => [
            &[$(Coords {x: $x, y: $y }),*]
        ];
    }

    static TEST_CASES: &'static [(CoordsIter, &'static [Coords])] = &[
        (iter!(1,1, 0,0, 0,0,2,2, Up),      array![(1,1), (1,0), (0,1), (0,0)]),
        (iter!(0,1, 0,0, 0,0,2,2, Up),      array![(0,1), (0,0)]),
        (iter!(1,0, 0,1, 0,0,2,2, Up),      array![(1,0), (0,1)]),
        (iter!(0,0, 1,1, 0,0,2,2, Down),    array![(0,0), (0,1), (1,0), (1,1)]),
        (iter!(0,0, 0,1, 0,0,2,2, Down),    array![(0,0), (0,1)]),
        (iter!(0,1, 1,0, 0,0,2,2, Down),    array![(0,1), (1,0)]),
        (iter!(1,1, 0,0, 0,0,2,2, Left),    array![(1,1), (0,1), (1,0), (0,0)]),
        (iter!(1,0, 0,0, 0,0,2,2, Left),    array![(1,0), (0,0)]),
        (iter!(0,1, 1,0, 0,0,2,2, Left),    array![(0,1), (1,0)]),
        (iter!(0,0, 1,1, 0,0,2,2, Right),   array![(0,0), (1,0), (0,1), (1,1)]),
        (iter!(0,0, 1,0, 0,0,2,2, Right),   array![(0,0), (1,0)]),
        (iter!(1,0, 0,1, 0,0,2,2, Right),   array![(1,0), (0,1)]),
    ];

    #[test]
    fn forward_iteration() {
        for &(iter, array) in TEST_CASES {
            assert_eq!(iter.collect::<Vec<_>>(), array.iter().cloned().collect::<Vec<_>>());
        }
    }

    #[test]
    fn backward_iteration() {
        for &(iter, array) in TEST_CASES {
            assert_eq!(iter.rev().collect::<Vec<_>>(),
                       array.iter().cloned().rev().collect::<Vec<_>>());
        }
    }

    #[test]
    fn length() {
        for &(iter, array) in TEST_CASES {
            assert!(iter.len() == array.len(), "{:?}; {} != {}", iter, iter.len(), array.len());
        }
    }
}
<|endoftext|>


<commit_before>use bitmap_font::BitmapFont;
use line_renderer::LineRenderer;
use text_renderer::TextRenderer;

use gfx;
use gfx::traits::*;
use gfx_texture;
use image;

pub enum DebugRendererError {
    ShaderProgramError(gfx::ProgramError),
    BitmapFontTextureError,
}

impl From<gfx::ProgramError> for DebugRendererError {
    fn from(err: gfx::ProgramError) -> DebugRendererError {
        DebugRendererError::ShaderProgramError(err)
    }
}

pub struct DebugRenderer<R: gfx::Resources> {
    line_renderer: LineRenderer<R>,
    text_renderer: TextRenderer<R>,
}

impl<R: gfx::Resources> DebugRenderer<R> {

    pub fn from_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        canvas: &mut gfx::Canvas<O, D, F>,
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::TextureHandle<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {
        let (w, h) = canvas.output.get_size();
        DebugRenderer::new(&canvas.device, &mut canvas.factory,
                           [w as u32, h as u32], initial_buffer_size,
                           bitmap_font, bitmap_font_texture)
    }

    pub fn new<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        device: &D,
        factory: &mut F,
        frame_size: [u32; 2],
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::TextureHandle<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {

        let device_capabilities = device.get_capabilities();

        let bitmap_font = match bitmap_font {
            Some(f) => f,
            None => BitmapFont::from_string(include_str!("../assets/notosans.fnt")).unwrap()
        };

        let bitmap_font_texture = match bitmap_font_texture {
            Some(t) => t,
            None => {
                if let image::DynamicImage::ImageRgba8(rgba_image) = image::load_from_memory_with_format(include_bytes!("../assets/notosans.png"), image::ImageFormat::PNG).unwrap() {
                    gfx_texture::Texture::from_image(factory, &rgba_image, false, false, false).handle()
                } else {
                    return Err(DebugRendererError::BitmapFontTextureError)
                }
            }
        };

        let line_renderer = try!(LineRenderer::new(*device_capabilities, factory, initial_buffer_size));
        let text_renderer = try!(TextRenderer::new(*device_capabilities, factory, frame_size, initial_buffer_size, bitmap_font, bitmap_font_texture));

        Ok(DebugRenderer {
            line_renderer: line_renderer,
            text_renderer: text_renderer,
        })
    }

    pub fn draw_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
        self.line_renderer.draw_line(start, end, color);
    }

    pub fn draw_text_on_screen (
        &mut self,
        text: &str,
        screen_position: [i32; 2],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_on_screen(text, screen_position, color);
    }

    pub fn draw_text_at_position (
        &mut self,
        text: &str,
        world_position: [f32; 3],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_at_position(text, world_position, color);
    }

    pub fn render_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        &mut self,
        canvas: &mut gfx::Canvas<O, D, F>,
        projection: [[f32; 4]; 4],
    ) {
        self.render(&mut canvas.renderer, &mut canvas.factory, &canvas.output, projection);
    }

    pub fn render<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
    > (
        &mut self,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        output: &O,
        projection: [[f32; 4]; 4],
    ) {
        self.line_renderer.render(renderer, factory, output, projection);
        self.text_renderer.render(renderer, factory, output, projection);
    }
}
<commit_msg>Auto-derive debug impl for DebugRendererError<commit_after>use bitmap_font::BitmapFont;
use line_renderer::LineRenderer;
use text_renderer::TextRenderer;

use gfx;
use gfx::traits::*;
use gfx_texture;
use image;

#[derive(Debug)]
pub enum DebugRendererError {
    ShaderProgramError(gfx::ProgramError),
    BitmapFontTextureError,
}

impl From<gfx::ProgramError> for DebugRendererError {
    fn from(err: gfx::ProgramError) -> DebugRendererError {
        DebugRendererError::ShaderProgramError(err)
    }
}

pub struct DebugRenderer<R: gfx::Resources> {
    line_renderer: LineRenderer<R>,
    text_renderer: TextRenderer<R>,
}

impl<R: gfx::Resources> DebugRenderer<R> {

    pub fn from_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        canvas: &mut gfx::Canvas<O, D, F>,
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::TextureHandle<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {
        let (w, h) = canvas.output.get_size();
        DebugRenderer::new(&canvas.device, &mut canvas.factory,
                           [w as u32, h as u32], initial_buffer_size,
                           bitmap_font, bitmap_font_texture)
    }

    pub fn new<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        device: &D,
        factory: &mut F,
        frame_size: [u32; 2],
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::TextureHandle<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {

        let device_capabilities = device.get_capabilities();

        let bitmap_font = match bitmap_font {
            Some(f) => f,
            None => BitmapFont::from_string(include_str!("../assets/notosans.fnt")).unwrap()
        };

        let bitmap_font_texture = match bitmap_font_texture {
            Some(t) => t,
            None => {
                if let image::DynamicImage::ImageRgba8(rgba_image) = image::load_from_memory_with_format(include_bytes!("../assets/notosans.png"), image::ImageFormat::PNG).unwrap() {
                    gfx_texture::Texture::from_image(factory, &rgba_image, false, false, false).handle()
                } else {
                    return Err(DebugRendererError::BitmapFontTextureError)
                }
            }
        };

        let line_renderer = try!(LineRenderer::new(*device_capabilities, factory, initial_buffer_size));
        let text_renderer = try!(TextRenderer::new(*device_capabilities, factory, frame_size, initial_buffer_size, bitmap_font, bitmap_font_texture));

        Ok(DebugRenderer {
            line_renderer: line_renderer,
            text_renderer: text_renderer,
        })
    }

    pub fn draw_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
        self.line_renderer.draw_line(start, end, color);
    }

    pub fn draw_text_on_screen (
        &mut self,
        text: &str,
        screen_position: [i32; 2],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_on_screen(text, screen_position, color);
    }

    pub fn draw_text_at_position (
        &mut self,
        text: &str,
        world_position: [f32; 3],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_at_position(text, world_position, color);
    }

    pub fn render_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        &mut self,
        canvas: &mut gfx::Canvas<O, D, F>,
        projection: [[f32; 4]; 4],
    ) {
        self.render(&mut canvas.renderer, &mut canvas.factory, &canvas.output, projection);
    }

    pub fn render<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
    > (
        &mut self,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        output: &O,
        projection: [[f32; 4]; 4],
    ) {
        self.line_renderer.render(renderer, factory, output, projection);
        self.text_renderer.render(renderer, factory, output, projection);
    }
}
<|endoftext|>


<commit_before>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Debug, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if <Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone, Debug)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}
<commit_msg>fix(rope internals): make node fmt::Debug implementations less wordy<commit_after>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl fmt::Debug for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f, "{:?}{}{}{}{}{}{}"
              , self.value
              , self.len.get().map(|l| format!(" length: {:?},", l))
                    .unwrap_or_else(|| { String::new() })
              , self.weight.get().map(|w| format!(" weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              )
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Leaf(ref r) => write!(f, "Leaf({:?})", r)
          , Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
                                                    , left
                                                    , right)
        }
    }
}
<|endoftext|>


<commit_before>use super::Token;
use std::char;

pub struct TokenCollection {
    pub open_brace: Token,
    pub close_brace: Token,
    pub open_bracket: Token,
    pub close_bracket: Token,
    pub comma: Token,
    pub colon: Token,
    pub identifier: Token,
    pub stringlit: Token,
    pub integerlit: Token,
    pub floatlit: Token,
}

impl TokenCollection {
    pub fn new() -> Self {
        TokenCollection {
            open_brace: Token::new(r"\{").unwrap(),
            close_brace: Token::new(r"\}").unwrap(),
            open_bracket: Token::new(r"\[").unwrap(),
            close_bracket: Token::new(r"\]").unwrap(),
            comma: Token::new(r",").unwrap(),
            colon: Token::new(r":").unwrap(),
            identifier: Token::new(r#"(?x)
                [
                    \p{L} # letters
                    \p{M} # combining marks
                    \p{Pc} # connector punctuation (e.g. _)
                ]
                \w* # all word characters
            "#).unwrap(),
            stringlit: Token::new(r#"(?x)
                  "(?: [^"\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*"
                | '(?: [^'\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*'
            "#).unwrap(),
            integerlit: Token::new(r#"(?x)
                  0[xX][0-9a-fA-F_]+
                | 0[oO][0-8_]+
                | 0[bB][10_]+
                | 0[dD][\d_]+
                | [+-]?[\d_]+
            "#).unwrap(),
            floatlit: Token::new(r#"(?x)
                [-+]? # optional sign
                (?:
                      \d+\.\d*  # numbers <dot> <optional numbers>
                    | \.\d+     # <dot> numbers
                )
                (?:
                    [eE]  # begin exponent
                    [+-]? # sign
                    \d+   # exponent
                )? # optional exponent part
            "#).unwrap(),
        }
    }
}

pub fn parse_string(inp: String) -> String {
    let mut escaped = false;
    let mut unicode = false;
    let mut uindex = 0;
    let mut uvalue = 0;
    let quote_char = inp.chars().next().expect("parse_string is parsing an empty string");
    inp.chars().filter_map(|character| {
        if escaped {
            escaped = false;
            match character {
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                'b' => Some('\x08'),
                'f' => Some('\x0c'),
                'u' => { unicode = true; uvalue = 0; uindex = 0; None }
                 _  => Some(character),
            }
        } else if unicode {
            // code adapted from https://github.com/rust-lang/rustc-serialize/blob/master/src/json.rs#L1608-L1624
            // original licensed under MIT/Apache-2.0
            uvalue = match character {
                ctr @ '0'...'9' => uvalue * 16 + ((ctr as u16) - ('0' as u16)),
                ctr @ 'a'...'f' => uvalue * 16 + (10 + (ctr as u16) - ('a' as u16)),
                ctr @ 'A'...'F' => uvalue * 16 + (10 + (ctr as u16) - ('A' as u16)),
                _ => return None,
            };
            if uindex < 3 {
                uindex += 1;
                None
            } else {
                unicode = false;
                char::from_u32(uvalue as u32)
            }
        } else if character == quote_char {
            None
        } else if character == '\\' {
            escaped = true;
            None
        } else {
            Some(character)
        }
    }).collect()
}

pub fn parse_integer(inp: String) -> i64 {
    if inp.starts_with("0d") || inp.starts_with("0D") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 10).unwrap()
    } else if inp.starts_with("0x") || inp.starts_with("0X") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 16).unwrap()
    } else if inp.starts_with("0o") || inp.starts_with("0O") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 8).unwrap()
    } else if inp.starts_with("0b") || inp.starts_with("0B") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 2).unwrap()
    } else if inp.starts_with("+") {
        i64::from_str_radix(&inp.chars().skip(1).collect::<String>(), 10).unwrap()
    } else {
        i64::from_str_radix(&inp, 10).unwrap()
    }
}

pub fn parse_float(inp: String) -> f64 {
    inp.parse().unwrap()
}

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

    #[test]
    fn test_parse_string() {
        assert_eq!(parse_string("'hello'".to_string()), "hello");
        assert_eq!(parse_string(r#""hello""#.to_string()), "hello");
        assert_eq!(parse_string("'he\\nllo'".to_string()), "he\nllo");
        assert_eq!(parse_string(r#"'he"llo'"#.to_string()), "he\"llo");
        assert_eq!(parse_string(r"'\u0058'".to_string()), "\u{0058}");
    }

    #[test]
    fn test_parse_integer() {
        assert_eq!(parse_integer("0d5".to_string()), 5);
        assert_eq!(parse_integer("0D5474".to_string()), 5474);
        assert_eq!(parse_integer("0x4f3".to_string()), 0x4f3);
        assert_eq!(parse_integer("0X7Df31".to_string()), 0x7df31);
        assert_eq!(parse_integer("0o443".to_string()), 3 + (8*4) + (64*4));
        assert_eq!(parse_integer("0O70131".to_string()), 28761);
        assert_eq!(parse_integer("0b01101".to_string()), 0b01101);
        assert_eq!(parse_integer("0B10010".to_string()), 0b10010);
        assert_eq!(parse_integer("32353".to_string()), 32353);
        assert_eq!(parse_integer("-1234".to_string()), -1234);
        assert_eq!(parse_integer("+4321".to_string()), 4321);
    }

    #[test]
    fn test_parse_float() {
        assert_eq!(parse_float("+1.2".to_string()), 1.2);
        assert_eq!(parse_float("-1.2".to_string()), -1.2);
        assert_eq!(parse_float("3.4".to_string()), 3.4);
        assert_eq!(parse_float("3.".to_string()), 3.0);
        assert_eq!(parse_float(".2".to_string()), 0.2);
        assert_eq!(parse_float("1.2e2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2e+2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2e-2".to_string()), 1.2E-2);
        assert_eq!(parse_float("1.2E2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2E+2".to_string()), 1.2E+2);
        assert_eq!(parse_float("1.2E-2".to_string()), 1.2E-2);
    }

    #[test]
    fn literals_match() {
        let tk = TokenCollection::new();
        assert_eq!(tk.open_brace.get_match("{"), Some(1));
        assert_eq!(tk.open_brace.get_match("}"), None);
        assert_eq!(tk.close_brace.get_match("}"), Some(1));
        assert_eq!(tk.close_brace.get_match("d"), None);
        assert_eq!(tk.open_bracket.get_match("["), Some(1));
        assert_eq!(tk.open_bracket.get_match(" "), None);
        assert_eq!(tk.close_bracket.get_match("]"), Some(1));
        assert_eq!(tk.close_bracket.get_match("["), None);
        assert_eq!(tk.comma.get_match(","), Some(1));
        assert_eq!(tk.comma.get_match(""), None);
        assert_eq!(tk.colon.get_match(":"), Some(1));
        assert_eq!(tk.colon.get_match(";"), None);
    }

    #[test]
    fn identifier_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.identifier.get_match("hello"), Some(5));
        assert_eq!(tk.identifier.get_match("HELLO"), Some(5));
        assert_eq!(tk.identifier.get_match("45fefe"), None);
        assert_eq!(tk.identifier.get_match("fefe45"), Some(6));
        assert_eq!(tk.identifier.get_match("true"), Some(4));
        assert_eq!(tk.identifier.get_match("$"), None);
    }

    #[test]
    fn string_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.stringlit.get_match(""), None);
        assert_eq!(tk.stringlit.get_match("hello"), None);
        assert_eq!(tk.stringlit.get_match("'hello'"), Some(7));
        assert_eq!(tk.stringlit.get_match("{}[],: 'string'"), None);
        assert_eq!(tk.stringlit.get_match(r#""hello""#), Some(7));
        assert_eq!(tk.stringlit.get_match(r"'hello\n'"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'hello\''"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'
            no newline in strings'"), None);
    }

    #[test]
    fn integer_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.integerlit.get_match("345"), Some(3));
        assert_eq!(tk.integerlit.get_match("3_4_5"), Some(5));
        assert_eq!(tk.integerlit.get_match("0d3_4_5"), Some(7));
        assert_eq!(tk.integerlit.get_match("0x45"), Some(4));
        assert_eq!(tk.integerlit.get_match("0Xff"), Some(4));
        assert_eq!(tk.integerlit.get_match("0xf_f"), Some(5));
        assert_eq!(tk.integerlit.get_match("0xgg"), Some(1));
        assert_eq!(tk.integerlit.get_match("0o44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0O44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0o99"), Some(1));
    }

    #[test]
    fn float_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.floatlit.get_match("300."), Some(4));
        assert_eq!(tk.floatlit.get_match("30.0"), Some(4));
        assert_eq!(tk.floatlit.get_match(".300"), Some(4));
        assert_eq!(tk.floatlit.get_match("300"), None);
        assert_eq!(tk.floatlit.get_match("3.e5"), Some(4));
        assert_eq!(tk.floatlit.get_match("3.e-5"), Some(5));
        assert_eq!(tk.floatlit.get_match("3.E-5"), Some(5));
    }
}
<commit_msg>Fix failing float tests for stable/beta rusts<commit_after>use super::Token;
use std::char;

pub struct TokenCollection {
    pub open_brace: Token,
    pub close_brace: Token,
    pub open_bracket: Token,
    pub close_bracket: Token,
    pub comma: Token,
    pub colon: Token,
    pub identifier: Token,
    pub stringlit: Token,
    pub integerlit: Token,
    pub floatlit: Token,
}

impl TokenCollection {
    pub fn new() -> Self {
        TokenCollection {
            open_brace: Token::new(r"\{").unwrap(),
            close_brace: Token::new(r"\}").unwrap(),
            open_bracket: Token::new(r"\[").unwrap(),
            close_bracket: Token::new(r"\]").unwrap(),
            comma: Token::new(r",").unwrap(),
            colon: Token::new(r":").unwrap(),
            identifier: Token::new(r#"(?x)
                [
                    \p{L} # letters
                    \p{M} # combining marks
                    \p{Pc} # connector punctuation (e.g. _)
                ]
                \w* # all word characters
            "#).unwrap(),
            stringlit: Token::new(r#"(?x)
                  "(?: [^"\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*"
                | '(?: [^'\n\\] | \\n | \\r | \\t | \\\\ | \\b
                    | \\f | \\/ | \\" | \\' | \\u[0-9a-fA-F]{4} )*'
            "#).unwrap(),
            integerlit: Token::new(r#"(?x)
                  0[xX][0-9a-fA-F_]+
                | 0[oO][0-8_]+
                | 0[bB][10_]+
                | 0[dD][\d_]+
                | [+-]?[\d_]+
            "#).unwrap(),
            floatlit: Token::new(r#"(?x)
                [-+]? # optional sign
                (?:
                      \d+\.\d*  # numbers <dot> <optional numbers>
                    | \.\d+     # <dot> numbers
                )
                (?:
                    [eE]  # begin exponent
                    [+-]? # sign
                    \d+   # exponent
                )? # optional exponent part
            "#).unwrap(),
        }
    }
}

pub fn parse_string(inp: String) -> String {
    let mut escaped = false;
    let mut unicode = false;
    let mut uindex = 0;
    let mut uvalue = 0;
    let quote_char = inp.chars().next().expect("parse_string is parsing an empty string");
    inp.chars().filter_map(|character| {
        if escaped {
            escaped = false;
            match character {
                'n' => Some('\n'),
                'r' => Some('\r'),
                't' => Some('\t'),
                'b' => Some('\x08'),
                'f' => Some('\x0c'),
                'u' => { unicode = true; uvalue = 0; uindex = 0; None }
                 _  => Some(character),
            }
        } else if unicode {
            // code adapted from https://github.com/rust-lang/rustc-serialize/blob/master/src/json.rs#L1608-L1624
            // original licensed under MIT/Apache-2.0
            uvalue = match character {
                ctr @ '0'...'9' => uvalue * 16 + ((ctr as u16) - ('0' as u16)),
                ctr @ 'a'...'f' => uvalue * 16 + (10 + (ctr as u16) - ('a' as u16)),
                ctr @ 'A'...'F' => uvalue * 16 + (10 + (ctr as u16) - ('A' as u16)),
                _ => return None,
            };
            if uindex < 3 {
                uindex += 1;
                None
            } else {
                unicode = false;
                char::from_u32(uvalue as u32)
            }
        } else if character == quote_char {
            None
        } else if character == '\\' {
            escaped = true;
            None
        } else {
            Some(character)
        }
    }).collect()
}

pub fn parse_integer(inp: String) -> i64 {
    if inp.starts_with("0d") || inp.starts_with("0D") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 10).unwrap()
    } else if inp.starts_with("0x") || inp.starts_with("0X") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 16).unwrap()
    } else if inp.starts_with("0o") || inp.starts_with("0O") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 8).unwrap()
    } else if inp.starts_with("0b") || inp.starts_with("0B") {
        i64::from_str_radix(&inp.chars().skip(2).collect::<String>(), 2).unwrap()
    } else if inp.starts_with("+") {
        i64::from_str_radix(&inp.chars().skip(1).collect::<String>(), 10).unwrap()
    } else {
        i64::from_str_radix(&inp, 10).unwrap()
    }
}

pub fn parse_float(inp: String) -> f64 {
    if inp.starts_with("+") {
        inp.chars().skip(1).collect::<String>().parse().unwrap()
    } else {
       inp.parse().unwrap()
    }
}

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

    #[test]
    fn test_parse_string() {
        assert_eq!(parse_string("'hello'".to_string()), "hello");
        assert_eq!(parse_string(r#""hello""#.to_string()), "hello");
        assert_eq!(parse_string("'he\\nllo'".to_string()), "he\nllo");
        assert_eq!(parse_string(r#"'he"llo'"#.to_string()), "he\"llo");
        assert_eq!(parse_string(r"'\u0058'".to_string()), "\u{0058}");
    }

    #[test]
    fn test_parse_integer() {
        assert_eq!(parse_integer("0d5".to_string()), 5);
        assert_eq!(parse_integer("0D5474".to_string()), 5474);
        assert_eq!(parse_integer("0x4f3".to_string()), 0x4f3);
        assert_eq!(parse_integer("0X7Df31".to_string()), 0x7df31);
        assert_eq!(parse_integer("0o443".to_string()), 3 + (8*4) + (64*4));
        assert_eq!(parse_integer("0O70131".to_string()), 28761);
        assert_eq!(parse_integer("0b01101".to_string()), 0b01101);
        assert_eq!(parse_integer("0B10010".to_string()), 0b10010);
        assert_eq!(parse_integer("32353".to_string()), 32353);
        assert_eq!(parse_integer("-1234".to_string()), -1234);
        assert_eq!(parse_integer("+4321".to_string()), 4321);
    }

    #[test]
    fn test_parse_float() {
        println!("run");
        assert_eq!(parse_float("+1.2".to_string()), 1.2);
        println!("run");
        assert_eq!(parse_float("-1.2".to_string()), -1.2);
        println!("run");
        assert_eq!(parse_float("3.4".to_string()), 3.4);
        println!("run");
        assert_eq!(parse_float("3.".to_string()), 3.0);
        println!("run");
        assert_eq!(parse_float(".2".to_string()), 0.2);
        println!("run");
        assert_eq!(parse_float("1.2e2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2e+2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2e-2".to_string()), 1.2E-2);
        println!("run");
        assert_eq!(parse_float("1.2E2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2E+2".to_string()), 1.2E+2);
        println!("run");
        assert_eq!(parse_float("1.2E-2".to_string()), 1.2E-2);
    }

    #[test]
    fn literals_match() {
        let tk = TokenCollection::new();
        assert_eq!(tk.open_brace.get_match("{"), Some(1));
        assert_eq!(tk.open_brace.get_match("}"), None);
        assert_eq!(tk.close_brace.get_match("}"), Some(1));
        assert_eq!(tk.close_brace.get_match("d"), None);
        assert_eq!(tk.open_bracket.get_match("["), Some(1));
        assert_eq!(tk.open_bracket.get_match(" "), None);
        assert_eq!(tk.close_bracket.get_match("]"), Some(1));
        assert_eq!(tk.close_bracket.get_match("["), None);
        assert_eq!(tk.comma.get_match(","), Some(1));
        assert_eq!(tk.comma.get_match(""), None);
        assert_eq!(tk.colon.get_match(":"), Some(1));
        assert_eq!(tk.colon.get_match(";"), None);
    }

    #[test]
    fn identifier_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.identifier.get_match("hello"), Some(5));
        assert_eq!(tk.identifier.get_match("HELLO"), Some(5));
        assert_eq!(tk.identifier.get_match("45fefe"), None);
        assert_eq!(tk.identifier.get_match("fefe45"), Some(6));
        assert_eq!(tk.identifier.get_match("true"), Some(4));
        assert_eq!(tk.identifier.get_match("$"), None);
    }

    #[test]
    fn string_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.stringlit.get_match(""), None);
        assert_eq!(tk.stringlit.get_match("hello"), None);
        assert_eq!(tk.stringlit.get_match("'hello'"), Some(7));
        assert_eq!(tk.stringlit.get_match("{}[],: 'string'"), None);
        assert_eq!(tk.stringlit.get_match(r#""hello""#), Some(7));
        assert_eq!(tk.stringlit.get_match(r"'hello\n'"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'hello\''"), Some(9));
        assert_eq!(tk.stringlit.get_match(r"'
            no newline in strings'"), None);
    }

    #[test]
    fn integer_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.integerlit.get_match("345"), Some(3));
        assert_eq!(tk.integerlit.get_match("3_4_5"), Some(5));
        assert_eq!(tk.integerlit.get_match("0d3_4_5"), Some(7));
        assert_eq!(tk.integerlit.get_match("0x45"), Some(4));
        assert_eq!(tk.integerlit.get_match("0Xff"), Some(4));
        assert_eq!(tk.integerlit.get_match("0xf_f"), Some(5));
        assert_eq!(tk.integerlit.get_match("0xgg"), Some(1));
        assert_eq!(tk.integerlit.get_match("0o44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0O44"), Some(4));
        assert_eq!(tk.integerlit.get_match("0o99"), Some(1));
    }

    #[test]
    fn float_matches() {
        let tk = TokenCollection::new();
        assert_eq!(tk.floatlit.get_match("300."), Some(4));
        assert_eq!(tk.floatlit.get_match("30.0"), Some(4));
        assert_eq!(tk.floatlit.get_match(".300"), Some(4));
        assert_eq!(tk.floatlit.get_match("300"), None);
        assert_eq!(tk.floatlit.get_match("3.e5"), Some(4));
        assert_eq!(tk.floatlit.get_match("3.e-5"), Some(5));
        assert_eq!(tk.floatlit.get_match("3.E-5"), Some(5));
    }
}
<|endoftext|>