<commit_before>use super::*;

use std::{collections::BTreeSet, ops::Bound};

#[derive(Debug, Clone)]
pub(crate) struct View<'a> {
    pub(crate) pid: PageId,
    pub(crate) lo: &'a IVec,
    pub(crate) hi: &'a IVec,
    pub(crate) is_index: bool,
    pub(crate) next: Option<PageId>,
    pub(crate) ptr: TreePtr<'a>,
    frags: Vec<&'a Frag>,
    base_offset: usize,
    pub(crate) base_data: &'a Data,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl<'a> View<'a> {
    pub(crate) fn new(
        pid: PageId,
        ptr: TreePtr<'a>,
        frags: Vec<&'a Frag>,
    ) -> View<'a> {
        let mut view = View {
            pid,
            ptr,
            frags,
            lo: unsafe { std::mem::uninitialized() },
            hi: unsafe { std::mem::uninitialized() },
            is_index: false,
            base_offset: usize::max_value(),
            base_data: unsafe { std::mem::uninitialized() },
            next: None,
            merging_child: None,
            merging: false,
        };

        let mut merge_confirmed = false;

        for (offset, frag) in view.frags.iter().enumerate() {
            match frag {
                Frag::Base(node) => {
                    if view.base_offset == usize::max_value() {
                        // hi and next may be changed via a
                        // parent split if we re-add that frag
                        view.hi = &node.hi;
                        view.next = node.next;
                    }
                    view.lo = &node.lo;
                    view.is_index = node.data.index_ref().is_some();
                    view.base_offset = offset;
                    view.base_data = &node.data;
                    break;
                }
                Frag::ParentMergeIntention(pid) => {
                    if merge_confirmed {
                        merge_confirmed = false;
                    } else {
                        assert!(view.merging_child.is_none());
                        view.merging_child = Some(*pid);
                    }
                }
                Frag::ParentMergeConfirm => {
                    assert!(!merge_confirmed);
                    merge_confirmed = true;
                }
                Frag::ChildMergeCap => {
                    assert!(!view.merging);
                    assert_eq!(offset, 0);
                    view.merging = true;
                }
                _ => {}
            }
        }

        assert_ne!(
            view.base_offset,
            usize::max_value(),
            "view was never initialized with a base"
        );

        view
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.hi.is_empty(),
            Bound::Included(bound) => self.hi > bound || self.hi.is_empty(),
            Bound::Excluded(bound) => self.hi >= bound || self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.lo.is_empty(),
            Bound::Included(bound) => self.lo <= bound,
            Bound::Excluded(bound) => self.lo < bound,
        }
    }

    fn keys(&self) -> BTreeSet<&IVec> {
        let mut keys: BTreeSet<&IVec> = self
            .base_data
            .leaf_ref()
            .unwrap()
            .iter()
            .map(|(k, _v)| k)
            .collect();

        for offset in (0..self.base_offset).rev() {
            match self.frags[offset] {
                Frag::Set(k, _) => {
                    keys.insert(k);
                }
                Frag::Del(k) => {
                    keys.remove(k);
                }
                Frag::Merge(k, _) => {
                    keys.insert(k);
                }
                Frag::Base(_) => {
                    panic!(
                        "somehow hit 2 base nodes while \
                         searching for a successor"
                    );
                }
                Frag::ChildMergeCap => {}
                Frag::ParentMergeIntention(_) | Frag::ParentMergeConfirm => {
                    panic!(
                        "somehow hit parent merge \
                         frags while searching for a \
                         successor"
                    )
                }
            }
        }

        keys
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(self.lo, self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
        };

        let keys = self.keys();

        let successor_keys = keys.range(predecessor_key..);

        for encoded_key in successor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    prefix_encode(self.lo, &[255; 1024 * 1024])
                } else {
                    prefix_encode(self.lo, self.hi)
                }
            }
            Bound::Included(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
        };

        let keys = self.keys();

        let predecessor_keys = keys.range(..=successor_key).rev();

        for encoded_key in predecessor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn is_free(&self) -> bool {
        self.frags.is_empty()
    }

    pub(crate) fn leaf_value_for_key(
        &self,
        key: &[u8],
        config: &Config,
    ) -> Option<IVec> {
        assert!(!self.is_index);

        let mut merge_base = None;
        let mut merges = vec![];

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(k, val) if self.key_eq(k, key) => {
                    if merges.is_empty() {
                        return Some(val.clone());
                    } else {
                        merge_base = Some(val);
                        break;
                    }
                }
                Frag::Del(k) if self.key_eq(k, key) => return None,
                Frag::Merge(k, val) if self.key_eq(k, key) => merges.push(val),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.leaf_ref().expect("last_node should be a leaf");
                    let search = items
                        .binary_search_by(|&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        })
                        .ok();

                    let val = search.map(|idx| &items[idx].1);
                    if merges.is_empty() {
                        return val.cloned();
                    } else {
                        merge_base = val;
                    }
                }
                _ => {}
            }
        }

        if merges.is_empty() {
            None
        } else {
            let merge_fn_ptr = config
                .merge_operator
                .expect("must have a merge operator set");

            unsafe {
                let merge_fn: MergeOperator = std::mem::transmute(merge_fn_ptr);

                let mut ret = merge_fn(
                    key,
                    merge_base.map(|iv| &**iv),
                    &merges.pop().unwrap(),
                );
                                       ;
                for merge in merges.into_iter().rev() {
                    if let Some(v) = ret {
                        ret = merge_fn(key, Some(&*v), merge);
                    } else {
                        ret = merge_fn(key, None, merge);
                    }
                }

                ret.map(IVec::from)
            }
        }
    }

    #[inline]
    fn key_eq(&self, encoded: &[u8], not_encoded: &[u8]) -> bool {
        prefix_cmp_encoded(encoded, not_encoded, self.lo)
            == std::cmp::Ordering::Equal
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> PageId {
        assert!(self.is_index);

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(..) => unimplemented!(),
                Frag::Del(..) => unimplemented!(),
                Frag::Merge(..) => unimplemented!(),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.index_ref().expect("last_node should be a leaf");
                    let search =
                        binary_search_lub(items, |&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        });

                    // This might be none if ord is Less and we're
                    // searching for the empty key
                    let index = search.expect("failed to traverse index");

                    return items[index].1;
                }
                Frag::ParentMergeIntention(_)
                | Frag::ParentMergeConfirm
                | Frag::ChildMergeCap => {
                    // nothing to do for these frags
                }
            }
        }
        panic!("no index found")
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        let children = self.base_data.len();
        children > 2
            && self.size_in_bytes() > max_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn compact(&self, config: &Config) -> Node {
        let mut lhs = self.frags[self.base_offset].unwrap_base().clone();
        for offset in (0..self.base_offset).rev() {
            let frag = self.frags[offset];
            lhs.apply(frag, config.merge_operator);
        }
        lhs
    }

    pub(crate) fn split(&self, config: &Config) -> (Node, Node) {
        let mut lhs = self.compact(config);
        let rhs = lhs.split();

        lhs.data.drop_gte(&rhs.lo, &lhs.lo);
        lhs.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        lhs.next = None;

        (lhs, rhs)
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        // TODO needs to better account for
        // sizes that don't actually fall under
        // a merge threshold once we support one.
        self.frags[..self.base_offset + 1]
            .iter()
            .map(|f| f.size_in_bytes())
            .sum()
    }
}
<commit_msg>Fix view bounding issue<commit_after>use super::*;

use std::{collections::BTreeSet, ops::Bound};

#[derive(Debug, Clone)]
pub(crate) struct View<'a> {
    pub(crate) pid: PageId,
    pub(crate) lo: &'a IVec,
    pub(crate) hi: &'a IVec,
    pub(crate) is_index: bool,
    pub(crate) next: Option<PageId>,
    pub(crate) ptr: TreePtr<'a>,
    frags: Vec<&'a Frag>,
    base_offset: usize,
    pub(crate) base_data: &'a Data,
    pub(crate) merging_child: Option<PageId>,
    pub(crate) merging: bool,
}

impl<'a> View<'a> {
    pub(crate) fn new(
        pid: PageId,
        ptr: TreePtr<'a>,
        frags: Vec<&'a Frag>,
    ) -> View<'a> {
        let mut view = View {
            pid,
            ptr,
            frags,
            lo: unsafe { std::mem::uninitialized() },
            hi: unsafe { std::mem::uninitialized() },
            is_index: false,
            base_offset: usize::max_value(),
            base_data: unsafe { std::mem::uninitialized() },
            next: None,
            merging_child: None,
            merging: false,
        };

        let mut merge_confirmed = false;

        for (offset, frag) in view.frags.iter().enumerate() {
            match frag {
                Frag::Base(node) => {
                    if view.base_offset == usize::max_value() {
                        // hi and next may be changed via a
                        // parent split if we re-add that frag
                        view.hi = &node.hi;
                        view.next = node.next;
                    }
                    view.lo = &node.lo;
                    view.is_index = node.data.index_ref().is_some();
                    view.base_offset = offset;
                    view.base_data = &node.data;
                    break;
                }
                Frag::ParentMergeIntention(pid) => {
                    if merge_confirmed {
                        merge_confirmed = false;
                    } else {
                        assert!(view.merging_child.is_none());
                        view.merging_child = Some(*pid);
                    }
                }
                Frag::ParentMergeConfirm => {
                    assert!(!merge_confirmed);
                    merge_confirmed = true;
                }
                Frag::ChildMergeCap => {
                    assert!(!view.merging);
                    assert_eq!(offset, 0);
                    view.merging = true;
                }
                _ => {}
            }
        }

