<commit_before>use std::rc::Rc;
use super::*;

gc_ref_type! {
    pub struct Pair / PairFields / PairStorage<'a> {
        head / set_head: Value<'a>,
        tail / set_tail: Value<'a>
    }
}

gc_inline_enum! {
    pub enum Value / ValueStorage <'a> {
        Null,
        Int(i32),
        Str(Rc<String>),  // <-- equality is by value
        Pair(Pair<'a>)  // <-- equality is by pointer
    }
}

/// Helper function to avoid having to write out `PairFields` literals all over the place.
fn alloc_pair<'a>(heap: &mut Heap<'a>, head: Value<'a>, tail: Value<'a>) -> Pair<'a> {
    heap.alloc(PairFields { head: head, tail: tail })
}

/// Allocate a pair with the values `(null, null)`.
fn alloc_null_pair<'a>(heap: &mut Heap<'a>) -> Pair<'a> {
    alloc_pair(heap, Value::Null, Value::Null)
}

/// Test that a Heap can at least allocate two objects.
#[test]
fn can_allocate_twice() {
    with_heap(|heap| {
        let obj1 = alloc_pair(heap, Value::Int(1), Value::Null);
        let obj2 = alloc_pair(heap, Value::Int(2), Value::Null);
        assert_eq!(obj1.head(), Value::Int(1));
        assert_eq!(obj2.head(), Value::Int(2));
    });
}

/// Test that rooted objects are not collected and reused.
#[test]
fn root_is_not_recycled() {
    with_heap(|heap| {
        // Create and root one object.
        let root = alloc_pair(heap, Value::Int(1), Value::Str(Rc::new("hello world".to_string())));

        // Subsequent allocations never return root.
        for _ in 0 .. HEAP_SIZE * 2 {
            let tmp = alloc_null_pair(heap);
            assert!(tmp != root);
        }
    });
}

fn null_pair<'a>() -> PairFields<'a> {
    PairFields { head: Value::Null, tail: Value::Null }
}

/// Test try_alloc()'s behavior when the heap is full and every Object is
/// reachable.
#[test]
fn full_heap() {
    with_heap(|heap| {
        // Fill up the heap by allocating HEAP_SIZE objects.
        let mut v = Value::Null;
        for _ in 0 .. HEAP_SIZE {
            v = Value::Pair(alloc_pair(heap, Value::Null, v));
        }

        // The whole heap is reachable.  Now try_alloc() should return null every
        // time it's called.
        for _ in 0 .. 4 {
            let attempt: Option<Pair> = heap.try_alloc(null_pair());
            assert_eq!(attempt, None);
        }
    });
}

/// Test allocate()'s behavior when the heap is only almost full.
#[test]
fn nearly_full_heap() {
    with_heap(|heap| {
        // Make the heap nearly full by allocating (HEAP_SIZE - 1) objects.
        let mut v = Value::Null;
        for _ in 0 .. HEAP_SIZE - 1 {
            v = Value::Pair(alloc_pair(heap, Value::Null, v));
        }

        // Now the entire heap is reachable except for one Object.  We should
        // be able to call allocate() successfully, repeatedly.  It returns
        // that one object every time it's called!
        let last = alloc_null_pair(heap).address();
        for _ in 0 .. 10 {
            assert_eq!(alloc_null_pair(heap).address(), last);
        }
    });
}

/// Test that objects reachable from a root's `.head` or `.tail` are not
/// collected.
#[test]
fn reachable_objects_not_collected() {
    with_heap(|heap| {
        let obj1 = alloc_null_pair(heap);
        let (p2, p3, p4, p5);
        {
            let obj2 = alloc_null_pair(heap);
            p2 = obj2.address();
            obj1.set_head(Value::Pair(obj2.clone()));
            let obj3 = alloc_null_pair(heap);
            p3 = obj3.address();
            obj1.set_tail(Value::Pair(obj3));
            let obj4 = alloc_null_pair(heap);
            p4 = obj4.address();
            obj2.set_head(Value::Pair(obj4));
            let obj5 = alloc_null_pair(heap);
            p5 = obj5.address();
            obj2.set_tail(Value::Pair(obj5));
        }

        heap.force_gc();

        let h = match obj1.head() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head")
        };
        assert_eq!(h.address(), p2);

        let t = match obj1.tail() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.tail")
        };
        assert_eq!(t.address(), p3);

        let hh = match h.head() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head.head")
        };
        assert_eq!(hh.address(), p4);

        let ht = match h.tail() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head.tail")
        };
        assert_eq!(ht.address(), p5);
    });
}

/// Test that the GC is not confused by an object that contains pointers to
/// itself.
#[test]
fn root_self_references() {
    with_heap(|heap| {
        // Create a root object that contains pointers to itself.
        let root = alloc_null_pair(heap);
        root.set_head(Value::Pair(root.clone()));
        root.set_tail(Value::Pair(root.clone()));

        heap.force_gc();

        // After GC, the root object should be unchanged.
        assert_eq!(root.head(), Value::Pair(root.clone()));
        assert_eq!(root.tail(), Value::Pair(root.clone()));
    });
}

/// Test that the GC is not confused by cycles in the reachable object graph.
#[test]
fn test_root_cycle() {
    with_heap(|heap| {
        // Set up obj1 and obj2 to point to each other.
        let obj1 = alloc_null_pair(heap);
        let obj2 = alloc_pair(heap,
                              Value::Pair(obj1.clone()),
                              Value::Pair(obj1.clone()));  // obj2 points to obj1
        obj1.set_head(Value::Pair(obj2.clone()));  // and vice versa
        obj1.set_tail(Value::Pair(obj2.clone()));

        heap.force_gc();

        // After GC, the two objects are unchanged.
        assert_eq!(obj1.head(), Value::Pair(obj2.clone()));
        assert_eq!(obj1.tail(), Value::Pair(obj2.clone()));
        assert_eq!(obj2.head(), Value::Pair(obj1.clone()));
        assert_eq!(obj2.tail(), Value::Pair(obj1.clone()));
    });
}

/// Test that the GC is not confused by cycles that are garbage.
#[test]
fn unreachable_cycle() {
    with_heap(|heap| {
        // Make a cycle.
        let (p1, p2);
        {
            let obj1 = alloc_null_pair(heap);
            p1 = obj1.address();
            let obj2 = alloc_null_pair(heap);
            p2 = obj2.address();
            obj2.set_tail(Value::Pair(obj1.clone()));
            obj1.set_tail(Value::Pair(obj2.clone()));
        }  // Make the cycle unreachable.

        // Allocation should eventually recycle both objects.
        let mut recycled1 = 0;
        let mut recycled2 = 0;
        let mut root = Value::Null;
        for _ in 0 .. HEAP_SIZE {
            let p = alloc_pair(heap, Value::Null, root);
            root = Value::Pair(p.clone());
            if p.address() == p1 {
                recycled1 += 1;
            }
            if p.address() == p2 {
                recycled2 += 1;
            }
        }
        assert_eq!(recycled1, 1);
        assert_eq!(recycled2, 1);
    });
}

// Tests that you can't share values across separate heaps. Amazingly,
// Rust enforces this rule at compile time; unfortunately, I don't fully
// understand *all* the parts of the enforcement mechanism, so it's worth
// testing.
//
// Try uncommenting the tests below: if any of them compile successfully,
// consider it a test failure!
/*

/// The most obvious case: you can't just straight-up pass an object from
/// one heap to another heap's `alloc` method.
#[test]
fn bug_cross_heap_edges_1() {
    with_heap(|heap1| {
        with_heap(|heap2| {
            let obj1 = heap1.alloc_null();  // error: cannot infer an appropriate lifetime
            let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
        });
    });
}

/// `with_heap` callers can't smuggle the heap out of the lifetime of the
/// closure callback. (I am not sure but I think it would be unsafe if you
/// could.)
#[test]
fn bug_cross_heap_edges_2() {
    let mut heap1 = with_heap(|h| *h);  // error: cannot infer an appropriate lifetime
    let mut heap2 = with_heap(|h| *h);
    let obj1 = heap1.alloc_null();
    let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
}

#[test]
fn bug_cross_heap_edges_2a() {
    with_heap(|heap1| {
        let mut heap2 = with_heap(|h| *h);  // error: cannot infer an appropriate lifetime
        let obj1 = heap1.alloc_null();
        let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
    });
}

/// Being able to swap two heap bindings would utterly break the safety
/// enforcement regime. :)
#[test]
fn bug_cross_heap_edges_3() {
    use std;
    with_heap(|mut heap1| {
        with_heap(|mut heap2| {
            let obj1 = heap1.alloc_null();
            std::mem::swap(&mut heap1, &mut heap2);  // error: mismatched types ... (lifetime mismatch)
            let obj2 = heap1.alloc((Value::Null, Value::Pair(obj1)));
        });
    });
}

#[test]
fn bug_heap_dropping() {
    // Check that Rust does not let us drop the heap while references into it
    // still exist (they would be dangling pointers). The first iteration of
    // `with_heap` passed the heap to the callback by value, and thus was
    // susceptible to this bug! It caused:
    //
    //     thread panicked while panicking. aborting.
    //
    // The fix was to pass the heap to the closure by reference.
    //
    with_heap(|heap| {
        let obj = alloc_null_pair(heap);

        // note: dropping `heap` would just drop the reference, which is no problem
        ::std::mem::drop(*heap);  // error: cannot move out of borrowed content

        let val = Value::Pair(obj.clone());
        obj.set_head(val); // occurs after the heap is gone
    });
}

#[test]
fn bug_outliving_1() {
    let obj = with_heap(|heap| {
        alloc_null_pair(heap)  // error: cannot infer an appropriate lifetime
    });

    let val = Value::Pair(obj.clone());
    obj.set_head(val);  // occurs after the heap is gone
}

#[test]
fn bug_outliving_2() {
    let obj;
    with_heap(|heap| {
        obj = alloc_null_pair(heap);  // error: cannot infer an appropriate lifetime
    });

    let val = Value::Pair(obj.clone());
    obj.set_head(val);  // occurs after the heap is gone
}

*/

