<commit_before>#![cfg_attr(feature = "qc", feature(plugin, custom_attribute))]
#![cfg_attr(feature="qc", plugin(quickcheck_macros))]
#![allow(dead_code)]

//! The purpose of these tests is to cover corner cases of iterators
//! and adaptors.
//!
//! In particular we test the tedious size_hint and exact size correctness.

#[macro_use]
extern crate itertools;

#[cfg(feature = "qc")]
extern crate quickcheck;

#[cfg(feature = "qc")]
mod quicktests {

use quickcheck as qc;
use std::ops::Range;
use itertools;
use itertools::Itertools;
use itertools::{
    Zip,
    Stride,
    EitherOrBoth,
};

/// Our base iterator that we can impl Arbitrary for
#[derive(Clone, Debug)]
pub struct Iter<T>(Range<T>);

impl<T> Iterator for Iter<T> where Range<T>: Iterator
{
    type Item = <Range<T> as Iterator>::Item;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
    fn size_hint(&self) -> (usize, Option<usize>)
    {
        self.0.size_hint()
    }
}

impl<T> DoubleEndedIterator for Iter<T> where Range<T>: DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
}

impl<T> ExactSizeIterator for Iter<T> where Range<T>: ExactSizeIterator
{ }

impl<T> qc::Arbitrary for Iter<T> where T: qc::Arbitrary
{
    fn arbitrary<G: qc::Gen>(g: &mut G) -> Self
    {
        Iter(T::arbitrary(g)..T::arbitrary(g))
    }

    fn shrink(&self) -> Box<Iterator<Item=Iter<T>>>
    {
        let r = self.0.clone();
        Box::new(
            r.start.shrink().flat_map(move |x| {
                r.end.shrink().map(move |y| (x.clone(), y))
            })
            .map(|(a, b)| Iter(a..b))
        )
    }
}

fn correct_size_hint_fast<I: Iterator>(it: I) -> bool {
    let (low, hi) = it.size_hint();
    let cnt = it.count();
    cnt >= low &&
        (hi.is_none() || hi.unwrap() >= cnt)
}

fn correct_size_hint<I: Iterator>(mut it: I) -> bool {
    // record size hint at each iteration
    let initial_hint = it.size_hint();
    let mut hints = Vec::with_capacity(initial_hint.0 + 1);
    hints.push(initial_hint);
    while let Some(_) = it.next() {
        hints.push(it.size_hint())
    }

    let mut true_count = hints.len(); // start off +1 too much

    // check all the size hints
    for &(low, hi) in &hints {
        true_count -= 1;
        if low > true_count ||
            (hi.is_some() && hi.unwrap() < true_count)
        {
            println!("True size: {:?}, size hint: {:?}", true_count, (low, hi));
            println!("All hints: {:?}", hints);
            return false
        }
    }
    true
}

fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
    // check every iteration
    let (mut low, mut hi) = it.size_hint();
    if Some(low) != hi { return false; }
    while let Some(_) = it.next() {
        let (xlow, xhi) = it.size_hint();
        if low != xlow + 1 { return false; }
        low = xlow;
        hi = xhi;
        if Some(low) != hi { return false; }
    }
    let (low, hi) = it.size_hint();
    low == 0 && hi == Some(0)
}

/*
 * NOTE: Range<i8> is broken!
 * (all signed ranges are)
#[quickcheck]
fn size_range_i8(a: Iter<i8>) -> bool {
    exact_size(a)
}

#[quickcheck]
fn size_range_i16(a: Iter<i16>) -> bool {
    exact_size(a)
}

#[quickcheck]
fn size_range_u8(a: Iter<u8>) -> bool {
    exact_size(a)
}
 */

#[quickcheck]
fn size_stride(data: Vec<u8>, mut stride: isize) -> bool {
    if stride == 0 {
        stride += 1; // never zero
    }
    exact_size(Stride::from_slice(&data, stride))
}

#[quickcheck]
fn equal_stride(data: Vec<u8>, mut stride: i8) -> bool {
    if stride == 0 {
        // never zero
        stride += 1;
    }
    if stride > 0 {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().step(stride as usize))
    } else {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().rev().step(-stride as usize))
    }
}

#[quickcheck]
fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.cartesian_product(b))
}

#[quickcheck]
fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
    correct_size_hint(iproduct!(a, b, c))
}

#[quickcheck]
fn size_step(a: Iter<u16>, mut s: usize) -> bool {
    if s == 0 {
        s += 1; // never zero
    }
    exact_size(a.step(s))
}

#[quickcheck]
fn size_multipeek(a: Iter<u16>, s: u8) -> bool {
    let mut it = a.multipeek();
    // peek a few times
    for _ in 0..s {
        it.peek();
    }
    exact_size(it)
}

#[quickcheck]
fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
    let mut sa = a.clone();
    let mut sb = b.clone();
    sa.sort();
    sb.sort();
    let mut merged = sa.clone() + &sb;
    merged.sort();
    itertools::equal(&merged, sa.iter().merge(&sb))

}
#[quickcheck]
fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.merge(b))
}

#[quickcheck]
fn size_zip(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
    exact_size(Zip::new((a, b, c)))
}

#[quickcheck]
fn size_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    exact_size(a.zip_longest(b))
}

#[quickcheck]
fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    let it = a.clone().zip_longest(b.clone());
    let jt = a.clone().zip_longest(b.clone());
    itertools::equal(a.clone(),
                     it.filter_map(|elt| match elt {
                         EitherOrBoth::Both(x, _) => Some(x),
                         EitherOrBoth::Left(x) => Some(x),
                         _ => None,
                     }
                     ))
        &&
    itertools::equal(b.clone(),
                     jt.filter_map(|elt| match elt {
                         EitherOrBoth::Both(_, y) => Some(y),
                         EitherOrBoth::Right(y) => Some(y),
                         _ => None,
                     }
                     ))
}

fn equal_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    let slc = &a[x..y];
    itertools::equal(a.iter().slice(x..y), slc)
}

fn size_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    let slc = &a[x..y];
    exact_size(a.iter().slice(x..y))
}

#[quickcheck]
fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
    correct_size_hint(a.interleave(b))
}

#[quickcheck]
fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
    correct_size_hint(a.intersperse(x))
}

#[quickcheck]
fn equal_intersperse(a: Vec<i32>, x: i32) -> bool {
    let mut inter = false;
    let mut i = 0;
    for elt in a.iter().cloned().intersperse(x) {
        if inter {
            if elt != x { return false }
        } else {
            if elt != a[i] { return false }
            i += 1;
        }
        inter = !inter;
    }
    true
}

#[quickcheck]
fn equal_dedup(a: Vec<i32>) -> bool {
    let mut b = a.clone();
    b.dedup();
    itertools::equal(&b, a.iter().dedup())
}

#[quickcheck]
fn size_dedup(a: Vec<i32>) -> bool {
    correct_size_hint(a.iter().dedup())
}

#[quickcheck]
fn size_group_by(a: Vec<i8>) -> bool {
    correct_size_hint(a.iter().group_by(|x| x.abs()))
}

#[quickcheck]
fn size_linspace(a: f32, b: f32, n: usize) -> bool {
    let it = itertools::linspace(a, b, n);
    it.len() == n &&
        exact_size(it)
}

#[quickcheck]
fn equal_repeatn(n: usize, x: i32) -> bool {
    let it = itertools::RepeatN::new(x, n);
    exact_size(it)
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted(a: Vec<u8>, b: Vec<u8>) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter())))
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted3(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter(), c.iter())))
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn equal_ziptrusted_mix(a: Vec<u8>, b: Vec<()>, x: u8, y: u8) -> bool {
    let it = itertools::ZipTrusted::new((a.iter(), b.iter(), x..y));
    let jt = Zip::new((a.iter(), b.iter(), x..y));
    itertools::equal(it, jt)
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted_mix(a: Vec<u8>, b: Vec<()>, x: u8, y: u8) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter(), x..y)))
}

#[quickcheck]
fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool {
    let mut it = itertools::PutBack::new(a.into_iter());
    match x {
        Some(t) => it.put_back(t),
        None => {}
    }
    correct_size_hint(it)
}

#[quickcheck]
fn size_tee(a: Vec<u8>) -> bool {
    let (mut t1, mut t2) = a.iter().tee();
    t1.next();
    t1.next();
    t2.next();
    exact_size(t1) && exact_size(t2)
}

}
<commit_msg>Add fuzzy size hint tests for more iterators<commit_after>#![cfg_attr(feature = "qc", feature(plugin, custom_attribute))]
#![cfg_attr(feature="qc", plugin(quickcheck_macros))]
#![allow(dead_code)]

//! The purpose of these tests is to cover corner cases of iterators
//! and adaptors.
//!
//! In particular we test the tedious size_hint and exact size correctness.

#[macro_use]
extern crate itertools;

#[cfg(feature = "qc")]
extern crate quickcheck;

#[cfg(feature = "qc")]
mod quicktests {

use quickcheck as qc;
use std::ops::Range;
use itertools;
use itertools::Itertools;
use itertools::{
    Zip,
    Stride,
    EitherOrBoth,
};

/// Our base iterator that we can impl Arbitrary for
#[derive(Clone, Debug)]
pub struct Iter<T>(Range<T>);

impl<T> Iterator for Iter<T> where Range<T>: Iterator
{
    type Item = <Range<T> as Iterator>::Item;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
    fn size_hint(&self) -> (usize, Option<usize>)
    {
        self.0.size_hint()
    }
}

impl<T> DoubleEndedIterator for Iter<T> where Range<T>: DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
}