        assert_ne!(
            view.base_offset,
            usize::max_value(),
            "view was never initialized with a base"
        );

        view
    }

    pub(crate) fn contains_upper_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.hi.is_empty(),
            Bound::Included(bound) => self.hi > bound || self.hi.is_empty(),
            Bound::Excluded(bound) => self.hi >= bound || self.hi.is_empty(),
        }
    }

    pub(crate) fn contains_lower_bound(&self, bound: &Bound<IVec>) -> bool {
        match bound {
            Bound::Unbounded => self.lo.is_empty(),
            Bound::Included(bound) | Bound::Excluded(bound) => self.lo <= bound,
        }
    }

    fn keys(&self) -> BTreeSet<&IVec> {
        let mut keys: BTreeSet<&IVec> = self
            .base_data
            .leaf_ref()
            .unwrap()
            .iter()
            .map(|(k, _v)| k)
            .collect();

        for offset in (0..self.base_offset).rev() {
            match self.frags[offset] {
                Frag::Set(k, _) => {
                    keys.insert(k);
                }
                Frag::Del(k) => {
                    keys.remove(k);
                }
                Frag::Merge(k, _) => {
                    keys.insert(k);
                }
                Frag::Base(_) => {
                    panic!(
                        "somehow hit 2 base nodes while \
                         searching for a successor"
                    );
                }
                Frag::ChildMergeCap => {}
                Frag::ParentMergeIntention(_) | Frag::ParentMergeConfirm => {
                    panic!(
                        "somehow hit parent merge \
                         frags while searching for a \
                         successor"
                    )
                }
            }
        }

        keys
    }

    pub(crate) fn successor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // keys cannot be lower than the node's lo key.
        let predecessor_key = match bound {
            Bound::Unbounded => prefix_encode(self.lo, self.lo),
            Bound::Included(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
            Bound::Excluded(b) => {
                let max = std::cmp::max(b, self.lo);
                prefix_encode(self.lo, max)
            }
        };

        let keys = self.keys();

        let successor_keys = keys.range(predecessor_key..);

        for encoded_key in successor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn predecessor(
        &self,
        bound: &Bound<IVec>,
        config: &Config,
    ) -> Option<(IVec, IVec)> {
        assert!(!self.is_index);

        // This encoding happens this way because
        // the rightmost (unbounded) node has
        // a hi key represented by the empty slice
        let successor_key = match bound {
            Bound::Unbounded => {
                if self.hi.is_empty() {
                    prefix_encode(self.lo, &[255; 1024 * 1024])
                } else {
                    prefix_encode(self.lo, self.hi)
                }
            }
            Bound::Included(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
            Bound::Excluded(b) => {
                let min = std::cmp::min(b, self.hi);
                prefix_encode(self.lo, min)
            }
        };

        let keys = self.keys();

        let predecessor_keys = keys.range(..=successor_key).rev();

        for encoded_key in predecessor_keys {
            let decoded_key = prefix_decode(self.lo, &encoded_key);

            if let Bound::Excluded(e) = bound {
                if &*e == &decoded_key {
                    // skip this excluded key
                    continue;
                }
            }

            // try to get this key until it works
            if let Some(value) = self.leaf_value_for_key(&decoded_key, config) {
                return Some((IVec::from(decoded_key), value));
            }
        }

        None
    }

    pub(crate) fn is_free(&self) -> bool {
        self.frags.is_empty()
    }

    pub(crate) fn leaf_value_for_key(
        &self,
        key: &[u8],
        config: &Config,
    ) -> Option<IVec> {
        assert!(!self.is_index);

        let mut merge_base = None;
        let mut merges = vec![];

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(k, val) if self.key_eq(k, key) => {
                    if merges.is_empty() {
                        return Some(val.clone());
                    } else {
                        merge_base = Some(val);
                        break;
                    }
                }
                Frag::Del(k) if self.key_eq(k, key) => return None,
                Frag::Merge(k, val) if self.key_eq(k, key) => merges.push(val),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.leaf_ref().expect("last_node should be a leaf");
                    let search = items
                        .binary_search_by(|&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        })
                        .ok();

                    let val = search.map(|idx| &items[idx].1);
                    if merges.is_empty() {
                        return val.cloned();
                    } else {
                        merge_base = val;
                    }
                }
                _ => {}
            }
        }

        if merges.is_empty() {
            None
        } else {
            let merge_fn_ptr = config
                .merge_operator
                .expect("must have a merge operator set");

            unsafe {
                let merge_fn: MergeOperator = std::mem::transmute(merge_fn_ptr);

                let mut ret = merge_fn(
                    key,
                    merge_base.map(|iv| &**iv),
                    &merges.pop().unwrap(),
                );
                                       ;
                for merge in merges.into_iter().rev() {
                    if let Some(v) = ret {
                        ret = merge_fn(key, Some(&*v), merge);
                    } else {
                        ret = merge_fn(key, None, merge);
                    }
                }

                ret.map(IVec::from)
            }
        }
    }

    #[inline]
    fn key_eq(&self, encoded: &[u8], not_encoded: &[u8]) -> bool {
        prefix_cmp_encoded(encoded, not_encoded, self.lo)
            == std::cmp::Ordering::Equal
    }

    pub(crate) fn index_next_node(&self, key: &[u8]) -> PageId {
        assert!(self.is_index);

        for frag in self.frags[..self.base_offset + 1].iter() {
            match frag {
                Frag::Set(..) => unimplemented!(),
                Frag::Del(..) => unimplemented!(),
                Frag::Merge(..) => unimplemented!(),
                Frag::Base(node) => {
                    let data = &node.data;
                    let items =
                        data.index_ref().expect("last_node should be a leaf");
                    let search =
                        binary_search_lub(items, |&(ref k, ref _v)| {
                            prefix_cmp_encoded(k, key.as_ref(), &node.lo)
                        });

                    // This might be none if ord is Less and we're
                    // searching for the empty key
                    let index = search.expect("failed to traverse index");

                    return items[index].1;
                }
                Frag::ParentMergeIntention(_)
                | Frag::ParentMergeConfirm
                | Frag::ChildMergeCap => {
                    // nothing to do for these frags
                }
            }
        }
        panic!("no index found")
    }

    pub(crate) fn should_split(&self, max_sz: u64) -> bool {
        let children = self.base_data.len();
        children > 2
            && self.size_in_bytes() > max_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn should_merge(&self, min_sz: u64) -> bool {
        self.size_in_bytes() < min_sz
            && self.merging_child.is_none()
            && !self.merging
    }

    pub(crate) fn can_merge_child(&self) -> bool {
        self.merging_child.is_none() && !self.merging
    }

    pub(crate) fn compact(&self, config: &Config) -> Node {
        let mut lhs = self.frags[self.base_offset].unwrap_base().clone();
        for offset in (0..self.base_offset).rev() {
            let frag = self.frags[offset];
            lhs.apply(frag, config.merge_operator);
        }
        lhs
    }

    pub(crate) fn split(&self, config: &Config) -> (Node, Node) {
        let mut lhs = self.compact(config);
        let rhs = lhs.split();

        lhs.data.drop_gte(&rhs.lo, &lhs.lo);
        lhs.hi = rhs.lo.clone();

        // intentionally make this the end to make
        // any issues pop out with setting it
        // correctly after the split.
        lhs.next = None;

        (lhs, rhs)
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        // TODO needs to better account for
        // sizes that don't actually fall under
        // a merge threshold once we support one.
        self.frags[..self.base_offset + 1]
            .iter()
            .map(|f| f.size_in_bytes())
            .sum()
    }
}
<|endoftext|>


<commit_before>use crate::*;
use rocket::fairing::AdHoc;
use rocket::http::hyper::header::AccessControlAllowOrigin;
use rocket::request::{self, FromRequest, Request};
use rocket::{
    http::{ContentType, Status},
    response::{self, content},
    Outcome, State,
};
use std::ffi::OsStr;
use std::io::Cursor;
use std::path::PathBuf;
use turingarena_contest_webcontent::WebContent;

struct Authorization(Option<String>);

impl<'a, 'r> FromRequest<'a, 'r> for Authorization {
    type Error = String;

    fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
        request::Outcome::Success(Authorization(
            match request.headers().get_one("Authorization") {
                Some(token) => Some(token.to_owned()),
                None => None,
            },
        ))
    }
}

#[rocket::get("/graphiql")]
fn graphiql() -> content::Html<String> {
    juniper_rocket::graphiql_source("/graphql")
}

#[rocket::post("/graphql", data = "<request>")]
fn post_graphql_handler(
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
    auth: Authorization,
) -> juniper_rocket::GraphQLResponse {
    let skip_auth = std::env::var("SKIP_AUTH").unwrap_or(String::new()) == "1";
    let secret_str = std::env::var("SECRET").unwrap_or(String::new());
    if secret_str == "" && !skip_auth {
        return juniper_rocket::GraphQLResponse::error(juniper::FieldError::from(
            "Cannot authenticate users: set environment variable SECRET or SKIP_AUTH=1",
        ));
    }
    let secret = secret_str.as_bytes().to_owned();
    let jwt_data = auth.0.map(|token| match auth::validate(&token, &secret) {
        Ok(claims) => claims,
        Err(_) => panic!("Invalid token"),
    });
    let context = Context {
        skip_auth,
        jwt_data,
        secret,
    };
    request.execute(&schema, &context)
}