<commit_msg>Rename `Pair -> GCRefPair` and `PairFields -> Pair`, in hopes of fixing the horrible naming throughout.<commit_after>use std::rc::Rc;
use super::*;

gc_ref_type! {
    pub struct GCRefPair / Pair / PairStorage<'a> {
        head / set_head: Value<'a>,
        tail / set_tail: Value<'a>
    }
}

gc_inline_enum! {
    pub enum Value / ValueStorage <'a> {
        Null,
        Int(i32),
        Str(Rc<String>),  // <-- equality is by value
        Pair(GCRefPair<'a>)  // <-- equality is by pointer
    }
}

/// Helper function to avoid having to write out `Pair` literals all over the place.
fn alloc_pair<'a>(heap: &mut Heap<'a>, head: Value<'a>, tail: Value<'a>) -> GCRefPair<'a> {
    heap.alloc(Pair { head: head, tail: tail })
}

/// Allocate a pair with the values `(null, null)`.
fn alloc_null_pair<'a>(heap: &mut Heap<'a>) -> GCRefPair<'a> {
    alloc_pair(heap, Value::Null, Value::Null)
}

/// Test that a Heap can at least allocate two objects.
#[test]
fn can_allocate_twice() {
    with_heap(|heap| {
        let obj1 = alloc_pair(heap, Value::Int(1), Value::Null);
        let obj2 = alloc_pair(heap, Value::Int(2), Value::Null);
        assert_eq!(obj1.head(), Value::Int(1));
        assert_eq!(obj2.head(), Value::Int(2));
    });
}

/// Test that rooted objects are not collected and reused.
#[test]
fn root_is_not_recycled() {
    with_heap(|heap| {
        // Create and root one object.
        let root = alloc_pair(heap, Value::Int(1), Value::Str(Rc::new("hello world".to_string())));

        // Subsequent allocations never return root.
        for _ in 0 .. HEAP_SIZE * 2 {
            let tmp = alloc_null_pair(heap);
            assert!(tmp != root);
        }
    });
}

fn null_pair<'a>() -> Pair<'a> {
    Pair { head: Value::Null, tail: Value::Null }
}

/// Test try_alloc()'s behavior when the heap is full and every Object is
/// reachable.
#[test]
fn full_heap() {
    with_heap(|heap| {
        // Fill up the heap by allocating HEAP_SIZE objects.
        let mut v = Value::Null;
        for _ in 0 .. HEAP_SIZE {
            v = Value::Pair(alloc_pair(heap, Value::Null, v));
        }

        // The whole heap is reachable.  Now try_alloc() should return null every
        // time it's called.
        for _ in 0 .. 4 {
            let attempt: Option<GCRefPair> = heap.try_alloc(null_pair());
            assert_eq!(attempt, None);
        }
    });
}

/// Test allocate()'s behavior when the heap is only almost full.
#[test]
fn nearly_full_heap() {
    with_heap(|heap| {
        // Make the heap nearly full by allocating (HEAP_SIZE - 1) objects.
        let mut v = Value::Null;
        for _ in 0 .. HEAP_SIZE - 1 {
            v = Value::Pair(alloc_pair(heap, Value::Null, v));
        }

        // Now the entire heap is reachable except for one Object.  We should
        // be able to call allocate() successfully, repeatedly.  It returns
        // that one object every time it's called!
        let last = alloc_null_pair(heap).address();
        for _ in 0 .. 10 {
            assert_eq!(alloc_null_pair(heap).address(), last);
        }
    });
}

/// Test that objects reachable from a root's `.head` or `.tail` are not
/// collected.
#[test]
fn reachable_objects_not_collected() {
    with_heap(|heap| {
        let obj1 = alloc_null_pair(heap);
        let (p2, p3, p4, p5);
        {
            let obj2 = alloc_null_pair(heap);
            p2 = obj2.address();
            obj1.set_head(Value::Pair(obj2.clone()));
            let obj3 = alloc_null_pair(heap);
            p3 = obj3.address();
            obj1.set_tail(Value::Pair(obj3));
            let obj4 = alloc_null_pair(heap);
            p4 = obj4.address();
            obj2.set_head(Value::Pair(obj4));
            let obj5 = alloc_null_pair(heap);
            p5 = obj5.address();
            obj2.set_tail(Value::Pair(obj5));
        }

        heap.force_gc();

        let h = match obj1.head() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head")
        };
        assert_eq!(h.address(), p2);

        let t = match obj1.tail() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.tail")
        };
        assert_eq!(t.address(), p3);

        let hh = match h.head() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head.head")
        };
        assert_eq!(hh.address(), p4);

        let ht = match h.tail() {
            Value::Pair(p) => p,
            _ => panic!("expected pair in obj1.head.tail")
        };
        assert_eq!(ht.address(), p5);
    });
}

/// Test that the GC is not confused by an object that contains pointers to
/// itself.
#[test]
fn root_self_references() {
    with_heap(|heap| {
        // Create a root object that contains pointers to itself.
        let root = alloc_null_pair(heap);
        root.set_head(Value::Pair(root.clone()));
        root.set_tail(Value::Pair(root.clone()));

        heap.force_gc();

        // After GC, the root object should be unchanged.
        assert_eq!(root.head(), Value::Pair(root.clone()));
        assert_eq!(root.tail(), Value::Pair(root.clone()));
    });
}

/// Test that the GC is not confused by cycles in the reachable object graph.
#[test]
fn test_root_cycle() {
    with_heap(|heap| {
        // Set up obj1 and obj2 to point to each other.
        let obj1 = alloc_null_pair(heap);
        let obj2 = alloc_pair(heap,
                              Value::Pair(obj1.clone()),
                              Value::Pair(obj1.clone()));  // obj2 points to obj1
        obj1.set_head(Value::Pair(obj2.clone()));  // and vice versa
        obj1.set_tail(Value::Pair(obj2.clone()));

        heap.force_gc();

        // After GC, the two objects are unchanged.
        assert_eq!(obj1.head(), Value::Pair(obj2.clone()));
        assert_eq!(obj1.tail(), Value::Pair(obj2.clone()));
        assert_eq!(obj2.head(), Value::Pair(obj1.clone()));
        assert_eq!(obj2.tail(), Value::Pair(obj1.clone()));
    });
}

/// Test that the GC is not confused by cycles that are garbage.
#[test]
fn unreachable_cycle() {
    with_heap(|heap| {
        // Make a cycle.
        let (p1, p2);
        {
            let obj1 = alloc_null_pair(heap);
            p1 = obj1.address();
            let obj2 = alloc_null_pair(heap);
            p2 = obj2.address();
            obj2.set_tail(Value::Pair(obj1.clone()));
            obj1.set_tail(Value::Pair(obj2.clone()));
        }  // Make the cycle unreachable.

        // Allocation should eventually recycle both objects.
        let mut recycled1 = 0;
        let mut recycled2 = 0;
        let mut root = Value::Null;
        for _ in 0 .. HEAP_SIZE {
            let p = alloc_pair(heap, Value::Null, root);
            root = Value::Pair(p.clone());
            if p.address() == p1 {
                recycled1 += 1;
            }
            if p.address() == p2 {
                recycled2 += 1;
            }
        }
        assert_eq!(recycled1, 1);
        assert_eq!(recycled2, 1);
    });
}

// Tests that you can't share values across separate heaps. Amazingly,
// Rust enforces this rule at compile time; unfortunately, I don't fully
// understand *all* the parts of the enforcement mechanism, so it's worth
// testing.
//
// Try uncommenting the tests below: if any of them compile successfully,
// consider it a test failure!
/*

/// The most obvious case: you can't just straight-up pass an object from
/// one heap to another heap's `alloc` method.
#[test]
fn bug_cross_heap_edges_1() {
    with_heap(|heap1| {
        with_heap(|heap2| {
            let obj1 = heap1.alloc_null();  // error: cannot infer an appropriate lifetime
            let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
        });
    });
}

/// `with_heap` callers can't smuggle the heap out of the lifetime of the
/// closure callback. (I am not sure but I think it would be unsafe if you
/// could.)
#[test]
fn bug_cross_heap_edges_2() {
    let mut heap1 = with_heap(|h| *h);  // error: cannot infer an appropriate lifetime
    let mut heap2 = with_heap(|h| *h);
    let obj1 = heap1.alloc_null();
    let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
}

#[test]
fn bug_cross_heap_edges_2a() {
    with_heap(|heap1| {
        let mut heap2 = with_heap(|h| *h);  // error: cannot infer an appropriate lifetime
        let obj1 = heap1.alloc_null();
        let obj2 = heap2.alloc((Value::Null, Value::Pair(obj1)));
    });
}

/// Being able to swap two heap bindings would utterly break the safety
/// enforcement regime. :)
#[test]
fn bug_cross_heap_edges_3() {
    use std;
    with_heap(|mut heap1| {
        with_heap(|mut heap2| {
            let obj1 = heap1.alloc_null();
            std::mem::swap(&mut heap1, &mut heap2);  // error: mismatched types ... (lifetime mismatch)
            let obj2 = heap1.alloc((Value::Null, Value::Pair(obj1)));
        });
    });
}

#[test]
fn bug_heap_dropping() {
    // Check that Rust does not let us drop the heap while references into it
    // still exist (they would be dangling pointers). The first iteration of
    // `with_heap` passed the heap to the callback by value, and thus was
    // susceptible to this bug! It caused:
    //
    //     thread panicked while panicking. aborting.
    //
    // The fix was to pass the heap to the closure by reference.
    //
    with_heap(|heap| {
        let obj = alloc_null_pair(heap);

        // note: dropping `heap` would just drop the reference, which is no problem
        ::std::mem::drop(*heap);  // error: cannot move out of borrowed content

        let val = Value::Pair(obj.clone());
        obj.set_head(val); // occurs after the heap is gone
    });
}

#[test]
fn bug_outliving_1() {
    let obj = with_heap(|heap| {
        alloc_null_pair(heap)  // error: cannot infer an appropriate lifetime
    });

    let val = Value::Pair(obj.clone());
    obj.set_head(val);  // occurs after the heap is gone
}

#[test]
fn bug_outliving_2() {
    let obj;
    with_heap(|heap| {
        obj = alloc_null_pair(heap);  // error: cannot infer an appropriate lifetime
    });

    let val = Value::Pair(obj.clone());
    obj.set_head(val);  // occurs after the heap is gone
}

*/