impl<T> ExactSizeIterator for Iter<T> where Range<T>: ExactSizeIterator
{ }

impl<T> qc::Arbitrary for Iter<T> where T: qc::Arbitrary
{
    fn arbitrary<G: qc::Gen>(g: &mut G) -> Self
    {
        Iter(T::arbitrary(g)..T::arbitrary(g))
    }

    fn shrink(&self) -> Box<Iterator<Item=Iter<T>>>
    {
        let r = self.0.clone();
        Box::new(
            r.start.shrink().flat_map(move |x| {
                r.end.shrink().map(move |y| (x.clone(), y))
            })
            .map(|(a, b)| Iter(a..b))
        )
    }
}

fn correct_size_hint_fast<I: Iterator>(it: I) -> bool {
    let (low, hi) = it.size_hint();
    let cnt = it.count();
    cnt >= low &&
        (hi.is_none() || hi.unwrap() >= cnt)
}

fn correct_size_hint<I: Iterator>(mut it: I) -> bool {
    // record size hint at each iteration
    let initial_hint = it.size_hint();
    let mut hints = Vec::with_capacity(initial_hint.0 + 1);
    hints.push(initial_hint);
    while let Some(_) = it.next() {
        hints.push(it.size_hint())
    }

    let mut true_count = hints.len(); // start off +1 too much

    // check all the size hints
    for &(low, hi) in &hints {
        true_count -= 1;
        if low > true_count ||
            (hi.is_some() && hi.unwrap() < true_count)
        {
            println!("True size: {:?}, size hint: {:?}", true_count, (low, hi));
            println!("All hints: {:?}", hints);
            return false
        }
    }
    true
}

fn exact_size<I: ExactSizeIterator>(mut it: I) -> bool {
    // check every iteration
    let (mut low, mut hi) = it.size_hint();
    if Some(low) != hi { return false; }
    while let Some(_) = it.next() {
        let (xlow, xhi) = it.size_hint();
        if low != xlow + 1 { return false; }
        low = xlow;
        hi = xhi;
        if Some(low) != hi { return false; }
    }
    let (low, hi) = it.size_hint();
    low == 0 && hi == Some(0)
}

/*
 * NOTE: Range<i8> is broken!
 * (all signed ranges are)
#[quickcheck]
fn size_range_i8(a: Iter<i8>) -> bool {
    exact_size(a)
}

#[quickcheck]
fn size_range_i16(a: Iter<i16>) -> bool {
    exact_size(a)
}

#[quickcheck]
fn size_range_u8(a: Iter<u8>) -> bool {
    exact_size(a)
}
 */

#[quickcheck]
fn size_stride(data: Vec<u8>, mut stride: isize) -> bool {
    if stride == 0 {
        stride += 1; // never zero
    }
    exact_size(Stride::from_slice(&data, stride))
}

#[quickcheck]
fn equal_stride(data: Vec<u8>, mut stride: i8) -> bool {
    if stride == 0 {
        // never zero
        stride += 1;
    }
    if stride > 0 {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().step(stride as usize))
    } else {
        itertools::equal(Stride::from_slice(&data, stride as isize),
                         data.iter().rev().step(-stride as usize))
    }
}

#[quickcheck]
fn size_product(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.cartesian_product(b))
}

#[quickcheck]
fn size_product3(a: Iter<u16>, b: Iter<u16>, c: Iter<u16>) -> bool {
    correct_size_hint(iproduct!(a, b, c))
}

#[quickcheck]
fn size_step(a: Iter<i16>, mut s: usize) -> bool {
    if s == 0 {
        s += 1; // never zero
    }
    let filt = a.clone().dedup();
    correct_size_hint(filt.step(s)) &&
        exact_size(a.step(s))
}

#[quickcheck]
fn size_multipeek(a: Iter<u16>, s: u8) -> bool {
    let mut it = a.multipeek();
    // peek a few times
    for _ in 0..s {
        it.peek();
    }
    exact_size(it)
}

#[quickcheck]
fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
    let mut sa = a.clone();
    let mut sb = b.clone();
    sa.sort();
    sb.sort();
    let mut merged = sa.clone() + &sb;
    merged.sort();
    itertools::equal(&merged, sa.iter().merge(&sb))

}
#[quickcheck]
fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
    correct_size_hint(a.merge(b))
}

#[quickcheck]
fn size_zip(a: Iter<i16>, b: Iter<i16>, c: Iter<i16>) -> bool {
    let filt = a.clone().dedup();
    correct_size_hint(Zip::new((filt, b.clone(), c.clone()))) &&
        exact_size(Zip::new((a, b, c)))
}

#[quickcheck]
fn size_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    let filt = a.clone().dedup();
    let filt2 = b.clone().dedup();
    correct_size_hint(filt.zip_longest(b.clone())) &&
    correct_size_hint(a.clone().zip_longest(filt2)) &&
        exact_size(a.zip_longest(b))
}

#[quickcheck]
fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
    let it = a.clone().zip_longest(b.clone());
    let jt = a.clone().zip_longest(b.clone());
    itertools::equal(a.clone(),
                     it.filter_map(|elt| match elt {
                         EitherOrBoth::Both(x, _) => Some(x),
                         EitherOrBoth::Left(x) => Some(x),
                         _ => None,
                     }
                     ))
        &&
    itertools::equal(b.clone(),
                     jt.filter_map(|elt| match elt {
                         EitherOrBoth::Both(_, y) => Some(y),
                         EitherOrBoth::Right(y) => Some(y),
                         _ => None,
                     }
                     ))
}

fn equal_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    let slc = &a[x..y];
    itertools::equal(a.iter().slice(x..y), slc)
}

fn size_islice(a: Vec<i16>, x: usize, y: usize) -> bool {
    if x > y || y > a.len() { return true; }
    correct_size_hint(a.iter().dedup().slice(x..y)) &&
        exact_size(a.iter().slice(x..y))
}

#[quickcheck]
fn size_interleave(a: Iter<i16>, b: Iter<i16>) -> bool {
    correct_size_hint(a.interleave(b))
}

#[quickcheck]
fn size_intersperse(a: Iter<i16>, x: i16) -> bool {
    correct_size_hint(a.intersperse(x))
}

#[quickcheck]
fn equal_intersperse(a: Vec<i32>, x: i32) -> bool {
    let mut inter = false;
    let mut i = 0;
    for elt in a.iter().cloned().intersperse(x) {
        if inter {
            if elt != x { return false }
        } else {
            if elt != a[i] { return false }
            i += 1;
        }
        inter = !inter;
    }
    true
}

#[quickcheck]
fn equal_dedup(a: Vec<i32>) -> bool {
    let mut b = a.clone();
    b.dedup();
    itertools::equal(&b, a.iter().dedup())
}

#[quickcheck]
fn size_dedup(a: Vec<i32>) -> bool {
    correct_size_hint(a.iter().dedup())
}

#[quickcheck]
fn size_group_by(a: Vec<i8>) -> bool {
    correct_size_hint(a.iter().group_by(|x| x.abs()))
}

#[quickcheck]
fn size_linspace(a: f32, b: f32, n: usize) -> bool {
    let it = itertools::linspace(a, b, n);
    it.len() == n &&
        exact_size(it)
}

#[quickcheck]
fn equal_repeatn(n: usize, x: i32) -> bool {
    let it = itertools::RepeatN::new(x, n);
    exact_size(it)
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted(a: Vec<u8>, b: Vec<u8>) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter())))
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted3(a: Vec<u8>, b: Vec<u8>, c: Vec<u8>) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter(), c.iter())))
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn equal_ziptrusted_mix(a: Vec<u8>, b: Vec<()>, x: u8, y: u8) -> bool {
    let it = itertools::ZipTrusted::new((a.iter(), b.iter(), x..y));
    let jt = Zip::new((a.iter(), b.iter(), x..y));
    itertools::equal(it, jt)
}

#[cfg(feature = "unstable")]
#[quickcheck]
fn size_ziptrusted_mix(a: Vec<u8>, b: Vec<()>, x: u8, y: u8) -> bool {
    exact_size(itertools::ZipTrusted::new((a.iter(), b.iter(), x..y)))
}

#[quickcheck]
fn size_put_back(a: Vec<u8>, x: Option<u8>) -> bool {
    let mut it = itertools::PutBack::new(a.into_iter());
    match x {
        Some(t) => it.put_back(t),
        None => {}
    }
    correct_size_hint(it)
}

#[quickcheck]
fn size_tee(a: Vec<u8>) -> bool {
    let (mut t1, mut t2) = a.iter().tee();
    t1.next();
    t1.next();
    t2.next();
    exact_size(t1) && exact_size(t2)
}

#[quickcheck]
fn size_tee_2(a: Vec<u8>) -> bool {
    let (mut t1, mut t2) = a.iter().dedup().tee();
    t1.next();
    t1.next();
    t2.next();
    correct_size_hint(t1) && correct_size_hint(t2)
}

}
<|endoftext|>