#[rocket::get("/")]
fn index<'r>() -> rocket::response::Result<'r> {
    dist(Some(PathBuf::from("index.html")))
}

#[rocket::get("/<file_option..>")]
fn dist<'r>(file_option: Option<PathBuf>) -> rocket::response::Result<'r> {
    let file = file_option.unwrap_or(PathBuf::new());
    let filename = file.display().to_string();
    let content = WebContent::get(&filename)
        .or(WebContent::get("index.html"))
        .unwrap();
    let ext = file
        .as_path()
        .extension()
        .and_then(OsStr::to_str)
        .unwrap_or("html");
    let content_type = ContentType::from_extension(ext)
        .ok_or(Status::new(400, "Could not get file content type"))?;
    response::Response::build()
        .header(content_type)
        .sized_body(Cursor::new(content))
        .ok()
}

pub fn run_server(host: String, port: u16) {
    let config = rocket::Config::build(rocket::config::Environment::active().unwrap())
        .port(port)
        .address(host)
        .finalize()
        .unwrap();

    rocket::custom(config)
        .manage(Schema::new(
            contest::Contest::from_env(),
            contest::Contest::from_env(),
        ))
        .attach(AdHoc::on_response("Cors header", |_, res| {
            res.set_header(AccessControlAllowOrigin::Any);
        }))
        .mount(
            "/",
            rocket::routes![graphiql, post_graphql_handler, index, dist],
        )
        .launch();
}
<commit_msg>Add OPTIONS for Cors<commit_after>use crate::*;
use rocket::fairing::AdHoc;
use rocket::http::hyper::header::AccessControlAllowOrigin;
use rocket::request::{self, FromRequest, Request};
use rocket::response::Response;
use rocket::{
    http::{ContentType, Status},
    response::{self, content},
    Outcome, State,
};
use std::ffi::OsStr;
use std::io::Cursor;
use std::path::PathBuf;
use turingarena_contest_webcontent::WebContent;

struct Authorization(Option<String>);

impl<'a, 'r> FromRequest<'a, 'r> for Authorization {
    type Error = String;

    fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
        request::Outcome::Success(Authorization(
            match request.headers().get_one("Authorization") {
                Some(token) => Some(token.to_owned()),
                None => None,
            },
        ))
    }
}

#[rocket::get("/graphiql")]
fn graphiql() -> content::Html<String> {
    juniper_rocket::graphiql_source("/graphql")
}

#[rocket::options("/graphql")]
fn options_graphql<'a>() -> Response<'a> {
    Response::build()
        .raw_header("Access-Control-Allow-Origin", "*")
        .raw_header("Access-Control-Allow-Methods", "OPTIONS, POST")
        .raw_header("Access-Control-Allow-Headers", "Content-Type")
        .finalize()
}

#[rocket::post("/graphql", data = "<request>")]
fn post_graphql_handler(
    request: juniper_rocket::GraphQLRequest,
    schema: State<Schema>,
    auth: Authorization,
) -> juniper_rocket::GraphQLResponse {
    let skip_auth = std::env::var("SKIP_AUTH").unwrap_or(String::new()) == "1";
    let secret_str = std::env::var("SECRET").unwrap_or(String::new());
    if secret_str == "" && !skip_auth {
        return juniper_rocket::GraphQLResponse::error(juniper::FieldError::from(
            "Cannot authenticate users: set environment variable SECRET or SKIP_AUTH=1",
        ));
    }
    let secret = secret_str.as_bytes().to_owned();
    let jwt_data = auth.0.map(|token| match auth::validate(&token, &secret) {
        Ok(claims) => claims,
        Err(_) => panic!("Invalid token"),
    });
    let context = Context {
        skip_auth,
        jwt_data,
        secret,
    };
    request.execute(&schema, &context)
}

#[rocket::get("/")]
fn index<'r>() -> rocket::response::Result<'r> {
    dist(Some(PathBuf::from("index.html")))
}

#[rocket::get("/<file_option..>")]
fn dist<'r>(file_option: Option<PathBuf>) -> rocket::response::Result<'r> {
    let file = file_option.unwrap_or(PathBuf::new());
    let filename = file.display().to_string();
    let content = WebContent::get(&filename)
        .or(WebContent::get("index.html"))
        .unwrap();
    let ext = file
        .as_path()
        .extension()
        .and_then(OsStr::to_str)
        .unwrap_or("html");
    let content_type = ContentType::from_extension(ext)
        .ok_or(Status::new(400, "Could not get file content type"))?;
    response::Response::build()
        .header(content_type)
        .sized_body(Cursor::new(content))
        .ok()
}

pub fn run_server(host: String, port: u16) {
    let config = rocket::Config::build(rocket::config::Environment::active().unwrap())
        .port(port)
        .address(host)
        .finalize()
        .unwrap();

    rocket::custom(config)
        .manage(Schema::new(
            contest::Contest::from_env(),
            contest::Contest::from_env(),
        ))
        .attach(AdHoc::on_response("Cors header", |_, res| {
            res.set_header(AccessControlAllowOrigin::Any);
        }))
        .mount(
            "/",
            rocket::routes![graphiql, post_graphql_handler, index, dist],
        )
        .launch();
}
<|endoftext|>


<commit_before>use rm::linalg::matrix::Matrix;
use test::Bencher;

#[bench]
fn empty(b: &mut Bencher) {
    b.iter(|| 1)
}

#[bench]
fn mat_add(b: &mut Bencher) {

    let a = Matrix::new(10, 10, vec![2.0;100]);
    let c = Matrix::new(10, 10, vec![3.0;100]);

    b.iter(|| &a + &c)
}

#[bench]
fn mat_mul(b: &mut Bencher) {

    let a = Matrix::new(10, 10, vec![2.0;100]);
    let c = Matrix::new(10, 10, vec![3.0;100]);

    b.iter(|| &a * &c)
}

#[bench]
fn mat_det(b: &mut Bencher) {

    let a = Matrix::new(10, 10, vec![2.0;100]);

    b.iter(|| a.det());
}
<commit_msg>Updating benchmarks to test memory allocation difference<commit_after>use rm::linalg::matrix::Matrix;
use test::Bencher;

#[bench]
fn empty(b: &mut Bencher) {
    b.iter(|| 1)
}

#[bench]
fn mat_ref_add_100_100(b: &mut Bencher) {

    let a = Matrix::new(100, 100, vec![2.0;10000]);
    let c = Matrix::new(100, 100, vec![3.0;10000]);

    b.iter(|| {
    	&a + &c
    })
}

#[bench]
fn mat_create_add_100_100(b: &mut Bencher) {
    let c = Matrix::new(100, 100, vec![3.0;10000]);

    b.iter(|| {
    	let a = Matrix::new(100, 100, vec![2.0;10000]);
    	a + &c
    })
}

#[bench]
fn mat_create_100_100(b: &mut Bencher) {
    b.iter(|| {
    	let a = Matrix::new(100, 100, vec![2.0;10000]);
    	a
    })
}

#[bench]
fn mat_mul_10_10(b: &mut Bencher) {

    let a = Matrix::new(10, 10, vec![2.0;100]);
    let c = Matrix::new(10, 10, vec![3.0;100]);

    b.iter(|| &a * &c)
}<|endoftext|>


<commit_before>use std::{io,os};
use extra::getopts::groups::{getopts, optflag, optopt, usage, OptGroup};
use toml;

static CONFIG_EXAMPLE: &'static str = include_str!("config.example.toml");

pub struct Config {
    plugin_dir: ~str,
    reconnect_time: Option<uint>,
    reconnect_backoff: bool,
    servers: ~[Server]
}

pub struct Server {
    name: ~str,
    host: ~str,
    port: uint,
    use_ssl: bool,
    nick: ~str,
    user: ~str,
    real: ~str
}

pub fn print_usage(opts: &[OptGroup]) {
    writeln!(&mut io::stderr(), "{}", usage(format!("Usage: {} [OPTIONS]", os::args()[0]), opts));
}