<|endoftext|>


<commit_before>
//! A basic std::sync front;
//!
//! When compiled with feature="spin" we will include as many of the sync primitives as we can
//! using only atomic spin lock style implementations.
//!
//! Note we can only provide Mutex and Once in this case.

pub use core::atomic;
pub use alloc::arc::{Arc, Weak};
#[cfg(feature="spin")] pub use self::spin::*;
#[cfg(feature="spin")] pub use self::poison::*;

#[cfg(feature="spin")] #[path="../rust/src/libstd/sync/poison.rs"] mod poison;
#[cfg(feature="spin")] mod spin {
    use super::atomic::{AtomicBool, AtomicUsize, ATOMIC_USIZE_INIT};
    use super::atomic::Ordering::SeqCst;
    use cell::*;
    use super::poison::*;
    use mem::transmute;
    use ops::{Deref, DerefMut};
    use prelude::v1::*;

    pub struct MutexGuard<'a, T: 'a> { __mtx : &'a Mutex<T>, }
    impl<'a, T: 'a> !Send for MutexGuard<'a, T> {}

    impl<'m, T> DerefMut for MutexGuard<'m, T> {
        fn deref_mut<'a>(&'a mut self) -> &'a mut T {
            unsafe { transmute(self.__mtx.val.get()) }
        }
    }

    impl<'m, T> Deref for MutexGuard<'m, T> {
        type Target = T;
        fn deref<'a>(&'a self) -> &'a T {
            unsafe { transmute(self.__mtx.val.get()) }
        }
    }

    #[unsafe_destructor]
    impl<'a, T: 'a> Drop for MutexGuard<'a, T> {
        fn drop(&mut self) { self.__mtx.locked.swap(false, SeqCst); }
    }

    pub struct Mutex<T> {
        locked: AtomicBool,
        val: UnsafeCell<T>,
    }

    unsafe impl<T: Send> Send for Mutex<T> {}
    unsafe impl<T: Send> Sync for Mutex<T> {}

    impl<T: Send> Mutex<T> {
        /// See std::sync::Mutex::new
        pub fn new(t: T) -> Mutex<T> {
            Mutex { locked: AtomicBool::new(false), val: UnsafeCell::new(t) }
        }
        pub fn lock(&self) -> LockResult<MutexGuard<T>> {
            while self.locked.compare_and_swap(false, true, SeqCst) { }
            Ok(MutexGuard { __mtx: self })
        }
        pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
            if self.locked.compare_and_swap(false, true, SeqCst) {
                Err(TryLockError::WouldBlock)
            } else {
                Ok(MutexGuard { __mtx: self })
            }
        }
    }

    /// We have never been called yet.
    const UNUSED       : usize = 0;
    /// We are currently running some initialization function
    const INITIALIZING : usize = 1;
    /// We have finished initializing.
    const INITIALIZED  : usize = 2;

    /// A once implementation that will have other threads spin when the initialization is being done.
    /// Use only with extreeme caution. Prefer procs::sync::Once if possible.
    pub struct Once {
        /// What the current state is.
        state: AtomicUsize,
    }

    pub const ONCE_INIT : Once = Once {
        state: ATOMIC_USIZE_INIT,
    };

    impl Once {
        /// Perform an initialization routine once and only once. The given closure will be executed if
        /// this is the first time `try_it` has been called, and otherwise the routine will *not* be
        /// invoked.
        ///
        /// This method will spin until at least one initialization routine has been completed.
        ///
        /// Returns true if the function given was executed, false otherwise.
        pub fn try_it<F>(&self, f: F) -> bool where F: Fn() {
            if self.state.load(SeqCst) == INITIALIZED {
                false
            } else if self.state.compare_and_swap(UNUSED, INITIALIZING, SeqCst) == UNUSED {
                // We are the ones who won the race.
                f();
                self.state.store(INITIALIZED, SeqCst);
                true
            } else if self.state.load(SeqCst) == INITIALIZED { false } else {
                while self.state.load(SeqCst) != INITIALIZED { }
                false
            }
        }

        /// Perform an initialization routine once and only once. The given closure will be executed if
        /// this is the first time `doit` has been called, and otherwise the routine will *not* be
        /// invoked.
        ///
        /// This method will block the calling task if another initialization routine is currently
        /// running.
        ///
        /// When this function returns, it is guaranteed that some initialization has run and completed
        /// (it may not be the closure specified).
        #[inline]
        pub fn doit<F>(&self, f: F) where F: Fn() { self.try_it(f); }
    }
}
<commit_msg>removed another reenix comment<commit_after>
//! A basic std::sync front;
//!
//! When compiled with feature="spin" we will include as many of the sync primitives as we can
//! using only atomic spin lock style implementations.
//!
//! Note we can only provide Mutex and Once in this case.

pub use core::atomic;
pub use alloc::arc::{Arc, Weak};
#[cfg(feature="spin")] pub use self::spin::*;
#[cfg(feature="spin")] pub use self::poison::*;

#[cfg(feature="spin")] #[path="../rust/src/libstd/sync/poison.rs"] mod poison;
#[cfg(feature="spin")] mod spin {
    use super::atomic::{AtomicBool, AtomicUsize, ATOMIC_USIZE_INIT};
    use super::atomic::Ordering::SeqCst;
    use cell::*;
    use super::poison::*;
    use mem::transmute;
    use ops::{Deref, DerefMut};
    use prelude::v1::*;

    pub struct MutexGuard<'a, T: 'a> { __mtx : &'a Mutex<T>, }
    impl<'a, T: 'a> !Send for MutexGuard<'a, T> {}

    impl<'m, T> DerefMut for MutexGuard<'m, T> {
        fn deref_mut<'a>(&'a mut self) -> &'a mut T {
            unsafe { transmute(self.__mtx.val.get()) }
        }
    }

    impl<'m, T> Deref for MutexGuard<'m, T> {
        type Target = T;
        fn deref<'a>(&'a self) -> &'a T {
            unsafe { transmute(self.__mtx.val.get()) }
        }
    }

    #[unsafe_destructor]
    impl<'a, T: 'a> Drop for MutexGuard<'a, T> {
        fn drop(&mut self) { self.__mtx.locked.swap(false, SeqCst); }
    }

    pub struct Mutex<T> {
        locked: AtomicBool,
        val: UnsafeCell<T>,
    }

    unsafe impl<T: Send> Send for Mutex<T> {}
    unsafe impl<T: Send> Sync for Mutex<T> {}

    impl<T: Send> Mutex<T> {
        /// See std::sync::Mutex::new
        pub fn new(t: T) -> Mutex<T> {
            Mutex { locked: AtomicBool::new(false), val: UnsafeCell::new(t) }
        }
        pub fn lock(&self) -> LockResult<MutexGuard<T>> {
            while self.locked.compare_and_swap(false, true, SeqCst) { }
            Ok(MutexGuard { __mtx: self })
        }
        pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
            if self.locked.compare_and_swap(false, true, SeqCst) {
                Err(TryLockError::WouldBlock)
            } else {
                Ok(MutexGuard { __mtx: self })
            }
        }
    }

    /// We have never been called yet.
    const UNUSED       : usize = 0;
    /// We are currently running some initialization function
    const INITIALIZING : usize = 1;
    /// We have finished initializing.
    const INITIALIZED  : usize = 2;

    /// A once implementation that will have other threads spin when the initialization is being done.
    /// Use only with extreme caution.
    pub struct Once {
        /// What the current state is.
        state: AtomicUsize,
    }

    pub const ONCE_INIT : Once = Once {
        state: ATOMIC_USIZE_INIT,
    };

    impl Once {
        /// Perform an initialization routine once and only once. The given closure will be executed if
        /// this is the first time `try_it` has been called, and otherwise the routine will *not* be
        /// invoked.
        ///
        /// This method will spin until at least one initialization routine has been completed.
        ///
        /// Returns true if the function given was executed, false otherwise.
        pub fn try_it<F>(&self, f: F) -> bool where F: Fn() {
            if self.state.load(SeqCst) == INITIALIZED {
                false
            } else if self.state.compare_and_swap(UNUSED, INITIALIZING, SeqCst) == UNUSED {
                // We are the ones who won the race.
                f();
                self.state.store(INITIALIZED, SeqCst);
                true
            } else {
                while self.state.load(SeqCst) != INITIALIZED { }
                false
            }
        }

        /// Perform an initialization routine once and only once. The given closure will be executed if
        /// this is the first time `doit` has been called, and otherwise the routine will *not* be
        /// invoked.
        ///
        /// This method will block the calling task if another initialization routine is currently
        /// running.
        ///
        /// When this function returns, it is guaranteed that some initialization has run and completed
        /// (it may not be the closure specified).
        #[inline]
        pub fn doit<F>(&self, f: F) where F: Fn() { self.try_it(f); }
    }
}
<|endoftext|>


<commit_before>use urlparse::{GetQuery, urlparse, urlunparse};