<commit_before>//! Arthas is an in-memory structure database.
//!
//! # Usage
//!
//! 1. Add dependencies to `Cargo.toml`.
//!
//!     ```html
//!     [dependencies]
//!     arthas = "^0.1"
//!     arthas_plugin = "^0.1"
//!     serde_derive = "^0.8"
//!     ```
//!
//! 2. In your `main.rs` or `lib.rs`:
//!
//!     ```html
//!     #![feature(proc_macro, plugin, custom_derive)]
//!     #![plugin(arthas_plugin)]
//!
//!     #[macro_use]
//!     extern crate serde_derive;
//!     extern crate arthas;
//!     ```
//!
//! 3. Add `[arthas]` attribute to your `struct`:
//!
//!     ```html
//!     #[arthas]
//!     pub struct Article {
//!         pub _id: String,    // If you want to use id. add a field named `_id`.
//!         pub title: String,
//!         pub content: String,
//!         pub views: usize,
//!     }
//!     ```
//!
//!
//! # CRUD Examples
//! All struct can use the static method `session()`. `session()` will return a [`Query`](struct.Query.html).
//!
//! ```
//! extern crate arthas;
//! extern crate model;  // `model` crate can be found in the `examples` directory.
//!
//! use arthas::prelude::*;
//! use model::Article;
//!
//! fn main() {
//!     // Disable persistence for the tests.
//!     arthas::config::persistence(false);
//!
//!     // Insert
//!     let id = Article::session().insert(Article::new("Hello world!")).unwrap();
//!
//!     // Update
//!     Article::session().id(&id).update(|article| article.views = 10).unwrap();
//!
//!     // Find
//!     let items = Article::session().find().unwrap();
//!     assert!(items.len() > 0);
//!
//!     // Find One
//!     let item = Article::session().id(&id).find_one().unwrap();
//!     assert!(item.is_some());
//!     assert_eq!(item.unwrap().title, "Hello world!");
//!
//!     // Remove
//!     Article::session().id(&id).remove().unwrap();
//! }
//! ```
//!
//! # Load Persistence
//! Arthas will not automatically load persistence from disk, you have to load persistence yourself.
//!
//! ```html
//! arthas::load::<Article>();  // Load `Article`'s persistence.
//! ```
//!
//! # Update Structure
//! Sometimes you want to update your structure. Like renaming or removing fields. Arthas will automatically remove and add fields, but you have to tell Arthas if you want to **rename** fields.
//!
//! ```html
//! #[arthas]
//! #[arthas_rename = "content = body, views = visit"] // Use `[arthas_rename]` attribute.
//! pub struct Article {
//!     pub _id: String,
//!     pub title: String,
//!     pub body: String,   // This is the field renamed from `content`
//!     pub visit: usize,   // This is the field renamed from `views`
//! }
//! ```
//!
#![feature(core_intrinsics, proc_macro)]
#![cfg_attr(all(test), feature(test))]
#![deny(missing_docs)]

#[cfg(test)]
extern crate test;
#[cfg(test)]
#[macro_use]
extern crate maplit;
#[cfg(test)]
extern crate model;
#[cfg(test)]
extern crate env_logger;

#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate serde_json;
extern crate memmap;
extern crate bincode;
extern crate serde;
extern crate glob;
extern crate num_cpus;
extern crate scoped_pool;
extern crate quickersort;
extern crate objectid;
extern crate thread_id;
extern crate chrono;
extern crate vec_map;

#[macro_use]
mod macros;
mod encoder;
mod memory;
mod persistence;
mod store;
mod utils;
mod loader;
mod query;
mod error;
mod tree;
mod item;

#[doc(hidden)]
pub mod traits;
pub mod prelude;

pub use query::Query;
pub use error::Error;
pub use item::Id;

pub mod types;
pub mod config;

/// Load persistence.
pub fn load<T: traits::Structure>() {
    loader::load::<T>();
}

const DATA_EXTENSION: &'static str = "ar";
const PERSISTENCE_EXTENSION: &'static str = "arx";
const LOG_EXTENSION: &'static str = "arl";
const SAVING_EXTENSION: &'static str = "saving";
const DATA_DIR: &'static str = "arthas.ar";
const BINENCODE: bool = true;
<commit_msg>hide types module.<commit_after>//! Arthas is an in-memory structure database.
//!
//! # Usage
//!
//! 1. Add dependencies to `Cargo.toml`.
//!
//!     ```html
//!     [dependencies]
//!     arthas = "^0.1"
//!     arthas_plugin = "^0.1"
//!     serde_derive = "^0.8"
//!     ```
//!
//! 2. In your `main.rs` or `lib.rs`:
//!
//!     ```html
//!     #![feature(proc_macro, plugin, custom_derive)]
//!     #![plugin(arthas_plugin)]
//!
//!     #[macro_use]
//!     extern crate serde_derive;
//!     extern crate arthas;
//!     ```
//!
//! 3. Add `[arthas]` attribute to your `struct`:
//!
//!     ```html
//!     #[arthas]
//!     pub struct Article {
//!         pub _id: String,    // If you want to use id. add a field named `_id`.
//!         pub title: String,
//!         pub content: String,
//!         pub views: usize,
//!     }
//!     ```
//!
//!
//! # CRUD Examples
//! All struct can use the static method `session()`. `session()` will return a [`Query`](struct.Query.html).
//!
//! ```
//! extern crate arthas;
//! extern crate model;  // `model` crate can be found in the `examples` directory.
//!
//! use arthas::prelude::*;
//! use model::Article;
//!
//! fn main() {
//!     // Disable persistence for the tests.
//!     arthas::config::persistence(false);
//!
//!     // Insert
//!     let id = Article::session().insert(Article::new("Hello world!")).unwrap();
//!
//!     // Update
//!     Article::session().id(&id).update(|article| article.views = 10).unwrap();
//!
//!     // Find
//!     let items = Article::session().find().unwrap();
//!     assert!(items.len() > 0);
//!
//!     // Find One
//!     let item = Article::session().id(&id).find_one().unwrap();
//!     assert!(item.is_some());
//!     assert_eq!(item.unwrap().title, "Hello world!");
//!
//!     // Remove
//!     Article::session().id(&id).remove().unwrap();
//! }
//! ```
//!
//! # Load Persistence
//! Arthas will not automatically load persistence from disk, you have to load persistence yourself.
//!
//! ```html
//! arthas::load::<Article>();  // Load `Article`'s persistence.
//! ```
//!
//! # Update Structure
//! Sometimes you want to update your structure. Like renaming or removing fields. Arthas will automatically remove and add fields, but you have to tell Arthas if you want to **rename** fields.
//!
//! ```html
//! #[arthas]
//! #[arthas_rename = "content = body, views = visit"] // Use `[arthas_rename]` attribute.
//! pub struct Article {
//!     pub _id: String,
//!     pub title: String,
//!     pub body: String,   // This is the field renamed from `content`
//!     pub visit: usize,   // This is the field renamed from `views`
//! }
//! ```
//!
#![feature(core_intrinsics, proc_macro)]
#![cfg_attr(all(test), feature(test))]
#![deny(missing_docs)]

#[cfg(test)]
extern crate test;
#[cfg(test)]
#[macro_use]
extern crate maplit;
#[cfg(test)]
extern crate model;
#[cfg(test)]
extern crate env_logger;

#[macro_use]
extern crate quick_error;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate serde_json;
extern crate memmap;
extern crate bincode;
extern crate serde;
extern crate glob;
extern crate num_cpus;
extern crate scoped_pool;
extern crate quickersort;
extern crate objectid;
extern crate thread_id;
extern crate chrono;
extern crate vec_map;

#[macro_use]
mod macros;
mod encoder;
mod memory;
mod persistence;
mod store;
mod utils;
mod loader;
mod query;
mod error;
mod tree;
mod item;

#[doc(hidden)]
pub mod traits;
pub mod prelude;

pub use query::Query;
pub use error::Error;
pub use item::Id;

#[doc(hidden)]
pub mod types;
pub mod config;

/// Load persistence.
pub fn load<T: traits::Structure>() {
    loader::load::<T>();
}

const DATA_EXTENSION: &'static str = "ar";
const PERSISTENCE_EXTENSION: &'static str = "arx";
const LOG_EXTENSION: &'static str = "arl";
const SAVING_EXTENSION: &'static str = "saving";
const DATA_DIR: &'static str = "arthas.ar";
const BINENCODE: bool = true;
<|endoftext|>


<commit_before>//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory unless the `--all` flag is present.

use std::fs;
use std::io::{self, ErrorKind};
use std::path::Path;

use build_helper::t;

use crate::Build;

pub fn clean(build: &Build, all: bool) {
    rm_rf("tmp".as_ref());

    if all {
        rm_rf(&build.out);
    } else {
        rm_rf(&build.out.join("tmp"));
        rm_rf(&build.out.join("dist"));

        for host in &build.hosts {
            let entries = match build.out.join(host.triple).read_dir() {
                Ok(iter) => iter,
                Err(_) => continue,
            };

            for entry in entries {
                let entry = t!(entry);
                if entry.file_name().to_str() == Some("llvm") {
                    continue;
                }
                let path = t!(entry.path().canonicalize());
                rm_rf(&path);
            }
        }
    }
}

fn rm_rf(path: &Path) {
    match path.symlink_metadata() {
        Err(e) => {
            if e.kind() == ErrorKind::NotFound {
                return;
            }
            panic!("failed to get metadata for file {}: {}", path.display(), e);
        }
        Ok(metadata) => {
            if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
                do_op(path, "remove file", |p| fs::remove_file(p));
                return;
            }

            for file in t!(fs::read_dir(path)) {
                rm_rf(&t!(file).path());
            }
            do_op(path, "remove dir", |p| fs::remove_dir(p));
        }
    };
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        // On windows we can't remove a readonly file, and git will often clone files as readonly.
        // As a result, we have some special logic to remove readonly files on windows.
        // This is also the reason that we can't use things like fs::remove_dir_all().
        Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.symlink_metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));
            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}