pub fn parse_args() -> Result<Config,()> {
    let args = os::args();

    let opts = [
        optflag("h", "help", "Displays this help"),
        optopt("c", "config", "Path for the config file, defaults to ~/.rustirc", "file")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut io::stderr(), "error: {}\n", f.to_err_msg());
            print_usage(opts);
            return Err(());
        }
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return Err(());
    }

    let path = match matches.opt_str("c") {
        None => {
            let p = os::homedir().expect("can't find user's home dir").join(".rustirc");
            if !p.exists() {
                println!("No config file ~/.rustirc exists, writing default file");
                let mut f = io::File::create(&p).unwrap(); // None should have raised
                f.write(CONFIG_EXAMPLE.as_bytes());
                return Err(());
            }
            p
        }
        Some(p) => {
            let p = Path::new(p);
            if !p.exists() {
                writeln!(&mut io::stderr(), "error: config file {} does not exist", p.display());
                return Err(());
            }
            p
        }
    };

    let root = toml::parse_from_path(&path);

    let plugin_dir = match root.lookup("plugin.dir").and_then(|v| v.get_str()) {
        None => {
            writeln!(&mut io::stderr(), "error: required string config value plugin.dir missing");
            return Err(());
        }
        Some(s) => s.clone()
    };
    let reconnect = match root.lookup("general.reconnect").and_then(|v| v.get_int()) {
        None => Some(5),
        Some(x) if x < 0 => None,
        Some(x) => Some(x.to_uint().unwrap())
    };
    let backoff = root.lookup("general.reconnect_backoff").and_then(|v| v.get_bool())
                      .unwrap_or(true);
    let default_nick = root.lookup("general.defaults.nick").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"rustbot");
    let default_user = root.lookup("general.defaults.user").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"rustbot");
    let default_real = root.lookup("general.defaults.real").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"Rust IRC Bot");

    let mut servers = ~[];
    let server_list = match root.lookup_key("servers").and_then(|v| v.get_table_array()) {
        None => {
            writeln!(&mut io::stderr(), "error: at least one server must be defined");
            return Err(());
        }
        Some(ary) => ary.as_slice()
    };
    for elem in server_list.iter() {
        let name = match elem.lookup_key("name").and_then(|v| v.get_str()) {
            None => {
                writeln!(&mut io::stderr(), "error: server entry missing required 'name' key");
                return Err(());
            }
            Some(s) => s.clone()
        };
        let server = match elem.lookup_key("server").and_then(|v| v.get_str()) {
            None => {
                writeln!(&mut io::stderr(), "error: server entry missing required 'server' key");
                return Err(());
            }
            Some(s) => s.clone()
        };
        let use_ssl = elem.lookup_key("use_ssl").and_then(|v| v.get_bool()).unwrap_or(false);
        if use_ssl {
            writeln!(&mut io::stderr(), "error: use_ssl is not currently implemented");
            return Err(());
        }
        let default_port = if use_ssl { 6697 } else { 6667 };
        let port = match elem.lookup_key("port").and_then(|v| v.get_int()).unwrap_or(default_port)
                             .to_uint() {
            None => {
                writeln!(&mut io::stderr(), "error: port is out of range");
                return Err(());
            }
            Some(p) => p
        };
        let nick = elem.lookup_key("nick").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_nick.clone());
        let user = elem.lookup_key("user").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_user.clone());
        let real = elem.lookup_key("real").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_real.clone());
        servers.push(Server{ name: name, host: server, port: port, use_ssl: use_ssl,
                             nick: nick, user: user, real: real });
    }

    Ok(Config{
        plugin_dir: plugin_dir,
        reconnect_time: reconnect,
        reconnect_backoff: backoff,
        servers: servers
    })
}
<commit_msg>Update config parser for proper error reporting<commit_after>use std::{io,os};
use std::io::{IoError,FileNotFound};
use extra::getopts::groups::{getopts, optflag, optopt, usage, OptGroup};
use toml;

static CONFIG_EXAMPLE: &'static str = include_str!("config.example.toml");

pub struct Config {
    plugin_dir: ~str,
    reconnect_time: Option<uint>,
    reconnect_backoff: bool,
    servers: ~[Server]
}

pub struct Server {
    name: ~str,
    host: ~str,
    port: uint,
    use_ssl: bool,
    nick: ~str,
    user: ~str,
    real: ~str
}

pub fn print_usage(opts: &[OptGroup]) {
    let s = usage(format!("Usage: {} [OPTIONS]", os::args()[0]), opts);
    let _ = writeln!(&mut io::stderr(), "{}", s);
}

pub enum Error {
    ErrBadFlag,
    ErrHelpFlag,
    ErrWroteConfig,
    ErrBadConfig,
    ErrIO(IoError)
}

pub fn parse_args() -> Result<Config,Error> {
    let args = os::args();

    let opts = [
        optflag("h", "help", "Displays this help"),
        optopt("c", "config", "Path for the config file, defaults to ~/.rustirc", "file")
    ];

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            let _ = writeln!(&mut io::stderr(), "error: {}\n", f.to_err_msg());
            print_usage(opts);
            return Err(ErrBadFlag);
        }
    };

    if matches.opt_present("h") {
        print_usage(opts);
        return Err(ErrHelpFlag);
    }

    let path = match matches.opt_str("c") {
        None => {
            let p = os::homedir().expect("can't find user's home dir").join(".rustirc");
            if !p.exists() {
                let _ = println!("No config file ~/.rustirc exists, writing default file");
                let mut f = io::File::create(&p).unwrap(); // None should have raised
                match f.write(CONFIG_EXAMPLE.as_bytes()) {
                    Err(e) => return Err(ErrIO(e)),
                    Ok(_) => ()
                }
                return Err(ErrWroteConfig);
            }
            p
        }
        Some(p) => {
            let p = Path::new(p);
            if !p.exists() {
                let _ = writeln!(&mut io::stderr(), "error: config file {} does not exist",
                                 p.display());
                let e = IoError { kind: FileNotFound, desc: "file not found", detail: None };
                return Err(ErrIO(e));
            }
            p
        }
    };

    let root = toml::parse_from_path(&path);

    let plugin_dir = match root.lookup("plugin.dir").and_then(|v| v.get_str()) {
        None => {
            let _ = writeln!(&mut io::stderr(),
                             "error: required string config value plugin.dir missing");
            return Err(ErrBadConfig);
        }
        Some(s) => s.clone()
    };
    let reconnect = match root.lookup("general.reconnect").and_then(|v| v.get_int()) {
        None => Some(5),
        Some(x) if x < 0 => None,
        Some(x) => Some(x.to_uint().unwrap())
    };
    let backoff = root.lookup("general.reconnect_backoff").and_then(|v| v.get_bool())
                      .unwrap_or(true);
    let default_nick = root.lookup("general.defaults.nick").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"rustbot");
    let default_user = root.lookup("general.defaults.user").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"rustbot");
    let default_real = root.lookup("general.defaults.real").and_then(|v| v.get_str())
                           .map(|s| s.clone()).unwrap_or_else(|| ~"Rust IRC Bot");

    let mut servers = ~[];
    let server_list = match root.lookup_key("servers").and_then(|v| v.get_table_array()) {
        None => {
            let _ = writeln!(&mut io::stderr(), "error: at least one server must be defined");
            return Err(ErrBadConfig);
        }
        Some(ary) => ary.as_slice()
    };
    for elem in server_list.iter() {
        let name = match elem.lookup_key("name").and_then(|v| v.get_str()) {
            None => {
                let _ = writeln!(&mut io::stderr(),
                                 "error: server entry missing required 'name' key");
                return Err(ErrBadConfig);
            }
            Some(s) => s.clone()
        };
        let server = match elem.lookup_key("server").and_then(|v| v.get_str()) {
            None => {
                let _ = writeln!(&mut io::stderr(),
                                 "error: server entry missing required 'server' key");
                return Err(ErrBadConfig);
            }
            Some(s) => s.clone()
        };
        let use_ssl = elem.lookup_key("use_ssl").and_then(|v| v.get_bool()).unwrap_or(false);
        if use_ssl {
            let _ = writeln!(&mut io::stderr(), "error: use_ssl is not currently implemented");
            return Err(ErrBadConfig);
        }
        let default_port = if use_ssl { 6697 } else { 6667 };
        let port = match elem.lookup_key("port").and_then(|v| v.get_int()).unwrap_or(default_port)
                             .to_uint() {
            None => {
                let _ = writeln!(&mut io::stderr(), "error: port is out of range");
                return Err(ErrBadConfig);
            }
            Some(p) => p
        };
        let nick = elem.lookup_key("nick").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_nick.clone());
        let user = elem.lookup_key("user").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_user.clone());
        let real = elem.lookup_key("real").and_then(|v| v.get_str()).map(|s| s.clone())
                       .unwrap_or_else(|| default_real.clone());
        servers.push(Server{ name: name, host: server, port: port, use_ssl: use_ssl,
                             nick: nick, user: user, real: real });
    }

    Ok(Config{
        plugin_dir: plugin_dir,
        reconnect_time: reconnect,
        reconnect_backoff: backoff,
        servers: servers
    })
}
<|endoftext|>


<commit_before>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;

/// Vector of `Resource`
pub type Resources = Vec<Resource>;
/// Vector of `ResourceIdentifiers`
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

pub type JsonApiId = String;
pub type JsonApiIds<'a> = Vec<&'a JsonApiId>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional `JsonApiDocument` payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
    /// Of these, `data` and `errors` must not co-exist.
    /// The optional field `included` may only be present if the `data` field is present too.
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }
}

impl Resource {
    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::Resource;
    ///
    /// let serialized = r#"{
    ///   "id":"1",
    ///   "type":"post",
    ///   "attributes":{
    ///     "title": "Rails is Omakase",
    ///     "likes": 250
    ///   },
    ///   "relationships":{},
    ///   "links" :{}
    /// }"#;
    ///
    /// let data = Resource::from_str(&serialized);
    /// assert_eq!(data.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }

    pub fn get_relationship(&self, name: &str) -> Option<&Relationship> {
        match self.relationships {
            None => None,
            Some(ref relationships) => {
                match relationships.get(name) {
                    None => None,
                    Some(rel) => Some(rel),
                }
            }
        }
    }