/// Strip tracking junk and URL suffixes.
pub fn tidy_url(url: String) -> String {
    let mut parsed_url = urlparse(url);

    // Always get the desktop version of Twitter URLs
    if parsed_url.netloc == "mobile.twitter.com" {
        parsed_url.netloc = String::from("twitter.com");
    }

    // Remove any tracking junk from Amazon URLs so they're not a
    // ridiculous length
    if parsed_url.netloc == "www.amazon.co.uk" {
        parsed_url.query = None;
        let mut new_path = String::from("");
        for component in parsed_url.path.split("ref=") {
            new_path = String::from(component);
            break;
        }
        parsed_url.path = new_path;
    }

    // Strip tracking junk from Medium, Mashable and Buzzfeed
    if (parsed_url.netloc == "medium.com") ||
       (parsed_url.netloc == "www.buzzfeed.com") ||
       (parsed_url.netloc == "mashable.com") {
            parsed_url.fragment = None;
    }

    // Remove '#notes' from Tumblr URLs
    if parsed_url.netloc.ends_with("tumblr.com") {
        let new_fragment: Option<String> = match parsed_url.fragment {
            Some(fragment) => {
                if fragment == "notes" {
                    None
                } else {
                    Some(fragment)
                }
            }
            None => None,
        };
        parsed_url.fragment = new_fragment;
    }

    // Remove &feature=youtu.be from YouTube URLs
    // TODO: What does this do with the timestamp URL fragment?
    if parsed_url.netloc.ends_with("youtube.com") {
        let query = parsed_url.get_parsed_query().unwrap();
        let video_id = query.get_first_from_str("v").unwrap();
        parsed_url.query = Some(String::from("v=".to_string() + &video_id));
    }

    urlunparse(parsed_url)
}

macro_rules! tidy_url_tests {
    ($($name:ident: $value:expr,)*) => {
    $(
        #[test]
        fn $name() {
            let (input, expected) = $value;
            assert_eq!(expected, tidy_url(String::from(input)));
        }
    )*
    }
}

tidy_url_tests! {
    url_tw_0:  ("https://mobile.twitter.com/Breaking911/status/822589852596191235",
                "https://twitter.com/Breaking911/status/822589852596191235"),
    url_tw_1:  ("https://twitter.com/elise3aum/status/822903824268533762",
                "https://twitter.com/elise3aum/status/822903824268533762"),

    url_az_0:  ("https://www.amazon.co.uk/dp/B01DFKBL68/ref=gw_aucc_comb_AB_clean_2?pf_rd_r=N1MF2PWADRHS55427ETG&pf_rd_p=c11a2c11-c670-46ff-87a1-c1eef4fad652",
                "https://www.amazon.co.uk/dp/B01DFKBL68/"),

    url_md_0:  ("https://medium.com/@anildash/forget-why-its-time-to-get-to-work-c49ac5f0da20#.sjyskxdsz",
                "https://medium.com/@anildash/forget-why-its-time-to-get-to-work-c49ac5f0da20"),

    url_yt_0:  ("https://www.youtube.com/watch?v=tJkEV3fvQUU",
                "https://www.youtube.com/watch?v=tJkEV3fvQUU"),
    url_yt_1:  ("https://www.youtube.com/watch?v=I4LVAu0pxHc&feature=youtu.be",
                "https://www.youtube.com/watch?v=I4LVAu0pxHc"),

    url_tm_0:  ("http://azurelunatic.tumblr.com/post/155525051123/things-about-hufflepuffs-539#notes",
                "http://azurelunatic.tumblr.com/post/155525051123/things-about-hufflepuffs-539"),

    url_8:   ("https://www.buzzfeed.com/katienotopoulos/the-end-of-apple-man#.biqmkzz8kn",
              "https://www.buzzfeed.com/katienotopoulos/the-end-of-apple-man"),
    url_9:   ("http://mashable.com/2016/03/21/apple-liam-recycling-robot/#b9y4lv3m4qqX",
              "http://mashable.com/2016/03/21/apple-liam-recycling-robot/"),
}
<commit_msg>Make sure YouTube URLs without a ?v= parameter don't panic<commit_after>use urlparse::{urlparse, urlunparse};

/// Strip tracking junk and URL suffixes.
pub fn tidy_url(url: String) -> String {
    let mut parsed_url = urlparse(url);

    // Always get the desktop version of Twitter URLs
    if parsed_url.netloc == "mobile.twitter.com" {
        parsed_url.netloc = String::from("twitter.com");
    }

    // Remove any tracking junk from Amazon URLs so they're not a
    // ridiculous length
    if parsed_url.netloc == "www.amazon.co.uk" {
        parsed_url.query = None;
        let mut new_path = String::from("");
        for component in parsed_url.path.split("ref=") {
            new_path = String::from(component);
            break;
        }
        parsed_url.path = new_path;
    }

    // Strip tracking junk from Medium, Mashable and Buzzfeed
    if (parsed_url.netloc == "medium.com") ||
       (parsed_url.netloc == "www.buzzfeed.com") ||
       (parsed_url.netloc == "mashable.com") {
            parsed_url.fragment = None;
    }

    // Remove '#notes' from Tumblr URLs
    if parsed_url.netloc.ends_with("tumblr.com") {
        let new_fragment: Option<String> = match parsed_url.fragment {
            Some(fragment) => {
                if fragment == "notes" {
                    None
                } else {
                    Some(fragment)
                }
            }
            None => None,
        };
        parsed_url.fragment = new_fragment;
    }

  // Remove &feature=youtu.be from YouTube URLs
  if parsed_url.netloc.ends_with("youtube.com") {
    parsed_url.query = match parsed_url.query {
      Some(q) => {
        let new_q = q
          .replace("&feature=youtu.be", "")
          .replace("feature=youtu.be&", "")
          .replace("feature=youtu.be", "");
        if new_q != "" {
          Some(new_q)
        } else {
          None
        }
      },
      None => None,
    };
  }

  urlunparse(parsed_url)
}

macro_rules! tidy_url_tests {
    ($($name:ident: $value:expr,)*) => {
    $(
        #[test]
        fn $name() {
            let (input, expected) = $value;
            assert_eq!(expected, tidy_url(String::from(input)));
        }
    )*
    }
}

tidy_url_tests! {
    url_tw_0:  ("https://mobile.twitter.com/Breaking911/status/822589852596191235",
                "https://twitter.com/Breaking911/status/822589852596191235"),
    url_tw_1:  ("https://twitter.com/elise3aum/status/822903824268533762",
                "https://twitter.com/elise3aum/status/822903824268533762"),

    url_az_0:  ("https://www.amazon.co.uk/dp/B01DFKBL68/ref=gw_aucc_comb_AB_clean_2?pf_rd_r=N1MF2PWADRHS55427ETG&pf_rd_p=c11a2c11-c670-46ff-87a1-c1eef4fad652",
                "https://www.amazon.co.uk/dp/B01DFKBL68/"),

    url_md_0:  ("https://medium.com/@anildash/forget-why-its-time-to-get-to-work-c49ac5f0da20#.sjyskxdsz",
                "https://medium.com/@anildash/forget-why-its-time-to-get-to-work-c49ac5f0da20"),

    url_tm_0:  ("http://azurelunatic.tumblr.com/post/155525051123/things-about-hufflepuffs-539#notes",
                "http://azurelunatic.tumblr.com/post/155525051123/things-about-hufflepuffs-539"),

    url_8:   ("https://www.buzzfeed.com/katienotopoulos/the-end-of-apple-man#.biqmkzz8kn",
              "https://www.buzzfeed.com/katienotopoulos/the-end-of-apple-man"),
    url_9:   ("http://mashable.com/2016/03/21/apple-liam-recycling-robot/#b9y4lv3m4qqX",
              "http://mashable.com/2016/03/21/apple-liam-recycling-robot/"),

  youtube_plain_video: (
    "https://www.youtube.com/watch?v=zB4I68XVPzQ",
    "https://www.youtube.com/watch?v=zB4I68XVPzQ",
  ),

  youtube_with_timestamp: (
    "https://www.youtube.com/watch?v=D68cUzqcTrg&feature=youtu.be#t=1m",
    "https://www.youtube.com/watch?v=D68cUzqcTrg#t=1m",
  ),

  youtube_with_trailing_feature: (
    "https://www.youtube.com/watch?v=PbJqNa0_Oz0&feature=youtu.be",
    "https://www.youtube.com/watch?v=PbJqNa0_Oz0",
  ),

  youtube_with_leading_feature: (
    "https://www.youtube.com/watch?feature=youtu.be&v=oPo4n9tBPsk",
    "https://www.youtube.com/watch?v=oPo4n9tBPsk",
  ),

  youtube_with_only_feature: (
    "https://www.youtube.com/watch?feature=youtu.be",
    "https://www.youtube.com/watch",
  ),

  youtube_channel: (
    "https://www.youtube.com/user/TheQIElves",
    "https://www.youtube.com/user/TheQIElves"
  ),
}
<|endoftext|>


<commit_before>#[allow(unused_attributes)]

use rustc_serialize::json;
use client::Client;

pub struct UserService {
    client: Client,
}

impl UserService {

    pub fn new(c: Client) -> UserService {
        UserService { client: c }
    }

    pub fn get(self, name: &str) -> User {
        let mut url = "http://api.stackexchange.com/2.2/users/2357380?site=stackoverflow".to_string();
        url.push_str(name);

        let req = self.client.request(url.as_ref());

        let user: User = json::decode(req.as_ref()).unwrap();

        return user;
    }
}

#[allow(dead_code)]
#[derive(RustcDecodable)]
pub struct User {
    pub items: String,
    pub has_more: String,
}
<commit_msg>Changed url string to immutable and removed name as a cli param<commit_after>#[allow(unused_attributes)]

use rustc_serialize::json;
use client::Client;

pub struct UserService {
    client: Client,
}

impl UserService {

    pub fn new(c: Client) -> UserService {
        UserService { client: c }
    }

    pub fn get(self) -> User {
        let url = "http://api.stackexchange.com/2.2/users/2357380?site=stackoverflow".to_string();

        let req = self.client.request(url.as_ref());

        let user: User = json::decode(req.as_ref()).unwrap();

        return user;
    }
}

#[allow(dead_code)]
#[derive(RustcDecodable)]
pub struct User {
    pub items: String,
    pub has_more: String,
}
<|endoftext|>


<commit_before>use std::ffi::{CStr, CString};
use std::ptr;

use binding::global::RubySpecialConsts;
use types::{c_char, c_int, c_void, Argc, InternalValue, Value};

use {AnyObject, Object};

pub unsafe fn cstr_to_string(str: *const c_char) -> String {
    CStr::from_ptr(str).to_string_lossy().into_owned()
}

pub unsafe fn cstr_to_str<'a>(str: *const c_char) -> &'a str {
    CStr::from_ptr(str).to_str().unwrap()
}