<commit_msg>Clean bootstrap artifacts on `x.py clean`<commit_after>//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory unless the `--all` flag is present.

use std::fs;
use std::io::{self, ErrorKind};
use std::path::Path;

use build_helper::t;

use crate::Build;

pub fn clean(build: &Build, all: bool) {
    rm_rf("tmp".as_ref());

    if all {
        rm_rf(&build.out);
    } else {
        rm_rf(&build.out.join("tmp"));
        rm_rf(&build.out.join("dist"));
        rm_rf(&build.out.join("bootstrap"));

        for host in &build.hosts {
            let entries = match build.out.join(host.triple).read_dir() {
                Ok(iter) => iter,
                Err(_) => continue,
            };

            for entry in entries {
                let entry = t!(entry);
                if entry.file_name().to_str() == Some("llvm") {
                    continue;
                }
                let path = t!(entry.path().canonicalize());
                rm_rf(&path);
            }
        }
    }
}

fn rm_rf(path: &Path) {
    match path.symlink_metadata() {
        Err(e) => {
            if e.kind() == ErrorKind::NotFound {
                return;
            }
            panic!("failed to get metadata for file {}: {}", path.display(), e);
        }
        Ok(metadata) => {
            if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
                do_op(path, "remove file", |p| fs::remove_file(p));
                return;
            }

            for file in t!(fs::read_dir(path)) {
                rm_rf(&t!(file).path());
            }
            do_op(path, "remove dir", |p| fs::remove_dir(p));
        }
    };
}

fn do_op<F>(path: &Path, desc: &str, mut f: F)
where
    F: FnMut(&Path) -> io::Result<()>,
{
    match f(path) {
        Ok(()) => {}
        // On windows we can't remove a readonly file, and git will often clone files as readonly.
        // As a result, we have some special logic to remove readonly files on windows.
        // This is also the reason that we can't use things like fs::remove_dir_all().
        Err(ref e) if cfg!(windows) && e.kind() == ErrorKind::PermissionDenied => {
            let mut p = t!(path.symlink_metadata()).permissions();
            p.set_readonly(false);
            t!(fs::set_permissions(path, p));
            f(path).unwrap_or_else(|e| {
                panic!("failed to {} {}: {}", desc, path.display(), e);
            })
        }
        Err(e) => {
            panic!("failed to {} {}: {}", desc, path.display(), e);
        }
    }
}
<|endoftext|>


<commit_before>use buffer::Distance;
use std::cmp::{PartialOrd, Ordering};

/// A two (zero-based) coordinate value representing a location in a buffer.
/// The `offset` field is so named to emphasize that positions point to
/// locations before/after characters, not characters themselves, in an effort
/// to avoid fencepost errors.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Position {
    pub line:   usize,
    pub offset: usize,
}

impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
        Some(
            if self.line < other.line {
                Ordering::Less
            } else if self.line > other.line {
                Ordering::Greater
            } else {
                if self.offset < other.offset {
                    Ordering::Less
                } else if self.offset > other.offset {
                    Ordering::Greater
                } else {
                    Ordering::Equal
                }
            }
        )
    }
}

impl Position {
    /// Creates a new position with a line/offset of 0.
    ///
    /// # Examples
    ///
    /// ```
    /// use scribe::buffer::Position;
    ///
    /// let mut position = Position::new();
    /// assert_eq!(position, Position{
    ///     line: 0,
    ///     offset: 0
    /// });
    pub fn new() -> Position {
        Position{ line: 0, offset: 0 }
    }

    /// Adds the specified Distance to the position.
    ///
    /// # Examples
    ///
    /// ```
    /// use scribe::buffer::{Distance, Position};
    ///
    /// let mut position = Position{ line: 1, offset: 3 };
    /// let distance = Distance{ lines: 1, offset: 4 };
    /// position.add(&distance);
    ///
    /// assert_eq!(position, Position{
    ///     line: 2,
    ///     offset: 4
    /// });
    /// ```
    pub fn add(&mut self, distance: &Distance) {
        self.line += distance.lines;

        if distance.lines > 0 {
            self.offset = distance.offset;
        } else {
            self.offset += distance.offset;
        }
    }
}

#[cfg(test)]
mod tests {
    use buffer::{Distance, Position};

    #[test]
    fn compare_works_when_lines_differ() {
        // Important to make the earlier position have a greater
        // offset, since that's an easy mistake to make.
        let earlier_position = Position{ line: 2, offset: 20 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 20};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_and_offsets_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position <= later_position);
        assert!(earlier_position >= later_position);

        // This is technically not necessary since we
        // derive the PartialEq trait, which provides
        // the implementation for this.
        assert!(earlier_position == later_position);
    }

    #[test]
    fn add_works_with_zero_line_distance() {
        let mut position = Position{ line: 1, offset: 3 };
        let distance = Distance{ lines: 0, offset: 4 };
        position.add(&distance);

        assert_eq!(position, Position{
            line: 1,
            offset: 7
        });
    }
}
<commit_msg>Implement add operation for position type<commit_after>use buffer::Distance;
use std::cmp::{PartialOrd, Ordering};
use std::ops::Add;

/// A two (zero-based) coordinate value representing a location in a buffer.
/// The `offset` field is so named to emphasize that positions point to
/// locations before/after characters, not characters themselves, in an effort
/// to avoid fencepost errors.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Position {
    pub line:   usize,
    pub offset: usize,
}

impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
        Some(
            if self.line < other.line {
                Ordering::Less
            } else if self.line > other.line {
                Ordering::Greater
            } else {
                if self.offset < other.offset {
                    Ordering::Less
                } else if self.offset > other.offset {
                    Ordering::Greater
                } else {
                    Ordering::Equal
                }
            }
        )
    }
}

impl Add<Distance> for Position {
    type Output = Position;

    fn add(self, distance: Distance) -> Self::Output {
        let offset =
            if distance.lines > 0 {
                distance.offset
            } else {
                self.offset + distance.offset
            };

        Position {
            line: self.line + distance.lines,
            offset: offset
        }
    }
}

impl Position {
    /// Creates a new position with a line/offset of 0.
    ///
    /// # Examples
    ///
    /// ```
    /// use scribe::buffer::Position;
    ///
    /// let mut position = Position::new();
    /// assert_eq!(position, Position{
    ///     line: 0,
    ///     offset: 0
    /// });
    pub fn new() -> Position {
        Position{ line: 0, offset: 0 }
    }

    /// Adds the specified Distance to the position.
    ///
    /// # Examples
    ///
    /// ```
    /// use scribe::buffer::{Distance, Position};
    ///
    /// let mut position = Position{ line: 1, offset: 3 };
    /// let distance = Distance{ lines: 1, offset: 4 };
    /// position.add(&distance);
    ///
    /// assert_eq!(position, Position{
    ///     line: 2,
    ///     offset: 4
    /// });
    /// ```
    pub fn add(&mut self, distance: &Distance) {
        self.line += distance.lines;

        if distance.lines > 0 {
            self.offset = distance.offset;
        } else {
            self.offset += distance.offset;
        }
    }
}

#[cfg(test)]
mod tests {
    use buffer::{Distance, Position};

    #[test]
    fn compare_works_when_lines_differ() {
        // Important to make the earlier position have a greater
        // offset, since that's an easy mistake to make.
        let earlier_position = Position{ line: 2, offset: 20 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 20};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_and_offsets_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position <= later_position);
        assert!(earlier_position >= later_position);