    /// Get an attribute `JsonApiValue`
    ///
    /// ```
    /// use jsonapi::api::Resource;
    ///
    /// let serialized = r#"{
    ///   "id":"1",
    ///   "type":"post",
    ///   "attributes":{
    ///     "title": "Rails is Omakase",
    ///     "likes": 250
    ///   },
    ///   "relationships":{},
    ///   "links" :{}
    /// }"#;
    ///
    /// match Resource::from_str(&serialized) {
    ///   Err(_)=> assert!(false),
    ///   Ok(resource)=> {
    ///     match resource.get_attribute("title") {
    ///       None => assert!(false),
    ///       Some(attr) => {
    ///         match attr.as_str() {
    ///           None => assert!(false),
    ///           Some(s) => {
    ///               assert_eq!(s, "Rails is Omakase");
    ///           }
    ///         }
    ///       }
    ///     }
    ///   }
    /// }
    pub fn get_attribute(&self, name: &str) -> Option<&JsonApiValue> {
        match self.attributes.get(name) {
            None => None,
            Some(val) => Some(&val),
        }
    }

    pub fn get_attribute_as_string(&self, attr: &str) -> Result<String, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_str() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn get_attribute_as_i64(&self, attr: &str) -> Result<i64, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_i64() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }
}

impl Relationship {
    pub fn as_id(&self) -> Result<Option<&JsonApiId>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Multiple(_) => Err(RelationshipAssumptionError::RelationshipIsAList),
            IdentifierData::Single(ref data) => Ok(Some(&data.id)),
        }
    }

    pub fn as_ids(&self) -> Result<Option<JsonApiIds>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Single(_) => Err(RelationshipAssumptionError::RelationshipIsNotAList),
            IdentifierData::Multiple(ref data) => Ok(Some(data.iter().map(|x| &x.id).collect())),
        }
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}

#[derive(Debug, PartialEq)]
pub enum JsonApiDataError {
    AttributeNotFound,
    IncompatibleAttributeType,
}

#[derive(Debug, PartialEq)]
pub enum RelationshipAssumptionError {
    RelationshipIsAList,
    RelationshipIsNotAList,
}
<commit_msg>feature: Stub Resource patch/diff functions<commit_after>use serde_json;
use std::collections::HashMap;

/// Permitted JSON-API values (all JSON Values)
pub type JsonApiValue = serde_json::Value;

/// Vector of `Resource`
pub type Resources = Vec<Resource>;
/// Vector of `ResourceIdentifiers`
pub type ResourceIdentifiers = Vec<ResourceIdentifier>;
pub type Links = HashMap<String, JsonApiValue>;
/// Meta-data object, can contain any data
pub type Meta = HashMap<String, JsonApiValue>;
/// Resource Attributes, can be any JSON value
pub type ResourceAttributes = HashMap<String, JsonApiValue>;
/// Map of relationships with other objects
pub type Relationships = HashMap<String, Relationship>;
/// Side-loaded Resources
pub type Included = Vec<Resource>;
/// Data-related errors
pub type JsonApiErrors = Vec<JsonApiError>;

pub type JsonApiId = String;
pub type JsonApiIds<'a> = Vec<&'a JsonApiId>;

/// Resource Identifier
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ResourceIdentifier {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
}

/// JSON-API Resource
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Resource {
    #[serde(rename = "type")]
    pub _type: String,
    pub id: JsonApiId,
    pub attributes: ResourceAttributes,
    pub relationships: Option<Relationships>,
    pub links: Option<Links>,
}

/// Relationship with another object
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct Relationship {
    pub data: IdentifierData,
    pub links: Option<Links>,
}

/// Valid data Resource (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum PrimaryData {
    None,
    Single(Resource),
    Multiple(Resources),
}

/// Valid Resource Identifier (can be None)
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum IdentifierData {
    None,
    Single(ResourceIdentifier),
    Multiple(ResourceIdentifiers),
}

/// The specification refers to this as a top-level `document`
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiDocument {
    pub data: Option<PrimaryData>,
    pub included: Option<Resources>,
    pub links: Option<Links>,
    pub meta: Option<Meta>,
    pub errors: Option<JsonApiErrors>,
    pub jsonapi: Option<JsonApiInfo>,
}

/// Error location
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct ErrorSource {
    pub pointer: Option<String>,
    pub parameter: Option<String>,
}

/// JSON-API Error
/// All fields are optional
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiError {
    pub id: Option<String>,
    pub links: Option<Links>,
    pub status: Option<String>,
    pub code: Option<String>,
    pub title: Option<String>,
    pub detail: Option<String>,
    pub source: Option<ErrorSource>,
    pub meta: Option<Meta>,
}

/// Optional `JsonApiDocument` payload identifying the JSON-API version the server implements
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct JsonApiInfo {
    pub version: Option<String>,
    pub meta: Option<Meta>,
}

/// Pagination links
#[derive(Serialize, Deserialize, Debug)]
pub struct Pagination {
    pub first: Option<String>,
    pub prev: Option<String>,
    pub next: Option<String>,
    pub last: Option<String>,
}

#[derive(Debug)]
pub struct Patch {
    pub patch_type: PatchType,
    pub subject: String,
    pub previous: JsonApiValue,
    pub next: JsonApiValue,
}

#[derive(Debug)]
pub struct PatchSet {
    pub resource_type: String,
    pub resource_id: String,
    pub patches: Vec<Patch>,
}

impl Pagination {
    pub fn has_first(&self) -> bool {
        !self.first.is_none()
    }
    pub fn has_prev(&self) -> bool {
        !self.prev.is_none()
    }
    pub fn has_next(&self) -> bool {
        !self.next.is_none()
    }
    pub fn has_last(&self) -> bool {
        !self.last.is_none()
    }
}

/// Top-level JSON-API Document
impl JsonApiDocument {
    fn has_errors(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_meta(&self) -> bool {
        !self.errors.is_none()
    }
    fn has_included(&self) -> bool {
        !self.included.is_none()
    }
    fn has_data(&self) -> bool {
        !self.data.is_none()
    }
    /// This function returns `false` if the `JsonApiDocument` contains any violations of the
    /// specification. See `DocumentValidationError`
    ///
    /// The spec dictates that the document must have least one of `data`, `errors` or `meta`.
    /// Of these, `data` and `errors` must not co-exist.
    /// The optional field `included` may only be present if the `data` field is present too.
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors};
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// assert_eq!(doc.is_valid(), false);
    /// ```
    pub fn is_valid(&self) -> bool {
        match self.validate() {
            Some(_) => false,
            None => true,
        }
    }

    /// This function returns a `Vec` with identified specification violations enumerated in
    /// `DocumentValidationError`
    ///
    /// ```
    /// use jsonapi::api::{JsonApiDocument, PrimaryData, JsonApiErrors, DocumentValidationError};
    ///
    /// let doc = JsonApiDocument {
    ///     data: Some(PrimaryData::None),
    ///     errors: Some(JsonApiErrors::new()),
    ///     meta: None,
    ///     included: None,
    ///     links: None,
    ///     jsonapi: None,
    /// };
    ///
    /// match doc.validate() {
    ///   Some(errors) => {
    ///     assert!(
    ///       errors.contains(
    ///         &DocumentValidationError::DataWithErrors
    ///       )
    ///     )
    ///   }
    ///   None => assert!(false)
    /// }
    /// ```
    pub fn validate(&self) -> Option<Vec<DocumentValidationError>> {

        let mut errors = Vec::<DocumentValidationError>::new();

        if self.has_data() && self.has_errors() {
            errors.push(DocumentValidationError::DataWithErrors);
        }

        if self.has_included() && !self.has_data() {
            errors.push(DocumentValidationError::IncludedWithoutData);
        }

        if !(self.has_data() || self.has_meta() || self.has_errors()) {
            errors.push(DocumentValidationError::MissingContent);
        }

        match errors.len() {
            0 => None,
            _ => Some(errors),
        }

    }

    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::JsonApiDocument;
    ///
    /// let serialized = r#"{
    ///   "data" : [
    ///     { "id":"1", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"2", "type":"post", "attributes":{}, "relationships":{}, "links" :{} },
    ///     { "id":"3", "type":"post", "attributes":{}, "relationships":{}, "links" :{} }
    ///   ]
    /// }"#;
    /// let doc = JsonApiDocument::from_str(&serialized);
    /// assert_eq!(doc.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }
}

impl Resource {
    /// Instantiate from string
    ///
    /// ```
    /// use jsonapi::api::Resource;
    ///
    /// let serialized = r#"{
    ///   "id":"1",
    ///   "type":"post",
    ///   "attributes":{
    ///     "title": "Rails is Omakase",
    ///     "likes": 250
    ///   },
    ///   "relationships":{},
    ///   "links" :{}
    /// }"#;
    ///
    /// let data = Resource::from_str(&serialized);
    /// assert_eq!(data.is_ok(), true);
    /// ```
    pub fn from_str(s: &str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(&s)
    }

    pub fn get_relationship(&self, name: &str) -> Option<&Relationship> {
        match self.relationships {
            None => None,
            Some(ref relationships) => {
                match relationships.get(name) {
                    None => None,
                    Some(rel) => Some(rel),
                }
            }
        }
    }