pub fn str_to_cstring(str: &str) -> CString {
    CString::new(str).unwrap()
}

pub fn bool_to_value(state: bool) -> Value {
    let internal_value = if state {
        RubySpecialConsts::True
    } else {
        RubySpecialConsts::False
    };

    Value::from(internal_value as InternalValue)
}

#[inline]
pub fn c_int_to_bool(int: c_int) -> bool {
    int != 0
}

#[inline]
pub fn bool_to_c_int(state: bool) -> c_int {
    state as c_int
}

pub fn arguments_to_values(arguments: Option<&[AnyObject]>) -> Option<Vec<Value>> {
    arguments.map(|arguments| {
        arguments.iter()
            .map(Object::value)
            .collect()
    })
}

pub fn process_arguments(arguments: &Option<Vec<Value>>) -> (Argc, *const Value) {
    match arguments {
        &Some(ref arguments) => (arguments.len() as Argc, arguments.as_ptr()),
        &None => (0, ptr::null()),
    }
}

pub fn closure_to_ptr<F, R>(func: F) -> *const c_void
    where F: FnOnce() -> R
{
    let wrap_return = || {
        let r = func();
        Box::into_raw(Box::new(r)) as *const c_void
    };

    let fnbox = Box::new(wrap_return) as Box<FnOnce() -> *const c_void>;

    Box::into_raw(Box::new(fnbox)) as *const c_void
}

pub unsafe fn ptr_to_data<R>(ptr: *mut c_void) -> R {
    *Box::from_raw(ptr as *mut R)
}
<commit_msg>Match arguments by values in process_arguments<commit_after>use std::ffi::{CStr, CString};
use std::ptr;

use binding::global::RubySpecialConsts;
use types::{c_char, c_int, c_void, Argc, InternalValue, Value};

use {AnyObject, Object};

pub unsafe fn cstr_to_string(str: *const c_char) -> String {
    CStr::from_ptr(str).to_string_lossy().into_owned()
}

pub unsafe fn cstr_to_str<'a>(str: *const c_char) -> &'a str {
    CStr::from_ptr(str).to_str().unwrap()
}

pub fn str_to_cstring(str: &str) -> CString {
    CString::new(str).unwrap()
}

pub fn bool_to_value(state: bool) -> Value {
    let internal_value = if state {
        RubySpecialConsts::True
    } else {
        RubySpecialConsts::False
    };

    Value::from(internal_value as InternalValue)
}

#[inline]
pub fn c_int_to_bool(int: c_int) -> bool {
    int != 0
}

#[inline]
pub fn bool_to_c_int(state: bool) -> c_int {
    state as c_int
}

pub fn arguments_to_values(arguments: Option<&[AnyObject]>) -> Option<Vec<Value>> {
    arguments.map(|arguments| {
        arguments.iter()
            .map(Object::value)
            .collect()
    })
}

pub fn process_arguments(arguments: &Option<Vec<Value>>) -> (Argc, *const Value) {
    match *arguments {
        Some(ref arguments) => (arguments.len() as Argc, arguments.as_ptr()),
        None => (0, ptr::null()),
    }
}

pub fn closure_to_ptr<F, R>(func: F) -> *const c_void
    where F: FnOnce() -> R
{
    let wrap_return = || {
        let r = func();
        Box::into_raw(Box::new(r)) as *const c_void
    };

    let fnbox = Box::new(wrap_return) as Box<FnOnce() -> *const c_void>;

    Box::into_raw(Box::new(fnbox)) as *const c_void
}

pub unsafe fn ptr_to_data<R>(ptr: *mut c_void) -> R {
    *Box::from_raw(ptr as *mut R)
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::env;
use std::fmt;
use std::io;
use std::path::MAIN_SEPARATOR;

use ansi_term::Color;
use env_logger::LogBuilder;
use log::{LogLevel, LogLevelFilter, LogRecord};
use ring::rand::{SecureRandom, SystemRandom};
use time;

use super::v3::MAX_PADDING_LEN;

struct ColorLevel(LogLevel);

impl fmt::Display for ColorLevel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            LogLevel::Trace => Color::Purple.paint("TRACE"),
            LogLevel::Debug => Color::Blue.paint("DEBUG"),
            LogLevel::Info => Color::Green.paint("INFO "),
            LogLevel::Warn => Color::Yellow.paint("WARN "),
            LogLevel::Error => Color::Red.paint("ERROR"),
        }.fmt(f)
    }
}

pub fn init_logger() {
    let format = |record: &LogRecord| {
        let now = time::now();
        let ms = now.tm_nsec / 1000 / 1000;
        let t = time::strftime("%Y-%m-%d %T", &now).unwrap();
        format!(
            "{}.{:03} [{}]  {}",
            t,
            ms,
            ColorLevel(record.level()),
            record.args()
        )
    };

    let mut builder = LogBuilder::new();
    builder.format(format).filter(None, LogLevelFilter::Info);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    if env::var("FAKIO_LOG").is_ok() {
        builder.parse(&env::var("FAKIO_LOG").unwrap());
    }

    builder.init().unwrap();
}

/// `MAX_PADDING_LEN 255`
///
/// +-------+----------+
/// |  len  |   bytes  |
/// +-------+----------+
/// | 1bytes| [0, 255] |
/// +-------+----------+
pub struct RandomBytes {
    len: usize,
    bytes: [u8; 1 + MAX_PADDING_LEN],
}

impl RandomBytes {
    pub fn new() -> io::Result<RandomBytes> {
        let mut padding = [0u8; 1 + MAX_PADDING_LEN];
        let rand = SystemRandom::new();

        // 1. rand len
        rand.fill(&mut padding[..1])
            .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("rand failed by {}", e)))?;

        // 2. rand data
        let len = padding[0] as usize;
        rand.fill(&mut padding[1..len + 1])
            .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("rand failed by {}", e)))?;
        Ok(RandomBytes {
            len: len,
            bytes: padding,
        })
    }

    #[inline]
    pub fn get(&self) -> &[u8] {
        &self.bytes[..self.len + 1]
    }
}

static CHARS: &'static [u8] = b"0123456789abcdef";

pub fn to_hex(slice: &[u8]) -> String {
    let mut v = Vec::with_capacity(slice.len() * 2);
    for &byte in slice.iter() {
        v.push(CHARS[(byte >> 4) as usize]);
        v.push(CHARS[(byte & 0xf) as usize]);
    }

    unsafe { String::from_utf8_unchecked(v) }
}

/// Expand path like ~/xxx
pub fn expand_tilde_path(path: &str) -> Cow<str> {
    if !path.starts_with('~') {
        return path.into();
    }

    let path_after_tilde = &path[1..];

    // on support windows `\`
    if path_after_tilde.is_empty() || path_after_tilde.starts_with('/')
        || path_after_tilde.starts_with(MAIN_SEPARATOR)
    {
        if let Some(hd) = env::home_dir() {
            let result = format!("{}{}", hd.display(), path_after_tilde);
            result.into()
        } else {
            // home dir is not available
            path.into()
        }
    } else {
        // we cannot handle `~otheruser/` paths yet
        path.into()
    }
}

#[cfg(test)]
mod test {
    use std::env;
    use std::io::ErrorKind;

    #[test]
    fn test_random_bytes() {
        match super::RandomBytes::new() {
            Ok(r) => {
                let bytes = r.get();
                let size = bytes[0] as usize;
                assert_eq!(size + 1, bytes.len());
            }
            Err(e) => assert_eq!(e.kind(), ErrorKind::Other),
        }
    }

    #[test]
    fn test_expand_tilde_path() {
        let old_home = env::var("HOME").ok();
        env::set_var("HOME", "/home/morty");

        assert_eq!("/home/morty", super::expand_tilde_path("~"));
        assert_eq!("/home/morty/rick", super::expand_tilde_path("~/rick"));
        assert_eq!("~rick", super::expand_tilde_path("~rick"));
        assert_eq!("/home", super::expand_tilde_path("/home"));

        if cfg!(windows) {
            env::set_var("HOME", r"C:\Users\Morty");
            assert_eq!(
                r"C:\Users\Morty\rick.txt",
                super::expand_tilde_path(r"~\rick")
            );
        }

        if let Some(old) = old_home {
            env::set_var("HOME", old);
        }
    }
}
<commit_msg>fix test_expand_tilde_path<commit_after>use std::borrow::Cow;
use std::env;
use std::fmt;
use std::io;
use std::path::MAIN_SEPARATOR;

use ansi_term::Color;
use env_logger::LogBuilder;
use log::{LogLevel, LogLevelFilter, LogRecord};
use ring::rand::{SecureRandom, SystemRandom};
use time;

use super::v3::MAX_PADDING_LEN;

struct ColorLevel(LogLevel);

impl fmt::Display for ColorLevel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            LogLevel::Trace => Color::Purple.paint("TRACE"),
            LogLevel::Debug => Color::Blue.paint("DEBUG"),
            LogLevel::Info => Color::Green.paint("INFO "),
            LogLevel::Warn => Color::Yellow.paint("WARN "),
            LogLevel::Error => Color::Red.paint("ERROR"),
        }.fmt(f)
    }
}

pub fn init_logger() {
    let format = |record: &LogRecord| {
        let now = time::now();
        let ms = now.tm_nsec / 1000 / 1000;
        let t = time::strftime("%Y-%m-%d %T", &now).unwrap();
        format!(
            "{}.{:03} [{}]  {}",
            t,
            ms,
            ColorLevel(record.level()),
            record.args()
        )
    };

    let mut builder = LogBuilder::new();
    builder.format(format).filter(None, LogLevelFilter::Info);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    if env::var("FAKIO_LOG").is_ok() {
        builder.parse(&env::var("FAKIO_LOG").unwrap());
    }

    builder.init().unwrap();
}

/// `MAX_PADDING_LEN 255`
///
/// +-------+----------+
/// |  len  |   bytes  |
/// +-------+----------+
/// | 1bytes| [0, 255] |
/// +-------+----------+
pub struct RandomBytes {
    len: usize,
    bytes: [u8; 1 + MAX_PADDING_LEN],
}