        // This is technically not necessary since we
        // derive the PartialEq trait, which provides
        // the implementation for this.
        assert!(earlier_position == later_position);
    }

    #[test]
    fn add_works_with_zero_line_distance() {
        let mut position = Position{ line: 1, offset: 3 };
        let distance = Distance{ lines: 0, offset: 4 };
        position.add(&distance);

        assert_eq!(position, Position{
            line: 1,
            offset: 7
        });
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::dispatch::{CostedReturnType, NativeReturnType, Result, StackAccessor};
use nextgen_crypto::{ed25519, traits::*};
use std::convert::TryFrom;

// TODO: Talk to Crypto to determine these costs
const ED25519_COST: u64 = 35;

pub fn native_ed25519_signature_verification<T: StackAccessor>(
    mut accessor: T,
) -> Result<CostedReturnType> {
    let msg = accessor.get_byte_array()?;
    let pubkey = accessor.get_byte_array()?;
    let signature = accessor.get_byte_array()?;

    let native_cost = ED25519_COST * msg.len() as u64;

    let sig = ed25519::Ed25519Signature::try_from(signature.as_bytes())?;
    let pk = ed25519::Ed25519PublicKey::try_from(pubkey.as_bytes())?;

    match sig.verify_arbitrary_msg(msg.as_bytes(), &pk) {
        Ok(()) => Ok(CostedReturnType::new(
            native_cost,
            NativeReturnType::Bool(true),
        )),
        Err(_) => Ok(CostedReturnType::new(
            native_cost,
            NativeReturnType::Bool(false),
        )),
    }
}
<commit_msg>cargo fmt fix<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::dispatch::{CostedReturnType, NativeReturnType, Result, StackAccessor};
use nextgen_crypto::{ed25519, traits::*};
use std::convert::TryFrom;

// TODO: Talk to Crypto to determine these costs
const ED25519_COST: u64 = 35;

pub fn native_ed25519_signature_verification<T: StackAccessor>(
    mut accessor: T,
) -> Result<CostedReturnType> {
    let msg = accessor.get_byte_array()?;
    let pubkey = accessor.get_byte_array()?;
    let signature = accessor.get_byte_array()?;

    let native_cost = ED25519_COST * msg.len() as u64;

    let sig = ed25519::Ed25519Signature::try_from(signature.as_bytes())?;
    let pk = ed25519::Ed25519PublicKey::try_from(pubkey.as_bytes())?;

    match sig.verify_arbitrary_msg(msg.as_bytes(), &pk) {
        Ok(()) => Ok(CostedReturnType::new(
            native_cost,
            NativeReturnType::Bool(true),
        )),
        Err(_) => Ok(CostedReturnType::new(
            native_cost,
            NativeReturnType::Bool(false),
        )),
    }
}
<|endoftext|>


<commit_before>use entities::*;
use business::error::RepoError;
use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use std::result;
use business::db::Db;
use super::models;
use super::schema;

type Result<T> = result::Result<T, RepoError>;

impl Db for SqliteConnection {
    fn create_entry(&mut self, e: &Entry) -> Result<()> {
        let new_entry = models::Entry::from(e.clone());
        let cat_rels: Vec<_> = e.categories
            .iter()
            .cloned()
            .map(|category_id| {
                models::EntryCategoryRelation {
                    entry_id: e.id.clone(),
                    category_id,
                }
            })
            .collect();
        diesel::insert_into(schema::entries::table)
            .values(&new_entry)
            .execute(self)?;
        diesel::insert_into(schema::entry_category_relations::table)
            //WHERE NOT EXISTS
            .values(&cat_rels)
            .execute(self)?;
        Ok(())
    }
    fn create_tag(&mut self, t: &Tag) -> Result<()> {
        diesel::insert_into(schema::tags::table)
            .values(&models::Tag::from(t.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_triple(&mut self, t: &Triple) -> Result<()> {
        diesel::insert_into(schema::triples::table)
            .values(&models::Triple::from(t.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_user(&mut self, u: &User) -> Result<()> {
        diesel::insert_into(schema::users::table)
            .values(&models::User::from(u.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_comment(&mut self, c: &Comment) -> Result<()> {
        diesel::insert_into(schema::comments::table)
            .values(&models::Comment::from(c.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_rating(&mut self, r: &Rating) -> Result<()> {
        diesel::insert_into(schema::ratings::table)
            .values(&models::Rating::from(r.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_bbox_subscription(&mut self, sub: &BboxSubscription) -> Result<()> {
        diesel::insert_into(schema::bbox_subscriptions::table)
            .values(&models::BboxSubscription::from(sub.clone()))
            .execute(self)?;
        Ok(())
    }
    fn all_users(&self) -> Result<Vec<User>> {
        use self::schema::users::dsl;
        Ok(
            dsl::users
                .load::<models::User>(self)?
                .into_iter()
                .map(User::from)
                .collect(),
        )
    }
    fn all_bbox_subscriptions(&self) -> Result<Vec<BboxSubscription>> {
        use self::schema::bbox_subscriptions::dsl;
        Ok(
            dsl::bbox_subscriptions
                .load::<models::BboxSubscription>(self)?
                .into_iter()
                .map(BboxSubscription::from)
                .collect(),
        )
    }
    fn confirm_email_address(&mut self, username: &str) -> Result<User> {
        use self::schema::users::dsl;
        diesel::update(dsl::users.find(username))
            .set(dsl::email_confirmed.eq(true))
            .execute(self)?;
        Ok(User::from(self.get_user(username)?))
    }
    fn delete_bbox_subscription(&mut self, id: &str) -> Result<()> {
        use self::schema::bbox_subscriptions::dsl;
        diesel::delete(dsl::bbox_subscriptions.find(id)).execute(self)?;
        Ok(())
    }
    fn delete_user(&mut self, user: &str) -> Result<()> {
        use self::schema::users::dsl::*;
        diesel::delete(users.find(user)).execute(self)?;
        Ok(())
    }

    fn get_entry(&self, e_id: &str) -> Result<Entry> {
        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let models::Entry {
            id,
            created,
            version,
            title,
            description,
            lat,
            lng,
            street,
            zip,
            city,
            country,
            email,
            telephone,
            homepage,
            license,
        } = e_dsl::entries.find(e_id).first(self)?;

        let categories = e_c_dsl::entry_category_relations
            .filter(e_c_dsl::entry_id.eq(&id))
            .load::<models::EntryCategoryRelation>(self)?
            .into_iter()
            .map(|r| r.category_id)
            .collect();

        Ok(Entry {
            id,
            created: created as u64,
            version: version as u64,
            title,
            description,
            lat: lat as f64,
            lng: lng as f64,
            street,
            zip,
            city,
            country,
            email,
            telephone,
            homepage,
            categories,
            license,
        })
    }

    fn get_user(&self, user_id: &str) -> Result<User> {
        use self::schema::users::dsl::*;
        let u: models::User = users.find(user_id).first(self)?;
        Ok(User::from(u))
    }

    fn all_entries(&self) -> Result<Vec<Entry>> {
        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let entries: Vec<models::Entry> = e_dsl::entries.load(self)?;
        let cat_rels = e_c_dsl::entry_category_relations
            .load::<models::EntryCategoryRelation>(self)?;

        Ok(
            entries
                .into_iter()
                .map(|e| {
                    let cats = cat_rels
                        .iter()
                        .filter(|r| r.entry_id == e.id)
                        .map(|r| &r.category_id)
                        .cloned()
                        .collect();
                    Entry {
                        id: e.id,
                        created: e.created as u64,
                        version: e.version as u64,
                        title: e.title,
                        description: e.description,
                        lat: e.lat as f64,
                        lng: e.lng as f64,
                        street: e.street,
                        zip: e.zip,
                        city: e.city,
                        country: e.country,
                        email: e.email,
                        telephone: e.telephone,
                        homepage: e.homepage,
                        categories: cats,
                        license: e.license,
                    }
                })
                .collect(),
        )
    }
    fn all_categories(&self) -> Result<Vec<Category>> {
        use self::schema::categories::dsl::*;
        Ok(
            categories
                .load::<models::Category>(self)?
                .into_iter()
                .map(Category::from)
                .collect(),
        )
    }
    fn all_tags(&self) -> Result<Vec<Tag>> {
        use self::schema::tags::dsl::*;
        Ok(
            tags.load::<models::Tag>(self)?
                .into_iter()
                .map(Tag::from)
                .collect(),
        )

    }
    fn all_triples(&self) -> Result<Vec<Triple>> {
        use self::schema::triples::dsl::*;
        Ok(
            triples
                .load::<models::Triple>(self)?
                .into_iter()
                .map(Triple::from)
                .collect(),
        )
    }
    fn all_ratings(&self) -> Result<Vec<Rating>> {
        use self::schema::ratings::dsl::*;
        Ok(
            ratings
                .load::<models::Rating>(self)?
                .into_iter()
                .map(Rating::from)
                .collect(),
        )
    }
    fn all_comments(&self) -> Result<Vec<Comment>> {
        use self::schema::comments::dsl::*;
        Ok(
            comments
                .load::<models::Comment>(self)?
                .into_iter()
                .map(Comment::from)
                .collect(),
        )
    }

    fn update_entry(&mut self, entry: &Entry) -> Result<()> {

        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let e = models::Entry::from(entry.clone());

        diesel::update(e_dsl::entries.find(e.id))
            .set((
                e_dsl::created.eq(e.created),
                e_dsl::version.eq(e.version),
                e_dsl::title.eq(e.title),
                e_dsl::description.eq(e.description),
                e_dsl::lat.eq(e.lat),
                e_dsl::lng.eq(e.lng),
                e_dsl::street.eq(e.street),
                e_dsl::zip.eq(e.zip),
                e_dsl::city.eq(e.city),
                e_dsl::country.eq(e.country),
                e_dsl::email.eq(e.email),
                e_dsl::telephone.eq(e.telephone),
                e_dsl::homepage.eq(e.homepage),
                e_dsl::license.eq(e.license),
            ))
            .execute(self)?;

        diesel::delete(e_c_dsl::entry_category_relations.filter(
            e_c_dsl::entry_id.eq(
                &entry.id,
            ),
        )).execute(self)?;

        let cat_rels: Vec<_> = entry
            .categories
            .iter()
            .cloned()
            .map(|category_id| {
                models::EntryCategoryRelation {
                    entry_id: entry.id.clone(),
                    category_id,
                }
            })
            .collect();

        diesel::insert_into(schema::entry_category_relations::table)
            //WHERE NOT EXISTS
            .values(&cat_rels)
            .execute(self)?;

        Ok(())
    }

    fn delete_triple(&mut self, t: &Triple) -> Result<()> {
        use self::schema::triples::dsl::*;
        let t = models::Triple::from(t.clone());
        diesel::delete(triples.find((t.subject_id, t.predicate, t.object_id)))
            .execute(self)?;
        Ok(())
    }
}
<commit_msg>new(db): use transactions<commit_after>use entities::*;
use business::error::RepoError;
use diesel;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use std::result;
use business::db::Db;
use super::models;
use super::schema;

type Result<T> = result::Result<T, RepoError>;

impl Db for SqliteConnection {
    fn create_entry(&mut self, e: &Entry) -> Result<()> {
        let new_entry = models::Entry::from(e.clone());
        let cat_rels: Vec<_> = e.categories
            .iter()
            .cloned()
            .map(|category_id| {
                models::EntryCategoryRelation {
                    entry_id: e.id.clone(),
                    category_id,
                }
            })
            .collect();
        self.transaction::<_, diesel::result::Error, _>(|| {
            diesel::insert_into(schema::entries::table)
                .values(&new_entry)
                .execute(self)?;
            diesel::insert_into(schema::entry_category_relations::table)
                //WHERE NOT EXISTS
                .values(&cat_rels)
                .execute(self)?;
            Ok(())
        })?;
        Ok(())
    }
    fn create_tag(&mut self, t: &Tag) -> Result<()> {
        diesel::insert_into(schema::tags::table)
            .values(&models::Tag::from(t.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_triple(&mut self, t: &Triple) -> Result<()> {
        diesel::insert_into(schema::triples::table)
            .values(&models::Triple::from(t.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_user(&mut self, u: &User) -> Result<()> {
        diesel::insert_into(schema::users::table)
            .values(&models::User::from(u.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_comment(&mut self, c: &Comment) -> Result<()> {
        diesel::insert_into(schema::comments::table)
            .values(&models::Comment::from(c.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_rating(&mut self, r: &Rating) -> Result<()> {
        diesel::insert_into(schema::ratings::table)
            .values(&models::Rating::from(r.clone()))
            .execute(self)?;
        Ok(())
    }
    fn create_bbox_subscription(&mut self, sub: &BboxSubscription) -> Result<()> {
        diesel::insert_into(schema::bbox_subscriptions::table)
            .values(&models::BboxSubscription::from(sub.clone()))
            .execute(self)?;
        Ok(())
    }
    fn all_users(&self) -> Result<Vec<User>> {
        use self::schema::users::dsl;
        Ok(
            dsl::users
                .load::<models::User>(self)?
                .into_iter()
                .map(User::from)
                .collect(),
        )
    }
    fn all_bbox_subscriptions(&self) -> Result<Vec<BboxSubscription>> {
        use self::schema::bbox_subscriptions::dsl;
        Ok(
            dsl::bbox_subscriptions
                .load::<models::BboxSubscription>(self)?
                .into_iter()
                .map(BboxSubscription::from)
                .collect(),
        )
    }
    fn confirm_email_address(&mut self, username: &str) -> Result<User> {
        use self::schema::users::dsl;
        diesel::update(dsl::users.find(username))
            .set(dsl::email_confirmed.eq(true))
            .execute(self)?;
        Ok(User::from(self.get_user(username)?))
    }
    fn delete_bbox_subscription(&mut self, id: &str) -> Result<()> {
        use self::schema::bbox_subscriptions::dsl;
        diesel::delete(dsl::bbox_subscriptions.find(id)).execute(
            self,
        )?;
        Ok(())
    }
    fn delete_user(&mut self, user: &str) -> Result<()> {
        use self::schema::users::dsl::*;
        diesel::delete(users.find(user)).execute(self)?;
        Ok(())
    }

    fn get_entry(&self, e_id: &str) -> Result<Entry> {
        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let models::Entry {
            id,
            created,
            version,
            title,
            description,
            lat,
            lng,
            street,
            zip,
            city,
            country,
            email,
            telephone,
            homepage,
            license,
        } = e_dsl::entries.find(e_id).first(self)?;

        let categories = e_c_dsl::entry_category_relations
            .filter(e_c_dsl::entry_id.eq(&id))
            .load::<models::EntryCategoryRelation>(self)?
            .into_iter()
            .map(|r| r.category_id)
            .collect();

        Ok(Entry {
            id,
            created: created as u64,
            version: version as u64,
            title,
            description,
            lat: lat as f64,
            lng: lng as f64,
            street,
            zip,
            city,
            country,
            email,
            telephone,
            homepage,
            categories,
            license,
        })
    }

    fn get_user(&self, user_id: &str) -> Result<User> {
        use self::schema::users::dsl::*;
        let u: models::User = users.find(user_id).first(self)?;
        Ok(User::from(u))
    }

    fn all_entries(&self) -> Result<Vec<Entry>> {
        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let entries: Vec<models::Entry> = e_dsl::entries.load(self)?;
        let cat_rels = e_c_dsl::entry_category_relations
            .load::<models::EntryCategoryRelation>(self)?;

        Ok(
            entries
                .into_iter()
                .map(|e| {
                    let cats = cat_rels
                        .iter()
                        .filter(|r| r.entry_id == e.id)
                        .map(|r| &r.category_id)
                        .cloned()
                        .collect();
                    Entry {
                        id: e.id,
                        created: e.created as u64,
                        version: e.version as u64,
                        title: e.title,
                        description: e.description,
                        lat: e.lat as f64,
                        lng: e.lng as f64,
                        street: e.street,
                        zip: e.zip,
                        city: e.city,
                        country: e.country,
                        email: e.email,
                        telephone: e.telephone,
                        homepage: e.homepage,
                        categories: cats,
                        license: e.license,
                    }
                })
                .collect(),
        )
    }
    fn all_categories(&self) -> Result<Vec<Category>> {
        use self::schema::categories::dsl::*;
        Ok(
            categories
                .load::<models::Category>(self)?
                .into_iter()
                .map(Category::from)
                .collect(),
        )
    }
    fn all_tags(&self) -> Result<Vec<Tag>> {
        use self::schema::tags::dsl::*;
        Ok(
            tags.load::<models::Tag>(self)?
                .into_iter()
                .map(Tag::from)
                .collect(),
        )

    }
    fn all_triples(&self) -> Result<Vec<Triple>> {
        use self::schema::triples::dsl::*;
        Ok(
            triples
                .load::<models::Triple>(self)?
                .into_iter()
                .map(Triple::from)
                .collect(),
        )
    }
    fn all_ratings(&self) -> Result<Vec<Rating>> {
        use self::schema::ratings::dsl::*;
        Ok(
            ratings
                .load::<models::Rating>(self)?
                .into_iter()
                .map(Rating::from)
                .collect(),
        )
    }
    fn all_comments(&self) -> Result<Vec<Comment>> {
        use self::schema::comments::dsl::*;
        Ok(
            comments
                .load::<models::Comment>(self)?
                .into_iter()
                .map(Comment::from)
                .collect(),
        )
    }

    fn update_entry(&mut self, entry: &Entry) -> Result<()> {

        use self::schema::entries::dsl as e_dsl;
        use self::schema::entry_category_relations::dsl as e_c_dsl;

        let e = models::Entry::from(entry.clone());

        let cat_rels: Vec<_> = entry
            .categories
            .iter()
            .cloned()
            .map(|category_id| {
                models::EntryCategoryRelation {
                    entry_id: entry.id.clone(),
                    category_id,
                }
            })
            .collect();

        self.transaction::<_, diesel::result::Error, _>(|| {

            diesel::update(e_dsl::entries.find(e.id))
                .set((
                    e_dsl::created.eq(e.created),
                    e_dsl::version.eq(e.version),
                    e_dsl::title.eq(e.title),
                    e_dsl::description.eq(e.description),
                    e_dsl::lat.eq(e.lat),
                    e_dsl::lng.eq(e.lng),
                    e_dsl::street.eq(e.street),
                    e_dsl::zip.eq(e.zip),
                    e_dsl::city.eq(e.city),
                    e_dsl::country.eq(e.country),
                    e_dsl::email.eq(e.email),
                    e_dsl::telephone.eq(e.telephone),
                    e_dsl::homepage.eq(e.homepage),
                    e_dsl::license.eq(e.license),
                ))
                .execute(self)?;

            diesel::delete(e_c_dsl::entry_category_relations.filter(
                e_c_dsl::entry_id.eq(
                    &entry.id,
                ),
            )).execute(self)?;

            diesel::insert_into(schema::entry_category_relations::table)
                //WHERE NOT EXISTS
                .values(&cat_rels)
                .execute(self)?;
            Ok(())
        })?;
        Ok(())
    }

    fn delete_triple(&mut self, t: &Triple) -> Result<()> {
        use self::schema::triples::dsl::*;
        let t = models::Triple::from(t.clone());
        diesel::delete(triples.find((t.subject_id, t.predicate, t.object_id)))
            .execute(self)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![crate_name = "sam4l"]
#![crate_type = "rlib"]
#![feature(asm,core_intrinsics,concat_idents,const_fn)]
#![no_std]

extern crate common;
extern crate hil;
extern crate process;

mod helpers;

pub mod chip;
pub mod ast;
pub mod bpm;
pub mod dma;
pub mod i2c;
pub mod spi;
pub mod nvic;
pub mod pm;
pub mod gpio;
pub mod usart;
pub mod scif;
pub mod adc;

unsafe extern "C" fn unhandled_interrupt() {
    let mut interrupt_number: u32;

    // IPSR[8:0] holds the currently active interrupt
    asm!(
        "mrs    r0, ipsr                    "
        : "={r0}"(interrupt_number)
        :
        : "r0"
        :
        );

    interrupt_number = interrupt_number & 0x1ff;

    panic!("Unhandled Interrupt. ISR {} is active.", interrupt_number);
}

extern {
    // _estack is not really a function, but it makes the types work
    // You should never actually invoke it!!
    fn _estack();

    // Defined in src/main/main.rs
    fn main();

    // Defined in src/arch/cortex-m4/ctx_switch.S
    fn SVC_Handler();

    static mut _szero : u32;
    static mut _ezero : u32;
    static mut _etext : u32;
    static mut _srelocate : u32;
    static mut _erelocate : u32;
}

#[link_section=".vectors"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>; 96] = [
    // First 16 are defined in the Cortex M4 user guide section 2.3.4

    /* Stack top */     Option::Some(_estack),
    /* Reset */         Option::Some(reset_handler),
    /* NMI */           Option::Some(unhandled_interrupt),
    /* Hard Fault */    Option::Some(hard_fault_handler),
    /* MemManage */     Option::Some(unhandled_interrupt),
    /* BusFault */      Option::Some(unhandled_interrupt),
    /* UsageFault*/     Option::Some(unhandled_interrupt),
    None, None, None, None,
    /* SVC */           Option::Some(SVC_Handler),
    /* DebugMon */      Option::Some(unhandled_interrupt),
    None,
    /* PendSV */        Option::Some(unhandled_interrupt),
    /* SysTick */       Option::Some(unhandled_interrupt),

    // Perhipheral vectors are defined by Atmel in the SAM4L datasheet section
    // 4.7.
    /* HFLASHC */       Option::Some(unhandled_interrupt),
    /* PDCA0 */         Option::Some(dma::PDCA_0_Handler),
    /* PDCA1 */         Option::Some(dma::PDCA_1_Handler),
    /* PDCA2 */         Option::Some(dma::PDCA_2_Handler),
    /* PDCA3 */         Option::Some(dma::PDCA_3_Handler),
    /* PDCA4 */         Option::Some(dma::PDCA_4_Handler),
    /* PDCA5..PDCA15 */ None, None, None, None, None, None, None, None,
                        None, None, None,
    /* CRCCU */         Option::Some(unhandled_interrupt),
    /* USBC */          Option::Some(unhandled_interrupt),
    /* PEVC_TR */       Option::Some(unhandled_interrupt),
    /* PEVC_OV */       Option::Some(unhandled_interrupt),
    /* AESA */          Option::Some(unhandled_interrupt),
    /* PM */            Option::Some(unhandled_interrupt),
    /* SCIF */          Option::Some(unhandled_interrupt),
    /* FREQM */         Option::Some(unhandled_interrupt),
    /* GPIO0 */         Option::Some(gpio::GPIO_0_Handler),
    /* GPIO1 */         Option::Some(gpio::GPIO_1_Handler),
    /* GPIO2 */         Option::Some(gpio::GPIO_2_Handler),
    /* GPIO3 */         Option::Some(gpio::GPIO_3_Handler),
    /* GPIO4 */         Option::Some(gpio::GPIO_4_Handler),
    /* GPIO5 */         Option::Some(gpio::GPIO_5_Handler),
    /* GPIO6 */         Option::Some(gpio::GPIO_6_Handler),
    /* GPIO7 */         Option::Some(gpio::GPIO_7_Handler),
    /* GPIO8 */         Option::Some(gpio::GPIO_8_Handler),
    /* GPIO9 */         Option::Some(gpio::GPIO_9_Handler),
    /* GPIO10 */        Option::Some(gpio::GPIO_10_Handler),
    /* GPIO11 */        Option::Some(gpio::GPIO_11_Handler),
    /* BPM */           Option::Some(unhandled_interrupt),
    /* BSCIF */         Option::Some(unhandled_interrupt),
    /* AST_ALARM */     Option::Some(ast::AST_ALARM_Handler),
    /* AST_PER */       Option::Some(unhandled_interrupt),
    /* AST_OVF */       Option::Some(unhandled_interrupt),
    /* AST_READY */     Option::Some(unhandled_interrupt),
    /* AST_CLKREADY */  Option::Some(unhandled_interrupt),
    /* WDT */           Option::Some(unhandled_interrupt),
    /* EIC1 */          Option::Some(unhandled_interrupt),
    /* EIC2 */          Option::Some(unhandled_interrupt),
    /* EIC3 */          Option::Some(unhandled_interrupt),
    /* EIC4 */          Option::Some(unhandled_interrupt),
    /* EIC5 */          Option::Some(unhandled_interrupt),
    /* EIC6 */          Option::Some(unhandled_interrupt),
    /* EIC7 */          Option::Some(unhandled_interrupt),
    /* EIC8 */          Option::Some(unhandled_interrupt),
    /* IISC */          Option::Some(unhandled_interrupt),
    /* SPI */           Option::Some(unhandled_interrupt),
    /* TC00 */          Option::Some(unhandled_interrupt),
    /* TC01 */          Option::Some(unhandled_interrupt),
    /* TC02 */          Option::Some(unhandled_interrupt),
    /* TC10 */          Option::Some(unhandled_interrupt),
    /* TC11 */          Option::Some(unhandled_interrupt),
    /* TC12 */          Option::Some(unhandled_interrupt),
    /* TWIM0 */         Option::Some(unhandled_interrupt),
    /* TWIS0 */         Option::Some(unhandled_interrupt),
    /* TWIM1 */         Option::Some(unhandled_interrupt),
    /* TWIS1 */         Option::Some(unhandled_interrupt),
    /* USART0 */        Option::Some(unhandled_interrupt),
    /* USART1 */        Option::Some(unhandled_interrupt),
    /* USART2 */        Option::Some(usart::USART2_Handler),
    /* USART3 */        Option::Some(usart::USART3_Handler),
    /* ADCIFE */        Option::Some(adc::ADCIFE_Handler),
    /* DACC */          Option::Some(unhandled_interrupt),
    /* ACIFC */         Option::Some(unhandled_interrupt),
    /* ABDACB */        Option::Some(unhandled_interrupt),
    /* TRNG */          Option::Some(unhandled_interrupt),
    /* PARC */          Option::Some(unhandled_interrupt),
    /* CATB */          Option::Some(unhandled_interrupt),
    None,
    /* TWIM2 */         Option::Some(i2c::twim2_interrupt),
    /* TWIM3 */         Option::Some(unhandled_interrupt),
    /* LCDCA */         Option::Some(unhandled_interrupt),
];

unsafe extern "C" fn reset_handler() {

    // Relocate data segment.
    // Assumes data starts right after text segment as specified by the linker
    // file.
    let mut pdest  = &mut _srelocate as *mut u32;
    let pend  = &mut _erelocate as *mut u32;
    let mut psrc = &_etext as *const u32;

    if psrc != pdest {
        while (pdest as *const u32) < pend {
            *pdest = *psrc;
            pdest = pdest.offset(1);
            psrc = psrc.offset(1);
        }
    }

    // Clear the zero segment (BSS)
    let pzero = &_ezero as *const u32;
    pdest = &mut _szero as *mut u32;

    while (pdest as *const u32) < pzero {
        *pdest = 0;
        pdest = pdest.offset(1);
    }

    main();
}

unsafe extern "C" fn hard_fault_handler() {
    use core::intrinsics::offset;

    let faulting_stack: *mut u32;

    asm!(
        "tst    lr, #4                      \n\
         ite    eq                          \n\
         mrseq  r0, msp                     \n\
         mrsne  r0, psp                     "
        : "={r0}"(faulting_stack)
        :
        : "r0"
        :
        );

    let stacked_r0  :u32 = *offset(faulting_stack, 0);
    let stacked_r1  :u32 = *offset(faulting_stack, 1);
    let stacked_r2  :u32 = *offset(faulting_stack, 2);
    let stacked_r3  :u32 = *offset(faulting_stack, 3);
    let stacked_r12 :u32 = *offset(faulting_stack, 4);
    let stacked_lr  :u32 = *offset(faulting_stack, 5);
    let stacked_pc  :u32 = *offset(faulting_stack, 6);
    let stacked_prs :u32 = *offset(faulting_stack, 7);

    panic!("HardFault.\n\
           \tr0  0x{:x}\n\
           \tr1  0x{:x}\n\
           \tr2  0x{:x}\n\
           \tr3  0x{:x}\n\
           \tr12 0x{:x}\n\
           \tlr  0x{:x}\n\
           \tpc  0x{:x}\n\
           \tprs 0x{:x}\n\
           ", stacked_r0, stacked_r1, stacked_r2, stacked_r3,
           stacked_r12, stacked_lr, stacked_pc, stacked_prs);
}

<commit_msg>SAM4L: More informative HardFault handler<commit_after>#![crate_name = "sam4l"]
#![crate_type = "rlib"]
#![feature(asm,core_intrinsics,concat_idents,const_fn)]
#![no_std]

extern crate common;
extern crate hil;
extern crate process;

mod helpers;

pub mod chip;
pub mod ast;
pub mod bpm;
pub mod dma;
pub mod i2c;
pub mod spi;
pub mod nvic;
pub mod pm;
pub mod gpio;
pub mod usart;
pub mod scif;
pub mod adc;

unsafe extern "C" fn unhandled_interrupt() {
    let mut interrupt_number: u32;

    // IPSR[8:0] holds the currently active interrupt
    asm!(
        "mrs    r0, ipsr                    "
        : "={r0}"(interrupt_number)
        :
        : "r0"
        :
        );

    interrupt_number = interrupt_number & 0x1ff;

    panic!("Unhandled Interrupt. ISR {} is active.", interrupt_number);
}

extern {
    // _estack is not really a function, but it makes the types work
    // You should never actually invoke it!!
    fn _estack();

    // Defined in src/main/main.rs
    fn main();

    // Defined in src/arch/cortex-m4/ctx_switch.S
    fn SVC_Handler();

    static mut _szero : u32;
    static mut _ezero : u32;
    static mut _etext : u32;
    static mut _srelocate : u32;
    static mut _erelocate : u32;
}

#[link_section=".vectors"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>; 96] = [
    // First 16 are defined in the Cortex M4 user guide section 2.3.4

    /* Stack top */     Option::Some(_estack),
    /* Reset */         Option::Some(reset_handler),
    /* NMI */           Option::Some(unhandled_interrupt),
    /* Hard Fault */    Option::Some(hard_fault_handler),
    /* MemManage */     Option::Some(unhandled_interrupt),
    /* BusFault */      Option::Some(unhandled_interrupt),
    /* UsageFault*/     Option::Some(unhandled_interrupt),
    None, None, None, None,
    /* SVC */           Option::Some(SVC_Handler),
    /* DebugMon */      Option::Some(unhandled_interrupt),
    None,
    /* PendSV */        Option::Some(unhandled_interrupt),
    /* SysTick */       Option::Some(unhandled_interrupt),

    // Perhipheral vectors are defined by Atmel in the SAM4L datasheet section
    // 4.7.
    /* HFLASHC */       Option::Some(unhandled_interrupt),
    /* PDCA0 */         Option::Some(dma::PDCA_0_Handler),
    /* PDCA1 */         Option::Some(dma::PDCA_1_Handler),
    /* PDCA2 */         Option::Some(dma::PDCA_2_Handler),
    /* PDCA3 */         Option::Some(dma::PDCA_3_Handler),
    /* PDCA4 */         Option::Some(dma::PDCA_4_Handler),
    /* PDCA5..PDCA15 */ None, None, None, None, None, None, None, None,
                        None, None, None,
    /* CRCCU */         Option::Some(unhandled_interrupt),
    /* USBC */          Option::Some(unhandled_interrupt),
    /* PEVC_TR */       Option::Some(unhandled_interrupt),
    /* PEVC_OV */       Option::Some(unhandled_interrupt),
    /* AESA */          Option::Some(unhandled_interrupt),
    /* PM */            Option::Some(unhandled_interrupt),
    /* SCIF */          Option::Some(unhandled_interrupt),
    /* FREQM */         Option::Some(unhandled_interrupt),
    /* GPIO0 */         Option::Some(gpio::GPIO_0_Handler),
    /* GPIO1 */         Option::Some(gpio::GPIO_1_Handler),
    /* GPIO2 */         Option::Some(gpio::GPIO_2_Handler),
    /* GPIO3 */         Option::Some(gpio::GPIO_3_Handler),
    /* GPIO4 */         Option::Some(gpio::GPIO_4_Handler),
    /* GPIO5 */         Option::Some(gpio::GPIO_5_Handler),
    /* GPIO6 */         Option::Some(gpio::GPIO_6_Handler),
    /* GPIO7 */         Option::Some(gpio::GPIO_7_Handler),
    /* GPIO8 */         Option::Some(gpio::GPIO_8_Handler),
    /* GPIO9 */         Option::Some(gpio::GPIO_9_Handler),
    /* GPIO10 */        Option::Some(gpio::GPIO_10_Handler),
    /* GPIO11 */        Option::Some(gpio::GPIO_11_Handler),
    /* BPM */           Option::Some(unhandled_interrupt),
    /* BSCIF */         Option::Some(unhandled_interrupt),
    /* AST_ALARM */     Option::Some(ast::AST_ALARM_Handler),
    /* AST_PER */       Option::Some(unhandled_interrupt),
    /* AST_OVF */       Option::Some(unhandled_interrupt),
    /* AST_READY */     Option::Some(unhandled_interrupt),
    /* AST_CLKREADY */  Option::Some(unhandled_interrupt),
    /* WDT */           Option::Some(unhandled_interrupt),
    /* EIC1 */          Option::Some(unhandled_interrupt),
    /* EIC2 */          Option::Some(unhandled_interrupt),
    /* EIC3 */          Option::Some(unhandled_interrupt),
    /* EIC4 */          Option::Some(unhandled_interrupt),
    /* EIC5 */          Option::Some(unhandled_interrupt),
    /* EIC6 */          Option::Some(unhandled_interrupt),
    /* EIC7 */          Option::Some(unhandled_interrupt),
    /* EIC8 */          Option::Some(unhandled_interrupt),
    /* IISC */          Option::Some(unhandled_interrupt),
    /* SPI */           Option::Some(unhandled_interrupt),
    /* TC00 */          Option::Some(unhandled_interrupt),
    /* TC01 */          Option::Some(unhandled_interrupt),
    /* TC02 */          Option::Some(unhandled_interrupt),
    /* TC10 */          Option::Some(unhandled_interrupt),
    /* TC11 */          Option::Some(unhandled_interrupt),
    /* TC12 */          Option::Some(unhandled_interrupt),
    /* TWIM0 */         Option::Some(unhandled_interrupt),
    /* TWIS0 */         Option::Some(unhandled_interrupt),
    /* TWIM1 */         Option::Some(unhandled_interrupt),
    /* TWIS1 */         Option::Some(unhandled_interrupt),
    /* USART0 */        Option::Some(unhandled_interrupt),
    /* USART1 */        Option::Some(unhandled_interrupt),
    /* USART2 */        Option::Some(usart::USART2_Handler),
    /* USART3 */        Option::Some(usart::USART3_Handler),
    /* ADCIFE */        Option::Some(adc::ADCIFE_Handler),
    /* DACC */          Option::Some(unhandled_interrupt),
    /* ACIFC */         Option::Some(unhandled_interrupt),
    /* ABDACB */        Option::Some(unhandled_interrupt),
    /* TRNG */          Option::Some(unhandled_interrupt),
    /* PARC */          Option::Some(unhandled_interrupt),
    /* CATB */          Option::Some(unhandled_interrupt),
    None,
    /* TWIM2 */         Option::Some(i2c::twim2_interrupt),
    /* TWIM3 */         Option::Some(unhandled_interrupt),
    /* LCDCA */         Option::Some(unhandled_interrupt),
];

unsafe extern "C" fn reset_handler() {

    // Relocate data segment.
    // Assumes data starts right after text segment as specified by the linker
    // file.
    let mut pdest  = &mut _srelocate as *mut u32;
    let pend  = &mut _erelocate as *mut u32;
    let mut psrc = &_etext as *const u32;

    if psrc != pdest {
        while (pdest as *const u32) < pend {
            *pdest = *psrc;
            pdest = pdest.offset(1);
            psrc = psrc.offset(1);
        }
    }

    // Clear the zero segment (BSS)
    let pzero = &_ezero as *const u32;
    pdest = &mut _szero as *mut u32;

    while (pdest as *const u32) < pzero {
        *pdest = 0;
        pdest = pdest.offset(1);
    }

    main();
}

unsafe extern "C" fn hard_fault_handler() {
    use core::intrinsics::offset;

    let faulting_stack: *mut u32;
    let kernel_stack: bool;

    asm!(
        "mov    r1, 0                       \n\
         tst    lr, #4                      \n\
         itte   eq                          \n\
         mrseq  r0, msp                     \n\
         addeq  r1, 1                       \n\
         mrsne  r0, psp                     "
        : "={r0}"(faulting_stack), "={r1}"(kernel_stack)
        :
        : "r0", "r1"
        :
        );

    let stacked_r0  :u32 = *offset(faulting_stack, 0);
    let stacked_r1  :u32 = *offset(faulting_stack, 1);
    let stacked_r2  :u32 = *offset(faulting_stack, 2);
    let stacked_r3  :u32 = *offset(faulting_stack, 3);
    let stacked_r12 :u32 = *offset(faulting_stack, 4);
    let stacked_lr  :u32 = *offset(faulting_stack, 5);
    let stacked_pc  :u32 = *offset(faulting_stack, 6);
    let stacked_prs :u32 = *offset(faulting_stack, 7);

    let mode_str = if kernel_stack { "Kernel" } else { "Process" };

    let shcsr : u32 = core::intrinsics::volatile_load(0xE000ED24 as *const u32);
    let cfsr : u32 = core::intrinsics::volatile_load(0xE000ED28 as *const u32);
    let hfsr : u32 = core::intrinsics::volatile_load(0xE000ED2C as *const u32);

    panic!("{} HardFault.\n\
           \tr0  0x{:x}\n\
           \tr1  0x{:x}\n\
           \tr2  0x{:x}\n\
           \tr3  0x{:x}\n\
           \tr12 0x{:x}\n\
           \tlr  0x{:x}\n\
           \tpc  0x{:x}\n\
           \tprs 0x{:x}\n\
           \tsp  0x{:x}\n\
           \tSHCSR 0x{:x}\n\
           \tCFSR  0x{:x}\n\
           \tHSFR  0x{:x}\n\
           ", mode_str,
           stacked_r0, stacked_r1, stacked_r2, stacked_r3,
           stacked_r12, stacked_lr, stacked_pc, stacked_prs,
           faulting_stack as u32, shcsr, cfsr, hfsr);
}

<|endoftext|>