    /// Get an attribute `JsonApiValue`
    ///
    /// ```
    /// use jsonapi::api::Resource;
    ///
    /// let serialized = r#"{
    ///   "id":"1",
    ///   "type":"post",
    ///   "attributes":{
    ///     "title": "Rails is Omakase",
    ///     "likes": 250
    ///   },
    ///   "relationships":{},
    ///   "links" :{}
    /// }"#;
    ///
    /// match Resource::from_str(&serialized) {
    ///   Err(_)=> assert!(false),
    ///   Ok(resource)=> {
    ///     match resource.get_attribute("title") {
    ///       None => assert!(false),
    ///       Some(attr) => {
    ///         match attr.as_str() {
    ///           None => assert!(false),
    ///           Some(s) => {
    ///               assert_eq!(s, "Rails is Omakase");
    ///           }
    ///         }
    ///       }
    ///     }
    ///   }
    /// }
    pub fn get_attribute(&self, name: &str) -> Option<&JsonApiValue> {
        match self.attributes.get(name) {
            None => None,
            Some(val) => Some(&val),
        }
    }

    pub fn get_attribute_as_string(&self, attr: &str) -> Result<String, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_str() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn get_attribute_as_i64(&self, attr: &str) -> Result<i64, JsonApiDataError> {
        match self.attributes.get(attr) {
            None => Err(JsonApiDataError::AttributeNotFound),
            Some(json_attr) => {
                match json_attr.as_i64() {
                    None => Err(JsonApiDataError::IncompatibleAttributeType),
                    Some(s) => Ok(s.into()),
                }
            }
        }
    }

    pub fn diff(&self, alt: Resource) -> Result<PatchSet, DiffPatchError> {
        unimplemented!();
    }

    pub fn patch(&mut self, patchset: PatchSet) -> Result<(), DiffPatchError> {
        unimplemented!();
    }
}

impl Relationship {
    pub fn as_id(&self) -> Result<Option<&JsonApiId>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Multiple(_) => Err(RelationshipAssumptionError::RelationshipIsAList),
            IdentifierData::Single(ref data) => Ok(Some(&data.id)),
        }
    }

    pub fn as_ids(&self) -> Result<Option<JsonApiIds>, RelationshipAssumptionError> {
        match self.data {
            IdentifierData::None => Ok(None),
            IdentifierData::Single(_) => Err(RelationshipAssumptionError::RelationshipIsNotAList),
            IdentifierData::Multiple(ref data) => Ok(Some(data.iter().map(|x| &x.id).collect())),
        }
    }
}

/// Top-level (Document) JSON-API specification violations
#[derive(Debug, PartialEq)]
pub enum DocumentValidationError {
    IncludedWithoutData,
    DataWithErrors,
    MissingContent,
}

#[derive(Debug, PartialEq)]
pub enum JsonApiDataError {
    AttributeNotFound,
    IncompatibleAttributeType,
}

#[derive(Debug, PartialEq)]
pub enum RelationshipAssumptionError {
    RelationshipIsAList,
    RelationshipIsNotAList,
}

#[derive(Debug, PartialEq)]
pub enum DiffPatchError {
    IncompatibleType(String, String),
    NonExistentProperty(String),
    IncorrectPropertyValue(String),
}

#[derive(Debug, PartialEq)]
pub enum PatchType {
    Relationship,
    Attribute,
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use state::{TurtleState, DrawingState, Path};

/// Types that will be shared with another thread
pub type Shared<T> = Arc<RwLock<T>>;
/// Alias to help make the types more understandable without exposing as many implementation details
pub type ReadOnlyRef<'a, T> = RwLockReadGuard<'a, T>;
pub type MutableRef<'a, T> = RwLockWriteGuard<'a, T>;

/// A structure that provides read-only access to shared state
pub struct ReadOnly {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl ReadOnly {
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    pub fn temporary_path(&self) -> ReadOnlyRef<Option<Path>> {
        self.temporary_path.read().expect("bug: Lock was poisoned")
    }
}

/// Container for all the state of a turtle application
pub struct TurtleApp {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl TurtleApp {
    pub fn new() -> Self {
        Self {
            turtle: Arc::new(RwLock::new(TurtleState::default())),
            drawing: Arc::new(RwLock::new(DrawingState::default())),
            temporary_path: Arc::new(RwLock::new(None)),
        }
    }

    /// Provide a read-only version of the state
    pub fn read_only(&self) -> ReadOnly {
        ReadOnly {
            turtle: Arc::clone(&self.turtle),
            drawing: Arc::clone(&self.drawing),
            temporary_path: Arc::clone(&self.temporary_path),
        }
    }

    /// Provides read-only access to the turtle state
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the turtle state
    pub fn turtle_mut(&mut self) -> MutableRef<TurtleState> {
        self.turtle.write().expect("bug: Lock was poisoned")
    }

    /// Provides read-only access to the drawing
    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the drawing
    pub fn drawing_mut(&mut self) -> MutableRef<DrawingState> {
        self.drawing.write().expect("bug: Lock was poisoned")
    }

    /// Provides read-only access to the temporary path
    pub fn temporary_path(&self) -> ReadOnlyRef<Option<Path>> {
        self.temporary_path.read().expect("bug: Lock was poisoned")
    }

    /// Set the temporary_path to a new value, overwriting the previous one
    pub fn set_temporary_path(&mut self, path: Option<Path>) {
        let mut temp = self.temporary_path.write().expect("bug: Lock was poisoned");
        *temp = path;
    }

}
<commit_msg>Removed unused temporary_path method from TurtleApp<commit_after>use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use state::{TurtleState, DrawingState, Path};

/// Types that will be shared with another thread
pub type Shared<T> = Arc<RwLock<T>>;
/// Alias to help make the types more understandable without exposing as many implementation details
pub type ReadOnlyRef<'a, T> = RwLockReadGuard<'a, T>;
pub type MutableRef<'a, T> = RwLockWriteGuard<'a, T>;

/// A structure that provides read-only access to shared state
pub struct ReadOnly {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl ReadOnly {
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    pub fn temporary_path(&self) -> ReadOnlyRef<Option<Path>> {
        self.temporary_path.read().expect("bug: Lock was poisoned")
    }
}

/// Container for all the state of a turtle application
pub struct TurtleApp {
    turtle: Shared<TurtleState>,
    drawing: Shared<DrawingState>,
    /// A temporary path for use during animations
    temporary_path: Shared<Option<Path>>,
}

impl TurtleApp {
    pub fn new() -> Self {
        Self {
            turtle: Arc::new(RwLock::new(TurtleState::default())),
            drawing: Arc::new(RwLock::new(DrawingState::default())),
            temporary_path: Arc::new(RwLock::new(None)),
        }
    }

    /// Provide a read-only version of the state
    pub fn read_only(&self) -> ReadOnly {
        ReadOnly {
            turtle: Arc::clone(&self.turtle),
            drawing: Arc::clone(&self.drawing),
            temporary_path: Arc::clone(&self.temporary_path),
        }
    }

    /// Provides read-only access to the turtle state
    pub fn turtle(&self) -> ReadOnlyRef<TurtleState> {
        self.turtle.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the turtle state
    pub fn turtle_mut(&mut self) -> MutableRef<TurtleState> {
        self.turtle.write().expect("bug: Lock was poisoned")
    }

    /// Provides read-only access to the drawing
    pub fn drawing(&self) -> ReadOnlyRef<DrawingState> {
        self.drawing.read().expect("bug: Lock was poisoned")
    }

    /// Provides mutable access to the drawing
    pub fn drawing_mut(&mut self) -> MutableRef<DrawingState> {
        self.drawing.write().expect("bug: Lock was poisoned")
    }

    /// Set the temporary_path to a new value, overwriting the previous one
    pub fn set_temporary_path(&mut self, path: Option<Path>) {
        let mut temp = self.temporary_path.write().expect("bug: Lock was poisoned");
        *temp = path;
    }

}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;
use env;

#[derive(Clone, PartialEq)]
pub enum ExprAst {
    Int(IntNode),
    Str(StrNode),
    Bool(BoolNode),
    Pair(PairNode),
    Symbol(SymbolNode),
    Char(CharNode),
    Proc(ProcNode),
    CompProc(CompProcNode),
    Nil
}

pub trait Ast {
    fn print(&self);
}

impl Ast for ExprAst {
    fn print(&self) {
        match *self {
            ExprAst::Int(ref ast) =>  ast.print(),
            ExprAst::Str(ref ast) =>  ast.print(),
            ExprAst::Bool(ref ast) => ast.print(),
            ExprAst::Pair(ref ast) => ast.print(),
            ExprAst::Symbol(ref ast) => ast.print(),
            ExprAst::Char(ref ast) => ast.print(),
            ExprAst::Proc(ref ast) => ast.print(),
            ExprAst::CompProc(ref ast) => ast.print(),
            ExprAst::Nil => println!("Nil")
        }
    }
}

macro_rules! is_ast_type {
    ($func_name:ident, $type_name:ident) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            match *self {
                ExprAst::$type_name(_) => true,
                _ => false
            }
        }})
}

is_ast_type!(is_char, Char);
is_ast_type!(is_int, Int);
is_ast_type!(is_symbol, Symbol);
is_ast_type!(is_string, Str);
is_ast_type!(is_proc, Proc);
is_ast_type!(is_bool, Bool);
is_ast_type!(is_cproc, CompProc);

macro_rules! is_type {
    ($func_name:ident, $type_str:expr) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            return self.is_tagged(ExprAst::Symbol(SymbolNode::new($type_str)))
        }
    })
}

is_type!(is_quote, "quote");
is_type!(is_def, "define");
is_type!(is_and, "and");
is_type!(is_or, "or");
is_type!(is_if, "if");
is_type!(is_assign, "set!");
is_type!(is_lambda, "lambda");
is_type!(is_cond, "cond");
is_type!(is_let, "let");
is_type!(is_begin, "begin");