impl RandomBytes {
    pub fn new() -> io::Result<RandomBytes> {
        let mut padding = [0u8; 1 + MAX_PADDING_LEN];
        let rand = SystemRandom::new();

        // 1. rand len
        rand.fill(&mut padding[..1])
            .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("rand failed by {}", e)))?;

        // 2. rand data
        let len = padding[0] as usize;
        rand.fill(&mut padding[1..len + 1])
            .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("rand failed by {}", e)))?;
        Ok(RandomBytes {
            len: len,
            bytes: padding,
        })
    }

    #[inline]
    pub fn get(&self) -> &[u8] {
        &self.bytes[..self.len + 1]
    }
}

static CHARS: &'static [u8] = b"0123456789abcdef";

pub fn to_hex(slice: &[u8]) -> String {
    let mut v = Vec::with_capacity(slice.len() * 2);
    for &byte in slice.iter() {
        v.push(CHARS[(byte >> 4) as usize]);
        v.push(CHARS[(byte & 0xf) as usize]);
    }

    unsafe { String::from_utf8_unchecked(v) }
}

/// Expand path like ~/xxx
pub fn expand_tilde_path(path: &str) -> Cow<str> {
    if !path.starts_with('~') {
        return path.into();
    }

    let path_after_tilde = &path[1..];

    // on support windows `\`
    if path_after_tilde.is_empty() || path_after_tilde.starts_with('/')
        || path_after_tilde.starts_with(MAIN_SEPARATOR)
    {
        if let Some(hd) = env::home_dir() {
            let result = format!("{}{}", hd.display(), path_after_tilde);
            result.into()
        } else {
            // home dir is not available
            path.into()
        }
    } else {
        // we cannot handle `~otheruser/` paths yet
        path.into()
    }
}

#[cfg(test)]
mod test {
    use std::env;
    use std::io::ErrorKind;

    #[test]
    fn test_random_bytes() {
        match super::RandomBytes::new() {
            Ok(r) => {
                let bytes = r.get();
                let size = bytes[0] as usize;
                assert_eq!(size + 1, bytes.len());
            }
            Err(e) => assert_eq!(e.kind(), ErrorKind::Other),
        }
    }

    #[test]
    fn test_expand_tilde_path() {
        let old_home = env::var("HOME").ok();
        env::set_var("HOME", "/home/morty");

        assert_eq!("/home/morty", super::expand_tilde_path("~"));
        assert_eq!("/home/morty/rick", super::expand_tilde_path("~/rick"));
        assert_eq!("~rick", super::expand_tilde_path("~rick"));
        assert_eq!("/home", super::expand_tilde_path("/home"));

        if cfg!(windows) {
            env::set_var("HOME", r"C:\Users\Morty");
            assert_eq!(
                r"C:\Users\Morty\rick.txt",
                super::expand_tilde_path(r"~\rick.txt")
            );
        }

        if let Some(old) = old_home {
            env::set_var("HOME", old);
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

pub fn identifier_to_tag_name<'a, T>(s: T) -> Cow<'a, str>
    where T: Into<Cow<'a, str>>
{
    let mut owned: Option<String> = None;
    let s = s.into();
    {
        let bs: &str = s.as_ref();
        for (i, c) in bs.chars().enumerate() {
            match c {
                c @ 'A' ... 'Z' => {
                    let mut os = owned.unwrap_or({
                        let mut os = String::with_capacity(bs.len() + 4);
                        os.extend((&bs[..i]).chars());
                        os
                    });
                    os.push('-');
                    os.push(c.to_lowercase().next().unwrap());
                    owned = Some(os);
                }
                _ => if let Some(ref mut os) = owned {
                    os.push(c);
                }
            }
        }
    }
    owned.map(|os| os.into()).unwrap_or(s)
}
<commit_msg>Simplify identifier_to_tag_name<commit_after>use std::ascii::AsciiExt;
use std::borrow::Cow;

pub fn identifier_to_tag_name<'a, T>(s: T) -> Cow<'a, str>
    where T: Into<Cow<'a, str>>
{
    let s = s.into();
    if s.contains(|c: char| c.is_ascii() && c.is_uppercase()) {
        let mut result = String::with_capacity(s.len() + 4);
        for c in s.chars() {
            if c.is_ascii() && c.is_uppercase() {
                result.push('-');
                result.push(c.to_ascii_lowercase());
            } else {
                result.push(c);
            }
        }
        Cow::Owned(result)
    } else {
        s
    }
}
<|endoftext|>


<commit_before>pub fn get_array() {}

#[cfg(test)]
mod tests {
    #[test]
    fn test_get_array() {
        assert!(true)
    }
}
<commit_msg>feat: add workaround method for Config::get_array()<commit_after>use config::{Config, Value};

/// Gets an array from a config file using a key, returning `None` if
/// the key wasn't present or couldn't be coerced into a `Vec<Value>`.
///
/// `Config::get_array()` in version `0.4.1` has a bug where it
/// consumes `self` instead of taking `self` by reference. This
/// function is a workaround for the time being. The bug has been
/// fixed but will not be available until the release of version `0.5`
/// of `config-rs`.
pub fn ref_get_array(key: &str, config: &Config) -> Option<Vec<Value>> {
    config.get(key).and_then(Value::into_array)
}

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

    #[test]
    // The real test is that this compiles successfully without giving
    // a warning about the config file being moved.
    fn test_ref_get_array() {
        let mut c: Config = Config::new();
        c.set("numbers", vec![1, 2, 3]).unwrap();
        c.set("boolean", true).unwrap();

        // Uncomment and the compiler should complain
        // assert_eq!(c.get_array("numbers"),
        //            Some(vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)]));
        // assert_eq!(c.get_array("boolean"), None); // Use of moved value: c

        assert_eq!(ref_get_array("numbers", &c),
                   Some(vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)]));
        assert_eq!(ref_get_array("boolean", &c), None);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use list_fonts::get_font_families;

use freetype::Library;
use freetype::Face;
use freetype;

/// Rasterizes glyphs for a single font face.
pub struct Rasterizer {
    faces: HashMap<FontDesc, Face<'static>>,
    library: Library,
    system_fonts: HashMap<String, ::list_fonts::Family>,
    dpi_x: u32,
    dpi_y: u32,
    dpr: f32,
}

#[inline]
fn to_freetype_26_6(f: f32) -> isize {
    ((1i32 << 6) as f32 * f) as isize
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
    name: String,
    style: String,
}

impl FontDesc {
    pub fn new<S>(name: S, style: S) -> FontDesc
        where S: Into<String>
    {
        FontDesc {
            name: name.into(),
            style: style.into()
        }
    }
}

impl Rasterizer {
    pub fn new(dpi_x: f32, dpi_y: f32, device_pixel_ratio: f32) -> Rasterizer {
        let library = Library::init().unwrap();

        Rasterizer {
            system_fonts: get_font_families(),
            faces: HashMap::new(),
            library: library,
            dpi_x: dpi_x as u32,
            dpi_y: dpi_y as u32,
            dpr: device_pixel_ratio,
        }
    }

    pub fn box_size_for_font(&mut self, desc: &FontDesc, size: f32) -> (u32, u32) {
        let face = self.get_face(&desc).unwrap();

        let scale_size = self.dpr * size;

        let em_size = face.em_size() as f32;
        let w = face.max_advance_width() as f32;
        let h = face.height() as f32;

        let w_scale = w / em_size;
        let h_scale = h / em_size;

        ((w_scale * scale_size) as u32, (h_scale * scale_size) as u32)
    }

    pub fn get_face(&mut self, desc: &FontDesc) -> Option<Face<'static>> {
        if let Some(face) = self.faces.get(desc) {
            return Some(face.clone());
        }

        if let Some(font) = self.system_fonts.get(&desc.name[..]) {
            if let Some(variant) = font.variants().get(&desc.style[..]) {
                let face = self.library.new_face(variant.path(), variant.index())
                                       .expect("TODO handle new_face error");

                self.faces.insert(desc.to_owned(), face);
                return Some(self.faces.get(desc).unwrap().clone());
            }
        }

        None
    }

    pub fn get_glyph(&mut self, desc: &FontDesc, size: f32, c: char) -> RasterizedGlyph {
        let face = self.get_face(desc).expect("TODO handle get_face error");
        face.set_char_size(to_freetype_26_6(size * self.dpr), 0, self.dpi_x, self.dpi_y).unwrap();
        face.load_char(c as usize, freetype::face::TARGET_LIGHT).unwrap();
        let glyph = face.glyph();
        glyph.render_glyph(freetype::render_mode::RenderMode::Lcd).unwrap();

        unsafe {
            let ft_lib = self.library.raw();
            freetype::ffi::FT_Library_SetLcdFilter(ft_lib, freetype::ffi::FT_LCD_FILTER_DEFAULT);
        }

        let bitmap = glyph.bitmap();
        let buf = bitmap.buffer();
        let pitch = bitmap.pitch() as usize;

        let mut packed = Vec::with_capacity((bitmap.rows() * bitmap.width()) as usize);
        for i in 0..bitmap.rows() {
            let start = (i as usize) * pitch;
            let stop = start + bitmap.width() as usize;
            packed.extend_from_slice(&buf[start..stop]);
        }

        RasterizedGlyph {
            top: glyph.bitmap_top() as usize,
            left: glyph.bitmap_left() as usize,
            width: glyph.bitmap().width() as usize / 3,
            height: glyph.bitmap().rows() as usize,
            buf: packed,
        }
    }
}

#[derive(Debug)]
pub struct RasterizedGlyph {
    pub width: usize,
    pub height: usize,
    pub top: usize,
    pub left: usize,
    pub buf: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Rasterizer, FontDesc};

    #[cfg(target_os = "linux")]
    fn font_desc() -> FontDesc {
        FontDesc::new("Ubuntu Mono", "Regular")
    }