impl ExprAst {
    pub fn is_true(&self) -> bool {
        return self.as_bool();
    }

    pub fn is_false(&self) -> bool {
        return !self.as_bool();
    }

    pub fn is_pair(&self) -> bool {
        match *self {
            ExprAst::Pair(_) => true,
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn as_bool(&self) -> bool {
        match *self {
            ExprAst::Bool(ref ast) => ast.value,
            _ => panic!("error type: expect BoolNode")
        }
    }

    pub fn as_int(&self) -> isize {
        match *self {
            ExprAst::Int(ref ast) => ast.value,
            _ => panic!("error type: expect IntNode")
        }
    }

    pub fn as_str(&self) -> String {
        match *self {
            ExprAst::Str(ref ast) => ast.value.clone(),
            ExprAst::Symbol(ref ast) => ast.value.clone(),
            _ => panic!("error type: expect StrNode")
        }
    }

    pub fn as_char(&self) -> char {
        match *self {
            ExprAst::Char(ref ast) => ast.value,
            _ => panic!("error type: expect CharNode")
        }
    }

    pub fn as_proc(&self) -> ProcFunc {
        match *self {
            ExprAst::Proc(ref ast) => ast.func.clone(),
            _ => panic!("error type: expct ProcNode")
        }
    }

    pub fn car(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn cdr(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn c(&self, s: &str) -> ExprAst {
        assert!(self.is_pair());
        let mut r = self.clone();
        for c in s.to_string().chars() {
            if c == 'a' { r = r.car(); }
            else { r = r.cdr(); }
        }
        return r;
    }

    pub fn is_last(&self) -> bool {
        assert!(self.is_pair());
        return self.cdr().is_empty();
    }

    pub fn is_self(&self) -> bool {
        match *self {
            ExprAst::Bool(_) => true,
            ExprAst::Int(_) => true,
            ExprAst::Char(_) => true,
            ExprAst::Str(_) => true,
            _ => false
        }
    }

    pub fn def_var(&self) -> ExprAst {
        assert!(self.is_def());
        if self.cdr().car().is_symbol() {
            self.c("da")
        } else {
            self.c("daa")
        }
    }

    pub fn def_val(&self) -> ExprAst {
        assert!(self.is_def());
        if self.c("da").is_symbol() {
            self.c("dda")
        } else {
            //proc
            return self.c("dad").make_lambda(self.c("dd"));
        }
    }

    pub fn make_lambda(&self, body: ExprAst) -> ExprAst {
        let lambda = ExprAst::Symbol(SymbolNode::new("lambda"));
        return ExprAst::Pair(PairNode::new(lambda,
                                           ExprAst::Pair(PairNode::new(
                                               (*self).clone(), body))));
    }

    pub fn params(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    pub fn body(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    fn is_tagged(&self, tag: ExprAst) -> bool {
        if self.is_pair() {
            let car = self.car();
            return car.is_symbol() && car == tag;
        }
        return false;
    }
}

#[derive(Clone, PartialEq, Eq)]
pub struct IntNode {
    value: isize
}

impl IntNode {
    pub fn new(val: isize) -> IntNode {
        IntNode{ value: val}
    }
    fn print(&self) {
        println!("IntNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct StrNode {
    value: String
}

impl StrNode {
    pub fn new(val: &str) -> StrNode {
        StrNode{ value: val.to_string()}
    }

    fn print(&self) {
        println!("StrNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct BoolNode {
    value: bool
}

impl BoolNode {
    pub fn new(val: bool) -> BoolNode {
        BoolNode{ value: val}
    }

    fn print(&self) {
        println!("BoolNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct PairNode{
    pair: Vec<ExprAst>,
}

impl PairNode {
    pub fn new(car: ExprAst, cdr: ExprAst) -> PairNode {
        PairNode {
            pair: vec![car, cdr]
        }
    }

    fn print(&self) {
        println!("PairNode (");
        self.pair[0].print();
        self.pair[1].print();
        println!(")");
    }
}

#[derive(Clone, PartialEq)]
pub struct SymbolNode {
    value: String
}

impl SymbolNode {
    pub fn new(val: &str) -> SymbolNode {
        SymbolNode { value: val.to_string() }
    }

    fn print(&self) {
        println!("SymbolNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct CharNode {
    value: char
}

impl CharNode {
    pub fn new(val: char) -> CharNode {
        CharNode { value: val}
    }

    fn print(&self) {
        println!("CharNode: {}", self.value);
    }
}

#[derive(Clone)]
pub struct ProcFunc(fn(ExprAst) -> ExprAst);
impl PartialEq for ProcFunc {
    fn eq(&self, o: &ProcFunc) -> bool {
        let _o: *const() = unsafe { ::std::mem::transmute(o)};
        let _s: *const() = unsafe { ::std::mem::transmute(self)};
        _s == _o
    }
    fn ne(&self, o: &ProcFunc) -> bool {
        !self.eq(o)
    }
}

impl ProcFunc {
    pub fn func(&self) -> (fn(ExprAst) -> ExprAst) {
        match *self {
            ProcFunc(fun) => fun
        }
    }
}

#[derive(Clone, PartialEq)]
pub struct ProcNode {
    value: String,
    func: ProcFunc
}

impl ProcNode {
    pub fn new(obj: fn(ExprAst)-> ExprAst) -> ProcNode {
        ProcNode { value: "proc".to_string(), func: ProcFunc(obj) }
    }

    fn print(&self) {
        println!("ProcNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct CompProcNode {
    pub pair:   Vec<ExprAst>,
    //pub env:    Option<Box<env::Env>>
    pub env:      Rc<RefCell<env::Env>>
}

impl CompProcNode {
    pub fn new(params: ExprAst, body: ExprAst, env: Rc<RefCell<env::Env>>) -> CompProcNode {
        CompProcNode { pair: vec![params, body],  env: env }
    }

    fn print(&self) {
        println!("CompProcNode: ");
    }
}

#[test]
fn test_ast() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_int() == 3);

    let char_node = ExprAst::Char(CharNode::new('a'));
    assert!(char_node.as_char() == 'a');

    let bool_node = ExprAst::Bool(BoolNode::new(false));
    assert!(bool_node.as_bool() == false);

    let str_node = ExprAst::Str(StrNode::new("hello"));
    assert!(str_node.as_str() == "hello");
    assert!(str_node.is_self());

    let int_node = ExprAst::Int(IntNode::new(3));
    int_node.print();
    let str_node = ExprAst::Str(StrNode::new("hello"));
    str_node.print();
    let pair_node = ExprAst::Pair(PairNode::new(int_node, str_node));
    let car_node = pair_node.car();
    let cdr_node = pair_node.cdr();
    assert!(car_node.as_int() == 3);
    assert!(cdr_node.as_str() == "hello");
    assert!(!pair_node.is_self());

    let sym_node = ExprAst::Symbol(SymbolNode::new("sym"));
    assert!(sym_node.is_symbol());
    assert!(!sym_node.is_self());

    let empty_node = ExprAst::Nil;
    assert!(empty_node.is_empty());
    assert!(!empty_node.is_self());
}

#[test]
fn test_ast_is_set() {
    macro_rules! test_case {
        ($str_name:expr) => {
            {let node = ExprAst::Pair(PairNode::new(
                ExprAst::Symbol(SymbolNode::new($str_name)),
                ExprAst::Int(IntNode::new(3))));
            node}
        }
    }
    assert!(test_case!("let").is_let());
    assert!(test_case!("if").is_if());
    assert!(test_case!("lambda").is_lambda());
    assert!(test_case!("cond").is_cond());
    assert!(test_case!("set!").is_assign());
    assert!(test_case!("begin").is_begin());
    assert!(!test_case!("begin").is_assign());
}

#[test]
fn test_symbol_eq() {
    let aa = ExprAst::Symbol(SymbolNode::new("else"));
    let bb = ExprAst::Symbol(SymbolNode::new("else"));
    assert!(aa == bb);
}

#[test]
fn test_proc() {
    fn _proc(obj: ExprAst) -> ExprAst {
        obj.print();
        return ExprAst::Symbol(SymbolNode::new("ok"));
    }

    let proc_node = ExprAst::Proc(ProcNode::new(_proc));
    assert!(proc_node.is_proc());
    assert!(!proc_node.is_cproc());
}
<commit_msg>cleanup<commit_after>use std::cell::RefCell;
use std::rc::Rc;
use env;

#[derive(Clone, PartialEq)]
pub enum ExprAst {
    Int(IntNode),
    Str(StrNode),
    Bool(BoolNode),
    Pair(PairNode),
    Symbol(SymbolNode),
    Char(CharNode),
    Proc(ProcNode),
    CompProc(CompProcNode),
    Nil
}

pub trait Ast {
    fn print(&self);
}

impl Ast for ExprAst {
    fn print(&self) {
        match *self {
            ExprAst::Int(ref ast) =>  ast.print(),
            ExprAst::Str(ref ast) =>  ast.print(),
            ExprAst::Bool(ref ast) => ast.print(),
            ExprAst::Pair(ref ast) => ast.print(),
            ExprAst::Symbol(ref ast) => ast.print(),
            ExprAst::Char(ref ast) => ast.print(),
            ExprAst::Proc(ref ast) => ast.print(),
            ExprAst::CompProc(ref ast) => ast.print(),
            ExprAst::Nil => println!("Nil")
        }
    }
}

macro_rules! is_ast_type {
    ($func_name:ident, $type_name:ident) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            match *self {
                ExprAst::$type_name(_) => true,
                _ => false
            }
        }})
}

is_ast_type!(is_char, Char);
is_ast_type!(is_int, Int);
is_ast_type!(is_symbol, Symbol);
is_ast_type!(is_string, Str);
is_ast_type!(is_proc, Proc);
is_ast_type!(is_bool, Bool);
is_ast_type!(is_cproc, CompProc);

macro_rules! is_type {
    ($func_name:ident, $type_str:expr) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            return self.is_tagged(ExprAst::Symbol(SymbolNode::new($type_str)))
        }
    })
}

is_type!(is_quote, "quote");
is_type!(is_def, "define");
is_type!(is_and, "and");
is_type!(is_or, "or");
is_type!(is_if, "if");
is_type!(is_assign, "set!");
is_type!(is_lambda, "lambda");
is_type!(is_cond, "cond");
is_type!(is_let, "let");
is_type!(is_begin, "begin");

impl ExprAst {
    pub fn is_true(&self) -> bool {
        return self.as_bool();
    }

    pub fn is_false(&self) -> bool {
        return !self.as_bool();
    }

    pub fn is_pair(&self) -> bool {
        match *self {
            ExprAst::Pair(_) => true,
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn as_bool(&self) -> bool {
        match *self {
            ExprAst::Bool(ref ast) => ast.value,
            _ => panic!("error type: expect BoolNode")
        }
    }

    pub fn as_int(&self) -> isize {
        match *self {
            ExprAst::Int(ref ast) => ast.value,
            _ => panic!("error type: expect IntNode")
        }
    }

    pub fn as_str(&self) -> String {
        match *self {
            ExprAst::Str(ref ast) => ast.value.clone(),
            ExprAst::Symbol(ref ast) => ast.value.clone(),
            _ => panic!("error type: expect StrNode")
        }
    }

    pub fn as_char(&self) -> char {
        match *self {
            ExprAst::Char(ref ast) => ast.value,
            _ => panic!("error type: expect CharNode")
        }
    }

    pub fn as_proc(&self) -> ProcFunc {
        match *self {
            ExprAst::Proc(ref ast) => ast.func.clone(),
            _ => panic!("error type: expct ProcNode")
        }
    }

    pub fn car(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn cdr(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn c(&self, s: &str) -> ExprAst {
        assert!(self.is_pair());
        let mut r = self.clone();
        for c in s.to_string().chars() {
            if c == 'a' { r = r.car(); }
            else { r = r.cdr(); }
        }
        return r;
    }

    pub fn is_last(&self) -> bool {
        assert!(self.is_pair());
        return self.cdr().is_empty();
    }

    pub fn is_self(&self) -> bool {
        match *self {
            ExprAst::Bool(_) => true,
            ExprAst::Int(_) => true,
            ExprAst::Char(_) => true,
            ExprAst::Str(_) => true,
            _ => false
        }
    }

    pub fn def_var(&self) -> ExprAst {
        assert!(self.is_def());
        if self.cdr().car().is_symbol() {
            self.c("da")
        } else {
            self.c("daa")
        }
    }

    pub fn def_val(&self) -> ExprAst {
        assert!(self.is_def());
        if self.c("da").is_symbol() {
            self.c("dda")
        } else {
            //proc
            return self.c("dad").make_lambda(self.c("dd"));
        }
    }

    pub fn make_lambda(&self, body: ExprAst) -> ExprAst {
        let lambda = ExprAst::Symbol(SymbolNode::new("lambda"));
        return ExprAst::Pair(PairNode::new(lambda,
                                           ExprAst::Pair(PairNode::new(
                                               (*self).clone(), body))));
    }

    pub fn params(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    pub fn body(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    fn is_tagged(&self, tag: ExprAst) -> bool {
        if self.is_pair() {
            let car = self.car();
            return car.is_symbol() && car == tag;
        }
        return false;
    }
}

#[derive(Clone, PartialEq, Eq)]
pub struct IntNode {
    value: isize
}

impl IntNode {
    pub fn new(val: isize) -> IntNode {
        IntNode{ value: val}
    }
    fn print(&self) {
        println!("IntNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct StrNode {
    value: String
}

impl StrNode {
    pub fn new(val: &str) -> StrNode {
        StrNode{ value: val.to_string()}
    }

    fn print(&self) {
        println!("StrNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct BoolNode {
    value: bool
}

impl BoolNode {
    pub fn new(val: bool) -> BoolNode {
        BoolNode{ value: val}
    }

    fn print(&self) {
        println!("BoolNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct PairNode{
    pair: Vec<ExprAst>,
}

impl PairNode {
    pub fn new(car: ExprAst, cdr: ExprAst) -> PairNode {
        PairNode {
            pair: vec![car, cdr]
        }
    }

    fn print(&self) {
        println!("PairNode (");
        self.pair[0].print();
        self.pair[1].print();
        println!(")");
    }
}

#[derive(Clone, PartialEq)]
pub struct SymbolNode {
    value: String
}

impl SymbolNode {
    pub fn new(val: &str) -> SymbolNode {
        SymbolNode { value: val.to_string() }
    }

    fn print(&self) {
        println!("SymbolNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct CharNode {
    value: char
}

impl CharNode {
    pub fn new(val: char) -> CharNode {
        CharNode { value: val}
    }

    fn print(&self) {
        println!("CharNode: {}", self.value);
    }
}

#[derive(Clone)]
pub struct ProcFunc(fn(ExprAst) -> ExprAst);
impl PartialEq for ProcFunc {
    fn eq(&self, o: &ProcFunc) -> bool {
        let _o: *const() = unsafe { ::std::mem::transmute(o)};
        let _s: *const() = unsafe { ::std::mem::transmute(self)};
        _s == _o
    }
    fn ne(&self, o: &ProcFunc) -> bool {
        !self.eq(o)
    }
}

impl ProcFunc {
    pub fn func(&self) -> (fn(ExprAst) -> ExprAst) {
        match *self {
            ProcFunc(fun) => fun
        }
    }
}

#[derive(Clone, PartialEq)]
pub struct ProcNode {
    value: String,
    func: ProcFunc
}

impl ProcNode {
    pub fn new(obj: fn(ExprAst)-> ExprAst) -> ProcNode {
        ProcNode { value: "proc".to_string(), func: ProcFunc(obj) }
    }

    fn print(&self) {
        println!("ProcNode: {}", self.value);
    }
}

#[derive(Clone, PartialEq)]
pub struct CompProcNode {
    pub pair:   Vec<ExprAst>,
    pub env:    Rc<RefCell<env::Env>>
}

impl CompProcNode {
    pub fn new(params: ExprAst, body: ExprAst, env: Rc<RefCell<env::Env>>) -> CompProcNode {
        CompProcNode { pair: vec![params, body],  env: env }
    }

    fn print(&self) {
        println!("CompProcNode: ");
    }
}

#[test]
fn test_ast() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_int() == 3);

    let char_node = ExprAst::Char(CharNode::new('a'));
    assert!(char_node.as_char() == 'a');

    let bool_node = ExprAst::Bool(BoolNode::new(false));
    assert!(bool_node.as_bool() == false);

    let str_node = ExprAst::Str(StrNode::new("hello"));
    assert!(str_node.as_str() == "hello");
    assert!(str_node.is_self());

    let int_node = ExprAst::Int(IntNode::new(3));
    int_node.print();
    let str_node = ExprAst::Str(StrNode::new("hello"));
    str_node.print();
    let pair_node = ExprAst::Pair(PairNode::new(int_node, str_node));
    let car_node = pair_node.car();
    let cdr_node = pair_node.cdr();
    assert!(car_node.as_int() == 3);
    assert!(cdr_node.as_str() == "hello");
    assert!(!pair_node.is_self());

    let sym_node = ExprAst::Symbol(SymbolNode::new("sym"));
    assert!(sym_node.is_symbol());
    assert!(!sym_node.is_self());

    let empty_node = ExprAst::Nil;
    assert!(empty_node.is_empty());
    assert!(!empty_node.is_self());
}

#[test]
fn test_ast_is_set() {
    macro_rules! test_case {
        ($str_name:expr) => {
            {let node = ExprAst::Pair(PairNode::new(
                ExprAst::Symbol(SymbolNode::new($str_name)),
                ExprAst::Int(IntNode::new(3))));
            node}
        }
    }
    assert!(test_case!("let").is_let());
    assert!(test_case!("if").is_if());
    assert!(test_case!("lambda").is_lambda());
    assert!(test_case!("cond").is_cond());
    assert!(test_case!("set!").is_assign());
    assert!(test_case!("begin").is_begin());
    assert!(!test_case!("begin").is_assign());
}

#[test]
fn test_symbol_eq() {
    let aa = ExprAst::Symbol(SymbolNode::new("else"));
    let bb = ExprAst::Symbol(SymbolNode::new("else"));
    assert!(aa == bb);
}

#[test]
fn test_proc() {
    fn _proc(obj: ExprAst) -> ExprAst {
        obj.print();
        return ExprAst::Symbol(SymbolNode::new("ok"));
    }

    let proc_node = ExprAst::Proc(ProcNode::new(_proc));
    assert!(proc_node.is_proc());
    assert!(!proc_node.is_cproc());
}
<|endoftext|>