    #[test]
    fn create_rasterizer_and_render_glyph() {
        let mut rasterizer = Rasterizer::new();
        let glyph = rasterizer.get_glyph(&font_desc(), 24., 'U');

        println!("glyph: {:?}", glyph);

        for j in 0..glyph.height {
            for i in 0..glyph.width {
                let val = glyph.buf[j * glyph.width + i];
                print!("{}", if val < 122 { " " } else { "%"});
            }

            print!("\n");
        }
    }
}
<commit_msg>Remove old debug "test"<commit_after>use std::collections::HashMap;
use list_fonts::get_font_families;

use freetype::Library;
use freetype::Face;
use freetype;

/// Rasterizes glyphs for a single font face.
pub struct Rasterizer {
    faces: HashMap<FontDesc, Face<'static>>,
    library: Library,
    system_fonts: HashMap<String, ::list_fonts::Family>,
    dpi_x: u32,
    dpi_y: u32,
    dpr: f32,
}

#[inline]
fn to_freetype_26_6(f: f32) -> isize {
    ((1i32 << 6) as f32 * f) as isize
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
    name: String,
    style: String,
}

impl FontDesc {
    pub fn new<S>(name: S, style: S) -> FontDesc
        where S: Into<String>
    {
        FontDesc {
            name: name.into(),
            style: style.into()
        }
    }
}

impl Rasterizer {
    pub fn new(dpi_x: f32, dpi_y: f32, device_pixel_ratio: f32) -> Rasterizer {
        let library = Library::init().unwrap();

        Rasterizer {
            system_fonts: get_font_families(),
            faces: HashMap::new(),
            library: library,
            dpi_x: dpi_x as u32,
            dpi_y: dpi_y as u32,
            dpr: device_pixel_ratio,
        }
    }

    pub fn box_size_for_font(&mut self, desc: &FontDesc, size: f32) -> (u32, u32) {
        let face = self.get_face(&desc).unwrap();

        let scale_size = self.dpr * size;

        let em_size = face.em_size() as f32;
        let w = face.max_advance_width() as f32;
        let h = face.height() as f32;

        let w_scale = w / em_size;
        let h_scale = h / em_size;

        ((w_scale * scale_size) as u32, (h_scale * scale_size) as u32)
    }

    pub fn get_face(&mut self, desc: &FontDesc) -> Option<Face<'static>> {
        if let Some(face) = self.faces.get(desc) {
            return Some(face.clone());
        }

        if let Some(font) = self.system_fonts.get(&desc.name[..]) {
            if let Some(variant) = font.variants().get(&desc.style[..]) {
                let face = self.library.new_face(variant.path(), variant.index())
                                       .expect("TODO handle new_face error");

                self.faces.insert(desc.to_owned(), face);
                return Some(self.faces.get(desc).unwrap().clone());
            }
        }

        None
    }

    pub fn get_glyph(&mut self, desc: &FontDesc, size: f32, c: char) -> RasterizedGlyph {
        let face = self.get_face(desc).expect("TODO handle get_face error");
        face.set_char_size(to_freetype_26_6(size * self.dpr), 0, self.dpi_x, self.dpi_y).unwrap();
        face.load_char(c as usize, freetype::face::TARGET_LIGHT).unwrap();
        let glyph = face.glyph();
        glyph.render_glyph(freetype::render_mode::RenderMode::Lcd).unwrap();

        unsafe {
            let ft_lib = self.library.raw();
            freetype::ffi::FT_Library_SetLcdFilter(ft_lib, freetype::ffi::FT_LCD_FILTER_DEFAULT);
        }

        let bitmap = glyph.bitmap();
        let buf = bitmap.buffer();
        let pitch = bitmap.pitch() as usize;

        let mut packed = Vec::with_capacity((bitmap.rows() * bitmap.width()) as usize);
        for i in 0..bitmap.rows() {
            let start = (i as usize) * pitch;
            let stop = start + bitmap.width() as usize;
            packed.extend_from_slice(&buf[start..stop]);
        }

        RasterizedGlyph {
            top: glyph.bitmap_top() as usize,
            left: glyph.bitmap_left() as usize,
            width: glyph.bitmap().width() as usize / 3,
            height: glyph.bitmap().rows() as usize,
            buf: packed,
        }
    }
}

#[derive(Debug)]
pub struct RasterizedGlyph {
    pub width: usize,
    pub height: usize,
    pub top: usize,
    pub left: usize,
    pub buf: Vec<u8>,
}

#[cfg(test)]
mod tests {
    use super::{Rasterizer, FontDesc};

    #[cfg(target_os = "linux")]
    fn font_desc() -> FontDesc {
        FontDesc::new("Ubuntu Mono", "Regular")
    }
}
<|endoftext|>


<commit_before>//!Constants and structures from include/uapi/linux/time.h

///A structure that contains the number of seconds and nanoseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timespec {
    ///The number of seconds contained in this timespec
    tv_sec: ::time_t,

    ///The number of nanoseconds contained in this timespec
    tv_nsec: ::c_long
}

///A structure that contains the number of seconds and microseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timeval {
    ///The number of seconds contained in this timeval
    tv_sec: ::time_t,

    ///The number of microseconds contained in this timeval
    tv_usec: ::suseconds_t
}

///A structure containing information on the time-based location of a timezone
///
///Please note that this does not include the name or country code, only the minutes west of Greenwich and the type of DST correction
#[repr(C)]
pub struct timezone {
    ///The number of minutes west of Greenwich
    tz_minuteswest: ::c_int,

    ///The type of Daylight Savings Time correction
    tz_dsttime: ::c_int
}

//Names of the interval timers

///An interval timer that decrements in real time
///
///On expiration, a SIGALRM is delivered
pub const ITIMER_REAL: ::c_int = 0;

///An interval timer that decrements only when the process is executing.
///
///On expiration, a SIGVTALRM is delivered
pub const ITIMER_VIRTUAL: ::c_int = 1;

///Decrements both while the process is executing and while the system is executing on behalf of the process
///
///This is usually used to profile kernel-space and user-space concurrently.
///
///If coupled with ITIMER_VIRTUAL, you can separate the two values - What is left when ITIMER_VIRTUAL's value is removed is kernel time
pub const ITIMER_PROF: ::c_int = 2;

///An interval timer based on a `timespec`
#[repr(C)]
pub struct itimerspec {
    ///The period of time this timer should run for (Need to verify)
    it_interval: timespec,

    ///The amount of time left until expiration (Need to verify)
    it_value: timespec
}

///An interval timer based on a `timeval`
#[repr(C)]
pub struct itimerval {
    ///The period of time this timer should run for (Need to verify)
    it_interval: timeval,

    ///The amount of time left until expiration (Need to verify)
    it_value: timeval
}

///A system-wide clock that measures time from the "real world"
///
///This clock **is** affected by discontinuous jumps in system time, NTP, and user changes
pub const CLOCK_REALTIME: ::clockid_t = 0;

///A clock that measures monotonic time since an unspecified starting point
///
///Unless you manage to break your system, this unspecified point is usually when your computer powers on.
///
///This is not affected by user changes, but is by `adjtime` and NTP.
pub const CLOCK_MONOTONIC: ::clockid_t = 1;

///A high-resolution per-process timer from the processor.
pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2;

///A (high-resolution?) thread-specific timer from the processor
pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3;

///A hardware-based version of `CLOCK_MONOTONIC` that is not subject to changes
pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4;

///A faster but less precise version of `CLOCK_REALTIME`, measuring time in the "real world"
pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5;

///A faster but less precise version of `CLOCK_MONOTONIC`, measuring time since an unspecified starting point
pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6;

///Identical to `CLOCK_MONOTONIC`, but includes any time that the system is suspended.
pub const CLOCK_BOOTIME: ::clockid_t = 7;

///Identical to `CLOCK_REALTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8;

///Identical to `CLOCK_BOOTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9;

///A clock used for SGI systems. Need to investigate
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;

///A clock that shows International Atomic Time
pub const CLOCK_TAI: ::clockid_t = 11;

///The maximum clock ID that the system is allowed to have
pub const MAX_CLOCKS: ::clockid_t = 16; //Resolves to c_int. Please let me know if this should be c_int on it's own

///A mask for supported clocks
///
///Needs to be investigated
pub const CLOCKS_MASK: ::clockid_t = CLOCK_REALTIME | CLOCK_MONOTONIC;

///A shorthand variant of CLOCK_MONOTONIC.
///
///This isn't used in the kernel. Is it left over from an old change that was reverted?
pub const CLOCKS_MONO: ::clockid_t = CLOCK_MONOTONIC;

///A flag indicating time is absolute
pub const TIMER_ABSTIME: ::c_int = 0x01;
<commit_msg>Add and test some constants found in time64.h<commit_after>//!Constants and structures from time classes
//!
//! This includes include/uapi/linux/time.h, //include/linux/time.h, and /include/linux/time64.h

///A structure that contains the number of seconds and nanoseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timespec {
    ///The number of seconds contained in this timespec
    tv_sec: ::time_t,

    ///The number of nanoseconds contained in this timespec
    tv_nsec: ::c_long
}

///A structure that contains the number of seconds and microseconds since an epoch.
///
///If in doubt, assume we're talking about the UNIX epoch.
#[repr(C)]
pub struct timeval {
    ///The number of seconds contained in this timeval
    tv_sec: ::time_t,

    ///The number of microseconds contained in this timeval
    tv_usec: ::suseconds_t
}

///A structure containing information on the time-based location of a timezone
///
///Please note that this does not include the name or country code, only the minutes west of Greenwich and the type of DST correction
#[repr(C)]
pub struct timezone {
    ///The number of minutes west of Greenwich
    tz_minuteswest: ::c_int,

    ///The type of Daylight Savings Time correction
    tz_dsttime: ::c_int
}

//Names of the interval timers

///An interval timer that decrements in real time
///
///On expiration, a SIGALRM is delivered
pub const ITIMER_REAL: ::c_int = 0;

///An interval timer that decrements only when the process is executing.
///
///On expiration, a SIGVTALRM is delivered
pub const ITIMER_VIRTUAL: ::c_int = 1;

///Decrements both while the process is executing and while the system is executing on behalf of the process
///
///This is usually used to profile kernel-space and user-space concurrently.
///
///If coupled with ITIMER_VIRTUAL, you can separate the two values - What is left when ITIMER_VIRTUAL's value is removed is kernel time
pub const ITIMER_PROF: ::c_int = 2;

///An interval timer based on a `timespec`
#[repr(C)]
pub struct itimerspec {
    ///The period of time this timer should run for (Need to verify)
    it_interval: timespec,

    ///The amount of time left until expiration (Need to verify)
    it_value: timespec
}

///An interval timer based on a `timeval`
#[repr(C)]
pub struct itimerval {
    ///The period of time this timer should run for (Need to verify)
    it_interval: timeval,

    ///The amount of time left until expiration (Need to verify)
    it_value: timeval
}

///A system-wide clock that measures time from the "real world"
///
///This clock **is** affected by discontinuous jumps in system time, NTP, and user changes
pub const CLOCK_REALTIME: ::clockid_t = 0;

///A clock that measures monotonic time since an unspecified starting point
///
///Unless you manage to break your system, this unspecified point is usually when your computer powers on.
///
///This is not affected by user changes, but is by `adjtime` and NTP.
pub const CLOCK_MONOTONIC: ::clockid_t = 1;

///A high-resolution per-process timer from the processor.
pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2;

///A (high-resolution?) thread-specific timer from the processor
pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3;

///A hardware-based version of `CLOCK_MONOTONIC` that is not subject to changes
pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4;

///A faster but less precise version of `CLOCK_REALTIME`, measuring time in the "real world"
pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5;

///A faster but less precise version of `CLOCK_MONOTONIC`, measuring time since an unspecified starting point
pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6;

///Identical to `CLOCK_MONOTONIC`, but includes any time that the system is suspended.
pub const CLOCK_BOOTIME: ::clockid_t = 7;

///Identical to `CLOCK_REALTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8;

///Identical to `CLOCK_BOOTIME`, but timers exposed via this will wake the system if suspended
pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9;

///A clock used for SGI systems. Need to investigate
pub const CLOCK_SGI_CYCLE: ::clockid_t = 10;

///A clock that shows International Atomic Time
pub const CLOCK_TAI: ::clockid_t = 11;

///The maximum clock ID that the system is allowed to have
pub const MAX_CLOCKS: ::clockid_t = 16; //Resolves to c_int. Please let me know if this should be c_int on it's own

///A mask for supported clocks
///
///Needs to be investigated
pub const CLOCKS_MASK: ::clockid_t = CLOCK_REALTIME | CLOCK_MONOTONIC;

///A shorthand variant of CLOCK_MONOTONIC.
///
///This isn't used in the kernel. Is it left over from an old change that was reverted?
pub const CLOCKS_MONO: ::clockid_t = CLOCK_MONOTONIC;

///A flag indicating time is absolute
pub const TIMER_ABSTIME: ::c_int = 0x01;

///The type used for 64-bit time
pub type time64_t = i64;

///The number of milliseconds in a second
pub const MSEC_PER_SEC: ::c_long = 1000;

///The number of microseconds in a millisecond
pub const USEC_PER_MSEC: ::c_long = 1000;

///The number of nanoseconds in a microsecond
pub const NSEC_PER_USEC: ::c_long = 1000;

///The number of nanoseconds in a millisecond
pub const NSEC_PER_MSEC: ::c_long = 1000000;

///The number of microseconds in a second
pub const USEC_PER_SEC: ::c_long = 1000000;

///The number of nanoseconds in a second
pub const NSEC_PER_SEC: ::c_long = 1000000000;

///The number of femtoseconds in a second
pub const FSEC_PER_SEC: ::c_longlong = 1000000000000000;

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

    #[test]
    fn test_per_sec_accuracy() {
        assert_eq!(NSEC_PER_MSEC, NSEC_PER_USEC * USEC_PER_MSEC);
        assert_eq!(NSEC_PER_SEC, NSEC_PER_MSEC * MSEC_PER_SEC);
    }
}<|endoftext|>


<commit_before>//!
//! # Tools
//!

use std::result::Result;
use std::error::Error;
use serde::*;
use serde_json::*;

///
/// Trait implemented by things that represent a tool
///
/// A tool is simply a routine that takes some input, does some processing
/// and returns a value or an error. The main difference between a tool and
/// a simple function is that a tool's input and output must be simple data,
/// which for Rust we define as 'can be serialized to JSON'.
///
/// Tools also have the requirement that they are encapsulated and can instantiate
/// themselves with no dependencies other than those they can discover from
/// their environment.
///
/// These two requirements mean that tools can be invoked simply by specifying
/// the input data (without necessarily having to know the exact Rust type involved!).
/// Test cases for tools can be specified as simple JSON data with no need for any
/// actual code. Tools can be turned into stand-alone command line programs or
/// web endpoints with no modification.
///
pub trait Tool<TIn: Deserialize, TOut: Serialize, TErr: Serialize> {
    ///
    /// Invokes this tool with an input data structure and returns its result
    ///
    fn invoke(&self, input: TIn) -> Result<TOut, TErr>;
}

///
/// Allows a tool to be invoked using JSON input and output
///
/// Tools in Rust are normally implemented using strong types for convenience's
/// sake, but an important capability is that their input and output can be
/// easily serialized, in particular to JSON which is currently a particularly
/// convenient format for interopability.
///
pub trait JsonTool {
    ///
    /// Invokes this tool with its input and output specified using JSON
    ///
    fn invoke_json(&self, input: Value) -> Result<Value, Value>;
}

impl<TIn, TOut, TErr> JsonTool for Tool<TIn, TOut, TErr>
where TIn: Deserialize, TOut: Serialize, TErr: Serialize {
    fn invoke_json(&self, input: Value) -> Result<Value, Value> {
        // Decode
        let input_decoded = from_value::<TIn>(input);

        // Chain into the tool itself
        match input_decoded {
            Ok(input_decoded) => {
                // Successfully decoded as the tool's input format
                let result = self.invoke(input_decoded);

                // Encode the error or the result
                // The encoding can go wrong, and we need to handle it slightly differently for the error or the success case
                match result {
                    Ok(res) => {
                        let encoded = to_value(res);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "JSON encode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(erm) => {
                        let encoded = to_value(erm);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Error encode failed",
                                "description":  erm.description()
                            }])
                        }
                    }
                }
            },

            Err(input_error) => {
                // Input does not match the format expected by the tool
                Err(json![{
                    "error":        "JSON input decode failed",
                    "description":  input_error.description(),
                }])
            }
        }
    }
}
<commit_msg>First pass at adding some test cases for the JSON stuff<commit_after>//!
//! # Tools
//!

use std::result::Result;
use std::error::Error;
use serde::*;
use serde_json::*;

///
/// Trait implemented by things that represent a tool
///
/// A tool is simply a routine that takes some input, does some processing
/// and returns a value or an error. The main difference between a tool and
/// a simple function is that a tool's input and output must be simple data,
/// which for Rust we define as 'can be serialized to JSON'.
///
/// Tools also have the requirement that they are encapsulated and can instantiate
/// themselves with no dependencies other than those they can discover from
/// their environment.
///
/// These two requirements mean that tools can be invoked simply by specifying
/// the input data (without necessarily having to know the exact Rust type involved!).
/// Test cases for tools can be specified as simple JSON data with no need for any
/// actual code. Tools can be turned into stand-alone command line programs or
/// web endpoints with no modification.
///
pub trait Tool<TIn: Deserialize, TOut: Serialize, TErr: Serialize> {
    ///
    /// Invokes this tool with an input data structure and returns its result
    ///
    fn invoke(&self, input: TIn) -> Result<TOut, TErr>;
}

///
/// Allows a tool to be invoked using JSON input and output
///
/// Tools in Rust are normally implemented using strong types for convenience's
/// sake, but an important capability is that their input and output can be
/// easily serialized, in particular to JSON which is currently a particularly
/// convenient format for interopability.
///
pub trait JsonTool {
    ///
    /// Invokes this tool with its input and output specified using JSON
    ///
    fn invoke_json(&self, input: Value) -> Result<Value, Value>;
}

impl<TIn, TOut, TErr> JsonTool for Tool<TIn, TOut, TErr>
where TIn: Deserialize, TOut: Serialize, TErr: Serialize {
    fn invoke_json(&self, input: Value) -> Result<Value, Value> {
        // Decode
        let input_decoded = from_value::<TIn>(input);

        // Chain into the tool itself
        match input_decoded {
            Ok(input_decoded) => {
                // Successfully decoded as the tool's input format
                let result = self.invoke(input_decoded);

                // Encode the error or the result
                // The encoding can go wrong, and we need to handle it slightly differently for the error or the success case
                match result {
                    Ok(res) => {
                        let encoded = to_value(res);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "JSON encode failed",
                                "description":  erm.description()
                            }])
                        }
                    },

                    Err(erm) => {
                        let encoded = to_value(erm);
                        match encoded {
                            Ok(final_value) => Ok(final_value),
                            Err(erm)        => Err(json![{
                                "error":        "Error encode failed",
                                "description":  erm.description()
                            }])
                        }
                    }
                }
            },

            Err(input_error) => {
                // Input does not match the format expected by the tool
                Err(json![{
                    "error":        "JSON input decode failed",
                    "description":  input_error.description(),
                }])
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::result::Result;
    use serde::*;
    use serde_json::*;

    #[derive(Serialize, Deserialize)]
    struct TestIn {
        input: i32
    }

    #[derive(Serialize, Deserialize)]
    struct TestOut {
        output: i32
    }

    struct InputOutput { }
    impl Tool<TestIn, TestOut, ()> for InputOutput {
        fn invoke(&self, x: TestIn) -> Result<TestOut, ()> {
            Ok(TestOut { output: x.input+1 })
        }
    }

    #[test]
    fn can_call_tool_via_json_interface() {
        let tool = InputOutput {};
        let result = tool.invoke_json(json![{ "input": 4 }]);

        assert!(result == Ok(json![{ "output": 5 }]));
    }
}
<|endoftext|>