<commit_before>//! Sources for key-value pairs.

use kv::{Error, Key, ToKey, Value, ToValue};

/// A source of key-value pairs.
///
/// The source may be a single pair, a set of pairs, or a filter over a set of pairs.
/// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data
/// in a source.
pub trait Source {
    /// Visit key-value pairs.
    ///
    /// A source doesn't have to guarantee any ordering or uniqueness of key-value pairs.
    /// If the given visitor returns an error then the source may early-return with it,
    /// even if there are more key-value pairs.
    ///
    /// # Implementation notes
    ///
    /// A source should yield the same key-value pairs to a subsequent visitor unless
    /// that visitor itself fails.
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error>;

    /// Get the value for a given key.
    ///
    /// If the key appears multiple times in the source then which key is returned
    /// is implementation specific.
    ///
    /// # Implementation notes
    ///
    /// A source that can provide a more efficient implementation of this method
    /// should override it.
    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        struct Get<'k, 'v> {
            key: Key<'k>,
            found: Option<Value<'v>>,
        }

        impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> {
            fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
                if self.key == key {
                    self.found = Some(value);
                }

                Ok(())
            }
        }

        let mut get = Get {
            key,
            found: None,
        };

        let _ = self.visit(&mut get);
        get.found
    }

    /// Count the number of key-value pairs that can be visited.
    ///
    /// # Implementation notes
    ///
    /// A source that knows the number of key-value pairs upfront may provide a more
    /// efficient implementation.
    ///
    /// A subsequent call to `visit` should yield the same number of key-value pairs
    /// to the visitor, unless that visitor fails part way through.
    fn count(&self) -> usize {
        struct Count(usize);

        impl<'kvs> Visitor<'kvs> for Count {
            fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> {
                self.0 += 1;

                Ok(())
            }
        }

        let mut count = Count(0);
        let _ = self.visit(&mut count);
        count.0
    }
}

impl<'a, T> Source for &'a T
where
    T: Source + ?Sized,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        Source::visit(&**self, visitor)
    }

    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        Source::get(&**self, key)
    }

    fn count(&self) -> usize {
        Source::count(&**self)
    }
}

impl<K, V> Source for (K, V)
where
    K: ToKey,
    V: ToValue,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        visitor.visit_pair(self.0.to_key(), self.1.to_value())
    }

    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        if self.0.to_key() == key {
            Some(self.1.to_value())
        } else {
            None
        }
    }

    fn count(&self) -> usize {
        1
    }
}

impl<S> Source for [S]
where
    S: Source,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        for source in self {
            source.visit(visitor)?;
        }

        Ok(())
    }

    fn count(&self) -> usize {
        self.len()
    }
}

impl<S> Source for Option<S>
where
    S: Source,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        if let Some(ref source) = *self {
            source.visit(visitor)?;
        }

        Ok(())
    }

    fn count(&self) -> usize {
        self.as_ref().map(Source::count).unwrap_or(0)
    }
}

/// A visitor for the key-value pairs in a [`Source`](trait.Source.html).
pub trait Visitor<'kvs> {
    /// Visit a key-value pair.
    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>;
}

impl<'a, 'kvs, T> Visitor<'kvs> for &'a mut T
where
    T: Visitor<'kvs> + ?Sized,
{
    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
        (**self).visit_pair(key, value)
    }
}

#[cfg(feature = "std")]
mod std_support {
    use super::*;

    impl<S> Source for Box<S>
    where
        S: Source + ?Sized,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            Source::visit(&**self, visitor)
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            Source::get(&**self, key)
        }

        fn count(&self) -> usize {
            Source::count(&**self)
        }
    }

    impl<S> Source for Vec<S>
    where
        S: Source,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            Source::visit(&**self, visitor)
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            Source::get(&**self, key)
        }

        fn count(&self) -> usize {
            Source::count(&**self)
        }
    }

    impl<'kvs, V> Visitor<'kvs> for Box<V>
    where
        V: Visitor<'kvs> + ?Sized,
    {
        fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
            (**self).visit_pair(key, value)
        }
    }

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

        #[test]
        fn count() {
            assert_eq!(1, Source::count(&Box::new(("a", 1))));
            assert_eq!(2, Source::count(&vec![("a", 1), ("b", 2)]));
        }

        #[test]
        fn get() {
            let source = vec![("a", 1), ("b", 2), ("a", 1)];
            assert_eq!(Token::I64(1), Source::get(&source, Key::from_str("a")).unwrap().to_token());

            let source = Box::new(Option::None::<(&str, i32)>);
            assert!(Source::get(&source, Key::from_str("a")).is_none());
        }
    }
}

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

    #[test]
    fn source_is_object_safe() {
        fn _check(_: &Source) {}
    }

    #[test]
    fn visitor_is_object_safe() {
        fn _check(_: &Visitor) {}
    }

    #[test]
    fn count() {
        struct OnePair {
            key: &'static str,
            value: i32,
        }

        impl Source for OnePair {
            fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
                visitor.visit_pair(self.key.to_key(), self.value.to_value())
            }
        }

        assert_eq!(1, Source::count(&("a", 1)));
        assert_eq!(2, Source::count(&[("a", 1), ("b", 2)] as &[_]));
        assert_eq!(0, Source::count(&Option::None::<(&str, i32)>));
        assert_eq!(1, Source::count(&OnePair { key: "a", value: 1 }));
    }

    #[test]
    fn get() {
        let source = &[("a", 1), ("b", 2), ("a", 1)] as &[_];
        assert_eq!(Token::I64(1), Source::get(source, Key::from_str("a")).unwrap().to_token());
        assert_eq!(Token::I64(2), Source::get(source, Key::from_str("b")).unwrap().to_token());
        assert!(Source::get(&source, Key::from_str("c")).is_none());

        let source = Option::None::<(&str, i32)>;
        assert!(Source::get(&source, Key::from_str("a")).is_none());
    }
}
<commit_msg>Add impls for Source for HashMap and BTreeMap<commit_after>//! Sources for key-value pairs.

use kv::{Error, Key, ToKey, Value, ToValue};

/// A source of key-value pairs.
///
/// The source may be a single pair, a set of pairs, or a filter over a set of pairs.
/// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data
/// in a source.
pub trait Source {
    /// Visit key-value pairs.
    ///
    /// A source doesn't have to guarantee any ordering or uniqueness of key-value pairs.
    /// If the given visitor returns an error then the source may early-return with it,
    /// even if there are more key-value pairs.
    ///
    /// # Implementation notes
    ///
    /// A source should yield the same key-value pairs to a subsequent visitor unless
    /// that visitor itself fails.
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error>;

    /// Get the value for a given key.
    ///
    /// If the key appears multiple times in the source then which key is returned
    /// is implementation specific.
    ///
    /// # Implementation notes
    ///
    /// A source that can provide a more efficient implementation of this method
    /// should override it.
    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        struct Get<'k, 'v> {
            key: Key<'k>,
            found: Option<Value<'v>>,
        }

        impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> {
            fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
                if self.key == key {
                    self.found = Some(value);
                }

                Ok(())
            }
        }

        let mut get = Get {
            key,
            found: None,
        };

        let _ = self.visit(&mut get);
        get.found
    }

    /// Count the number of key-value pairs that can be visited.
    ///
    /// # Implementation notes
    ///
    /// A source that knows the number of key-value pairs upfront may provide a more
    /// efficient implementation.
    ///
    /// A subsequent call to `visit` should yield the same number of key-value pairs
    /// to the visitor, unless that visitor fails part way through.
    fn count(&self) -> usize {
        struct Count(usize);

        impl<'kvs> Visitor<'kvs> for Count {
            fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> {
                self.0 += 1;

                Ok(())
            }
        }

        let mut count = Count(0);
        let _ = self.visit(&mut count);
        count.0
    }
}

impl<'a, T> Source for &'a T
where
    T: Source + ?Sized,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        Source::visit(&**self, visitor)
    }

    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        Source::get(&**self, key)
    }

    fn count(&self) -> usize {
        Source::count(&**self)
    }
}

impl<K, V> Source for (K, V)
where
    K: ToKey,
    V: ToValue,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        visitor.visit_pair(self.0.to_key(), self.1.to_value())
    }

    fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
        if self.0.to_key() == key {
            Some(self.1.to_value())
        } else {
            None
        }
    }

    fn count(&self) -> usize {
        1
    }
}

impl<S> Source for [S]
where
    S: Source,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        for source in self {
            source.visit(visitor)?;
        }

        Ok(())
    }

    fn count(&self) -> usize {
        self.len()
    }
}

impl<S> Source for Option<S>
where
    S: Source,
{
    fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
        if let Some(ref source) = *self {
            source.visit(visitor)?;
        }

        Ok(())
    }

    fn count(&self) -> usize {
        self.as_ref().map(Source::count).unwrap_or(0)
    }
}

/// A visitor for the key-value pairs in a [`Source`](trait.Source.html).
pub trait Visitor<'kvs> {
    /// Visit a key-value pair.
    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>;
}

impl<'a, 'kvs, T> Visitor<'kvs> for &'a mut T
where
    T: Visitor<'kvs> + ?Sized,
{
    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
        (**self).visit_pair(key, value)
    }
}

#[cfg(feature = "std")]
mod std_support {
    use super::*;
    use std::borrow::Borrow;
    use std::collections::{BTreeMap, HashMap};
    use std::hash::{BuildHasher, Hash};

    impl<S> Source for Box<S>
    where
        S: Source + ?Sized,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            Source::visit(&**self, visitor)
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            Source::get(&**self, key)
        }

        fn count(&self) -> usize {
            Source::count(&**self)
        }
    }

    impl<S> Source for Vec<S>
    where
        S: Source,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            Source::visit(&**self, visitor)
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            Source::get(&**self, key)
        }

        fn count(&self) -> usize {
            Source::count(&**self)
        }
    }

    impl<'kvs, V> Visitor<'kvs> for Box<V>
    where
        V: Visitor<'kvs> + ?Sized,
    {
        fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
            (**self).visit_pair(key, value)
        }
    }

    impl<K, V, S> Source for HashMap<K, V, S>
    where
        K: ToKey + Borrow<str> + Eq + Hash,
        V: ToValue,
        S: BuildHasher,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            for (key, value) in self {
                visitor.visit_pair(key.to_key(), value.to_value())?;
            }
            Ok(())
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            HashMap::get(self, key.as_str()).map(|v| v.to_value())
        }

        fn count(&self) -> usize {
            self.len()
        }
    }

    impl<K, V> Source for BTreeMap<K, V>
    where
        K: ToKey + Borrow<str> + Ord,
        V: ToValue,
    {
        fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
            for (key, value) in self {
                visitor.visit_pair(key.to_key(), value.to_value())?;
            }
            Ok(())
        }

        fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {
            BTreeMap::get(self, key.as_str()).map(|v| v.to_value())
        }

        fn count(&self) -> usize {
            self.len()
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;
        use kv::value::test::Token;
        use std::collections::{BTreeMap, HashMap};

        #[test]
        fn count() {
            assert_eq!(1, Source::count(&Box::new(("a", 1))));
            assert_eq!(2, Source::count(&vec![("a", 1), ("b", 2)]));
        }

        #[test]
        fn get() {
            let source = vec![("a", 1), ("b", 2), ("a", 1)];
            assert_eq!(
                Token::I64(1),
                Source::get(&source, Key::from_str("a")).unwrap().to_token()
            );

            let source = Box::new(Option::None::<(&str, i32)>);
            assert!(Source::get(&source, Key::from_str("a")).is_none());
        }

        #[test]
        fn hash_map() {
            let mut map = HashMap::new();
            map.insert("a", 1);
            map.insert("b", 2);

            assert_eq!(2, Source::count(&map));
            assert_eq!(
                Token::I64(1),
                Source::get(&map, Key::from_str("a")).unwrap().to_token()
            );
        }

        #[test]
        fn btree_map() {
            let mut map = BTreeMap::new();
            map.insert("a", 1);
            map.insert("b", 2);

            assert_eq!(2, Source::count(&map));
            assert_eq!(
                Token::I64(1),
                Source::get(&map, Key::from_str("a")).unwrap().to_token()
            );
        }
    }
}

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

    #[test]
    fn source_is_object_safe() {
        fn _check(_: &Source) {}
    }

    #[test]
    fn visitor_is_object_safe() {
        fn _check(_: &Visitor) {}
    }

    #[test]
    fn count() {
        struct OnePair {
            key: &'static str,
            value: i32,
        }

        impl Source for OnePair {
            fn visit<'kvs>(&'kvs self, visitor: &mut Visitor<'kvs>) -> Result<(), Error> {
                visitor.visit_pair(self.key.to_key(), self.value.to_value())
            }
        }

        assert_eq!(1, Source::count(&("a", 1)));
        assert_eq!(2, Source::count(&[("a", 1), ("b", 2)] as &[_]));
        assert_eq!(0, Source::count(&Option::None::<(&str, i32)>));
        assert_eq!(1, Source::count(&OnePair { key: "a", value: 1 }));
    }

    #[test]
    fn get() {
        let source = &[("a", 1), ("b", 2), ("a", 1)] as &[_];
        assert_eq!(
            Token::I64(1),
            Source::get(source, Key::from_str("a")).unwrap().to_token()
        );
        assert_eq!(
            Token::I64(2),
            Source::get(source, Key::from_str("b")).unwrap().to_token()
        );
        assert!(Source::get(&source, Key::from_str("c")).is_none());

        let source = Option::None::<(&str, i32)>;
        assert!(Source::get(&source, Key::from_str("a")).is_none());
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Create channel and spawn a thread that sends string through it<commit_after>use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("Hello there");
        tx.send(val).unwrap();
    });
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul};
use libc::{c_char, c_int, c_ulong, c_long, c_double, c_void};
use std::ffi::*;
use std::cmp::{Ordering};
use std::slice;
use std::sync::{Once, ONCE_INIT};

static EXACTINIT: Once = ONCE_INIT;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point2D {
    x: c_double,
    y: c_double,
}

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point3D {
    x: c_double,
    y: c_double,
    z: c_double,
}

#[link(name = "predicates")]
extern "C" {
    fn exactinit() -> c_void;
    fn insphere(pa: *const Point3D, pb: *const Point3D, pc: *const Point3D, pd: *const Point3D, pe: *const Point3D) -> c_double;
    fn incircle(pa: *const Point2D, pb: *const Point2D, pc: *const Point2D, pd: *const Point2D) -> c_double;
}

fn init_predicates() {
    EXACTINIT.call_once(|| {
        unsafe { exactinit() };
    });
}

#[derive(Debug, Eq, PartialEq)]
pub enum InCircleLocation {
    Inside,
    Outside,
    On
}

pub trait InCircle<P> {
    fn in_circle_test(&self, point: &P) -> Option<InCircleLocation>;
}

pub struct Triangle<P> {
    p1: P,
    p2: P,
    p3: P,
}

impl InCircle<Point2D> for Triangle<Point2D> {
    fn in_circle_test(&self, point: &Point2D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { incircle(&self.p1, &self.p2, &self.p3, point) };

        match 0.0.partial_cmp(&incircle_det) {
            Some(Ordering::Greater) => { Some(InCircleLocation::Inside) }
            Some(Ordering::Less) => { Some(InCircleLocation::Outside) }
            Some(Ordering::Equal) => { Some(InCircleLocation::On) }
            None => { None }
        }
    }
}

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

    #[test]
    fn in_circle_2d() {
        let p1 = Point2D { x: 0.0, y: 0.0 };
        let p2 = Point2D { x: 0.0, y: 1.0 };
        let p3 = Point2D { x: 1.0, y: 1.0 };
        let d_inside  = Point2D { x: 0.5, y: 0.5 };
        let d_outside  = Point2D { x: 2.0, y: 0.0 };
        let d_on  = Point2D { x: 1.0, y: 1.0 };

        let t = Triangle { p1: p1, p2: p2, p3: p3 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }
}
<commit_msg>Extract function<commit_after>use std::ops::{Add, Sub, Mul};
use libc::{c_char, c_int, c_ulong, c_long, c_double, c_void};
use std::ffi::*;
use std::cmp::{Ordering};
use std::slice;
use std::sync::{Once, ONCE_INIT};

static EXACTINIT: Once = ONCE_INIT;

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point2D {
    x: c_double,
    y: c_double,
}

#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Point3D {
    x: c_double,
    y: c_double,
    z: c_double,
}

#[link(name = "predicates")]
extern "C" {
    fn exactinit() -> c_void;
    fn insphere(pa: *const Point3D, pb: *const Point3D, pc: *const Point3D, pd: *const Point3D, pe: *const Point3D) -> c_double;
    fn incircle(pa: *const Point2D, pb: *const Point2D, pc: *const Point2D, pd: *const Point2D) -> c_double;
}

fn init_predicates() {
    EXACTINIT.call_once(|| {
        unsafe { exactinit() };
    });
}

#[derive(Debug, Eq, PartialEq)]
pub enum InCircleLocation {
    Inside,
    Outside,
    On
}

pub trait InCircle<P> {
    fn in_circle_test(&self, point: &P) -> Option<InCircleLocation>;
}

pub struct Triangle<P> {
    p1: P,
    p2: P,
    p3: P,
}

fn det_to_in_circle_location(det: f64) -> Option<InCircleLocation> {
    match 0.0.partial_cmp(&det) {
        Some(Ordering::Greater) => { Some(InCircleLocation::Inside) }
        Some(Ordering::Less) => { Some(InCircleLocation::Outside) }
        Some(Ordering::Equal) => { Some(InCircleLocation::On) }
        None => { None }
    }
}

impl InCircle<Point2D> for Triangle<Point2D> {
    fn in_circle_test(&self, point: &Point2D) -> Option<InCircleLocation> {
        init_predicates();

        let incircle_det = unsafe { incircle(&self.p1, &self.p2, &self.p3, point) };

        det_to_in_circle_location(incircle_det)
    }
}

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

    #[test]
    fn in_circle_2d() {
        let p1 = Point2D { x: 0.0, y: 0.0 };
        let p2 = Point2D { x: 0.0, y: 1.0 };
        let p3 = Point2D { x: 1.0, y: 1.0 };
        let d_inside  = Point2D { x: 0.5, y: 0.5 };
        let d_outside  = Point2D { x: 2.0, y: 0.0 };
        let d_on  = Point2D { x: 1.0, y: 1.0 };

        let t = Triangle { p1: p1, p2: p2, p3: p3 };

        assert_eq!(t.in_circle_test(&d_inside), Some(InCircleLocation::Inside));
        assert_eq!(t.in_circle_test(&d_outside), Some(InCircleLocation::Outside));
        assert_eq!(t.in_circle_test(&d_on), Some(InCircleLocation::On));
    }
}
<|endoftext|>


<commit_before>//! Disk header parsing.
//!
//! The disk header provides information on how to read a TFS disk. This module parses and
//! interprets the disk header so it is meaningful to the programmer.

/// The size of the disk header.
///
/// This should be a multiple of the cluster size.
const DISK_HEADER_SIZE: usize = 4096;
/// The default disk header.
const DEFAULT_DISK_HEADER: &'static [u8] = &[
    // The magic number (`TFS fmt `).
    b'T', b'F', b'S', b' ', b'f', b'm', b't', b' ',
    // The version number.
    0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF,
    // The implementation ID (`official`).
     b'o',  b'f',  b'f',  b'i',  b'c',  b'i',  b'a',  b'l',
    !b'o', !b'f', !b'f', !b'i', !b'c', !b'i', !b'a', !b'l',
    // Encryption algorithm.
    0x00, 0x00,
    0xFF, 0xFF,
    // Encryption parameters.
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    // State block address (uninitialized).
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    // Consistency flag.
    0x03, 0xFC,
];

/// A disk header reading error.
enum Error {
    /// The consistency flag is corrupt.
    CorruptConsistencyFlag,
    /// The cipher field is corrupt.
    CorruptCipher,
    /// The encryption parameters is corrupt.
    CorruptEncryptionParameters,
    /// The implementation ID is corrupt.
    CorruptImplementationId,
    /// The state block address is corrupt.
    CorruptStateBlockAddress,
    /// The version number is corrupt.
    CorruptVersionNumber,
    /// The version is incompatible with this implementation.
    ///
    /// The version number is given by some integer. If the higher half of the integer does not
    /// match, the versions are incompatible and this error is returned.
    IncompatibleVersion,
    /// Unknown cipher option.
    UnknownCipher,
    /// Unknown consistency flag value.
    UnknownConsistencyFlag,
    /// Unknown format (not TFS).
    UnknownFormat,
    /// A disk I/O error.
    Disk(disk::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
        write!(f, )
    }
}

/// TFS magic number.
enum MagicNumber {
    /// The image is partially compatible with the official TFS specification.
    PartialCompatibility,
    /// The image is completely compatible with the official TFS specification.
    TotalCompatibility,
}

/// Cipher option.
enum Cipher {
    /// Disk encryption disabled.
    Identity = 0,
    /// Use the SPECK cipher.
    Speck128 = 1,
}

/// Consistency flag.
///
/// The consistency flag defines the state of the disk, telling the user if it is in a consistent
/// state or not. It is important for doing non-trivial things like garbage-collection, where the
/// disk needs to enter an inconsistent state for a small period of time.
enum ConsistencyFlag {
    /// The disk was properly closed and shut down.
    Closed,
    /// The disk is active/was forcibly shut down.
    StillActive,
    /// The disk is in an inconsistent state.
    ///
    /// Proceed with caution.
    Inconsistent,
    /// The disk is uninitialized.
    Uninitialized,
}

/// The disk header.
#[derive(Default)]
struct DiskHeader {
    /// The magic number.
    magic_number: MagicNumber,
    /// The version number.
    version_number: u32,
    /// The implementation ID.
    implementation_id: u32,
    /// The cipher.
    cipher: Cipher,
    /// The encryption paramters.
    ///
    /// These are used as defined by the choice of cipher. Some ciphers might use it for salt or
    /// settings, and others not use it at all.
    encryption_parameters: [u8; 16],
    /// The address of the state block.
    state_block_address: clusters::Pointer,
    /// The consistency flag.
    consistency_flag: ConsistencyFlag,
}

impl DiskHeader {
    /// Load the disk header from some disk.
    ///
    /// This will construct it into memory while performing error checks on the header to ensure
    /// correctness.
    fn load<D: Disk>(disk: &mut D) -> Result<DiskHeader, Error> {
        // Load the disk header into a buffer in memory.
        let mut buf = [0; DISK_HEADER_SIZE];
        // Fetch the sector size.
        let sector_size = disk.sector_size();
        // Load the first couple of sectors into `buf`.
        for sector in 0..DISK_HEADER_SIZE / sector_size {
            disk.read(sector, 0, &mut buf[sector * sector_size..])?;
        }

        // Start with some default value, which will be filled out later.
        let mut ret = DiskHeader::default();

        // # Introducer Section
        //
        // This section has the purpose of defining the implementation, version, and type of the
        // disk image. It is rarely changed unless updates or reformatting happens.

        // Load the magic number.
        ret.magic_number = match buf[..8] {
            // Total compatibility.
            b"TFS fmt " => MagicNumber::TotalCompatibility,
            // Partial compatibility.
            b"~TFS fmt" => MagicNumber::PartialCompatibility,
            // Unknown format; abort.
            _ => return Err(Error::UnknownFormat),
        };

        // Load the version number.
        ret.version_number = LittleEndian::read(buf[8..12]);
        // Right after the version number, the same number follows, but bitwise negated. Make sure
        // that these numbers match (if it is bitwise negated). The reason for using this form of
        // code rather than just repeating it as-is is that if one overwrites all bytes with a
        // constant value, like zero, it won't be detected.
        if ret.version_number == !LittleEndian::read(buf[12..16]) {
            // Check if the version is compatible.
            if ret.version_number >> 16 > 0 {
                // The version is not compatible; abort.
                return Err(Error::IncompatibleVersion);
            }
        } else {
            // The version number is corrupt; abort.
            return Err(Error::CorruptVersionNumber);
        }

        // Load the implementation ID.
        ret.implementation_id = LittleEndian::read(buf[16..24]);
        // Similarly to the version number, a bitwise negated repetition follows. Make sure it
        // matches.
        if ret.implementation_id != !LittleEndian::read(buf[24..32]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptImplementationId);
        }

        //////////////// Encryption Section ////////////////

        // Load the encryption algorithm choice.
        ret.cipher = Cipher::from(LittleEndian::read(buf[64..66]))?;
        // Repeat the bitwise negation.
        if ret.cipher as u16 != !LittleEndian::read(buf[66..68]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptCipher);
        }

        // Load the encryption parameters (e.g. salt).
        self.encryption_parameters.copy_from_slice(&buf[68..84]);
        // Repeat the bitwise negation.
        if self.encryption_parameters.iter().eq(buf[84..100].iter().map(|x| !x)) {
            // The encryption parameters are corrupt; abort.
            return Err(Error::CorruptEncryptionParameters);
        }

        //////////////// State ////////////////

        // Load the state block pointer.
        ret.state_block_address = clusters::Pointer::new(LittleEndian::read(buf[128..136]));
        // Repeat the bitwise negation.
        if ret.state_block_address as u64 != !LittleEndian::read(buf[136..144]) {
            // The state block address is corrupt; abort.
            return Err(Error::CorruptStateBlockAddress);
        }

        // Load the consistency flag.
        self.consistency_flag = ConsistencyFlag::from(buf[144])?;
        // Repeat the bitwise negation.
        if self.consistency_flag as u8 != !buf[145] {
            // The consistency flag is corrupt; abort.
            return Err(Error::CorruptConsistencyFlag);
        }
    }
}
<commit_msg>Use the values given in the enums in the header module instead of hardcoding them in the default buffer.<commit_after>//! Disk header parsing.
//!
//! The disk header provides information on how to read a TFS disk. This module parses and
//! interprets the disk header so it is meaningful to the programmer.

/// The size of the disk header.
///
/// This should be a multiple of the cluster size.
const DISK_HEADER_SIZE: usize = 4096;
/// The default disk header.
const DEFAULT_DISK_HEADER: &'static [u8] = &[
    // The magic number (`TFS fmt `).
    b'T', b'F', b'S', b' ', b'f', b'm', b't', b' ',
    // The version number.
    0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF,
    // The implementation ID (`official`).
     b'o',  b'f',  b'f',  b'i',  b'c',  b'i',  b'a',  b'l',
    !b'o', !b'f', !b'f', !b'i', !b'c', !b'i', !b'a', !b'l',
    // Encryption algorithm.
    0x00, CompressionAlgorithm::Identity as u8,
    0xFF, !CompressionAlgorithm::Identity as u8,
    // Encryption parameters.
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    // State block address (uninitialized).
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    // Consistency flag.
    ConsistencyFlag::Uninitialized as u8, !ConsistencyFlag::Uninitialized as u8,
];

/// A disk header reading error.
enum Error {
    /// The consistency flag is corrupt.
    CorruptConsistencyFlag,
    /// The cipher field is corrupt.
    CorruptCipher,
    /// The encryption parameters is corrupt.
    CorruptEncryptionParameters,
    /// The implementation ID is corrupt.
    CorruptImplementationId,
    /// The state block address is corrupt.
    CorruptStateBlockAddress,
    /// The version number is corrupt.
    CorruptVersionNumber,
    /// The version is incompatible with this implementation.
    ///
    /// The version number is given by some integer. If the higher half of the integer does not
    /// match, the versions are incompatible and this error is returned.
    IncompatibleVersion,
    /// Unknown cipher option.
    UnknownCipher,
    /// Unknown consistency flag value.
    UnknownConsistencyFlag,
    /// Unknown format (not TFS).
    UnknownFormat,
    /// A disk I/O error.
    Disk(disk::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), Error> {
        write!(f, )
    }
}

/// TFS magic number.
enum MagicNumber {
    /// The image is partially compatible with the official TFS specification.
    PartialCompatibility,
    /// The image is completely compatible with the official TFS specification.
    TotalCompatibility,
}

/// Cipher option.
enum Cipher {
    /// Disk encryption disabled.
    Identity = 0,
    /// Use the SPECK cipher.
    Speck128 = 1,
}

/// Consistency flag.
///
/// The consistency flag defines the state of the disk, telling the user if it is in a consistent
/// state or not. It is important for doing non-trivial things like garbage-collection, where the
/// disk needs to enter an inconsistent state for a small period of time.
enum ConsistencyFlag {
    /// The disk was properly closed and shut down.
    Closed,
    /// The disk is active/was forcibly shut down.
    StillActive,
    /// The disk is in an inconsistent state.
    ///
    /// Proceed with caution.
    Inconsistent,
    /// The disk is uninitialized.
    Uninitialized,
}

/// The disk header.
#[derive(Default)]
struct DiskHeader {
    /// The magic number.
    magic_number: MagicNumber,
    /// The version number.
    version_number: u32,
    /// The implementation ID.
    implementation_id: u32,
    /// The cipher.
    cipher: Cipher,
    /// The encryption paramters.
    ///
    /// These are used as defined by the choice of cipher. Some ciphers might use it for salt or
    /// settings, and others not use it at all.
    encryption_parameters: [u8; 16],
    /// The address of the state block.
    state_block_address: clusters::Pointer,
    /// The consistency flag.
    consistency_flag: ConsistencyFlag,
}

impl DiskHeader {
    /// Load the disk header from some disk.
    ///
    /// This will construct it into memory while performing error checks on the header to ensure
    /// correctness.
    fn load<D: Disk>(disk: &mut D) -> Result<DiskHeader, Error> {
        // Load the disk header into a buffer in memory.
        let mut buf = [0; DISK_HEADER_SIZE];
        // Fetch the sector size.
        let sector_size = disk.sector_size();
        // Load the first couple of sectors into `buf`.
        for sector in 0..DISK_HEADER_SIZE / sector_size {
            disk.read(sector, 0, &mut buf[sector * sector_size..])?;
        }

        // Start with some default value, which will be filled out later.
        let mut ret = DiskHeader::default();

        // # Introducer Section
        //
        // This section has the purpose of defining the implementation, version, and type of the
        // disk image. It is rarely changed unless updates or reformatting happens.

        // Load the magic number.
        ret.magic_number = match buf[..8] {
            // Total compatibility.
            b"TFS fmt " => MagicNumber::TotalCompatibility,
            // Partial compatibility.
            b"~TFS fmt" => MagicNumber::PartialCompatibility,
            // Unknown format; abort.
            _ => return Err(Error::UnknownFormat),
        };

        // Load the version number.
        ret.version_number = LittleEndian::read(buf[8..12]);
        // Right after the version number, the same number follows, but bitwise negated. Make sure
        // that these numbers match (if it is bitwise negated). The reason for using this form of
        // code rather than just repeating it as-is is that if one overwrites all bytes with a
        // constant value, like zero, it won't be detected.
        if ret.version_number == !LittleEndian::read(buf[12..16]) {
            // Check if the version is compatible.
            if ret.version_number >> 16 > 0 {
                // The version is not compatible; abort.
                return Err(Error::IncompatibleVersion);
            }
        } else {
            // The version number is corrupt; abort.
            return Err(Error::CorruptVersionNumber);
        }

        // Load the implementation ID.
        ret.implementation_id = LittleEndian::read(buf[16..24]);
        // Similarly to the version number, a bitwise negated repetition follows. Make sure it
        // matches.
        if ret.implementation_id != !LittleEndian::read(buf[24..32]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptImplementationId);
        }

        //////////////// Encryption Section ////////////////

        // Load the encryption algorithm choice.
        ret.cipher = Cipher::from(LittleEndian::read(buf[64..66]))?;
        // Repeat the bitwise negation.
        if ret.cipher as u16 != !LittleEndian::read(buf[66..68]) {
            // The implementation ID is corrupt; abort.
            return Err(Error::CorruptCipher);
        }

        // Load the encryption parameters (e.g. salt).
        self.encryption_parameters.copy_from_slice(&buf[68..84]);
        // Repeat the bitwise negation.
        if self.encryption_parameters.iter().eq(buf[84..100].iter().map(|x| !x)) {
            // The encryption parameters are corrupt; abort.
            return Err(Error::CorruptEncryptionParameters);
        }

        //////////////// State ////////////////

        // Load the state block pointer.
        ret.state_block_address = clusters::Pointer::new(LittleEndian::read(buf[128..136]));
        // Repeat the bitwise negation.
        if ret.state_block_address as u64 != !LittleEndian::read(buf[136..144]) {
            // The state block address is corrupt; abort.
            return Err(Error::CorruptStateBlockAddress);
        }

        // Load the consistency flag.
        self.consistency_flag = ConsistencyFlag::from(buf[144])?;
        // Repeat the bitwise negation.
        if self.consistency_flag as u8 != !buf[145] {
            // The consistency flag is corrupt; abort.
            return Err(Error::CorruptConsistencyFlag);
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)] // Currently unused.

use std::ops::{Deref, DerefMut};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawSocket;
use std::{fmt, io};

#[cfg(unix)]
use crate::poll;
#[cfg(debug_assertions)]
use crate::poll::SelectorId;
use crate::sys::IoSourceState;
use crate::{event, Interest, Registry, Token};

/// Adapter for a [`RawFd`] or [`RawSocket`] providing an [`event::Source`]
/// implementation.
///
/// `IoSource` enables registering any FD or socket wrapper with [`Poll`].
///
/// While only implementations for TCP, UDP, and UDS (Unix only) are provided,
/// Mio supports registering any FD or socket that can be registered with the
/// underlying OS selector. `IoSource` provides the necessary bridge.
///
/// [`RawFd`]: std::os::unix::io::RawFd
/// [`RawSocket`]: std::os::windows::io::RawSocket
///
/// # Notes
///
/// To handle the registrations and events properly **all** I/O operations (such
/// as `read`, `write`, etc.) must go through the [`do_io`] method to ensure the
/// internal state is updated accordingly.
///
/// [`Poll`]: crate::Poll
/// [`do_io`]: IoSource::do_io
/*
///
/// # Examples
///
/// Basic usage.
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Interest, Poll, Token};
/// use mio::IoSource;
///
/// use std::net;
///
/// let poll = Poll::new()?;
///
/// // Bind a std TCP listener.
/// let listener = net::TcpListener::bind("127.0.0.1:0")?;
/// // Wrap it in the `IoSource` type.
/// let mut listener = IoSource::new(listener);
///
/// // Register the listener.
/// poll.registry().register(&mut listener, Token(0), Interest::READABLE)?;
/// #     Ok(())
/// # }
/// ```
*/
pub struct IoSource<T> {
    state: IoSourceState,
    inner: T,
    #[cfg(debug_assertions)]
    selector_id: SelectorId,
}

impl<T> IoSource<T> {
    /// Create a new `IoSource`.
    pub fn new(io: T) -> IoSource<T> {
        IoSource {
            state: IoSourceState::new(),
            inner: io,
            #[cfg(debug_assertions)]
            selector_id: SelectorId::new(),
        }
    }

    /// Execute an I/O operations ensuring that the socket receives more events
    /// if it hit a [`WouldBlock`] error.
    ///
    /// # Notes
    ///
    /// This method is required to be called for **all** I/O operations to
    /// ensure the user will receive events once the socket is ready again after
    /// returning a [`WouldBlock`] error.
    ///
    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
    pub fn do_io<F, R>(&mut self, f: F) -> io::Result<R>
    where
        F: FnOnce(&mut T) -> io::Result<R>,
    {
        self.state.do_io(f, &mut self.inner)
    }

    /// Returns the I/O source, dropping the state.
    ///
    /// # Notes
    ///
    /// To ensure no more events are to be received for this I/O source first
    /// [`deregister`] it.
    ///
    /// [`deregister`]: Registry::deregister
    pub fn into_inner(self) -> T {
        self.inner
    }
}

/// Be careful when using this method. All I/O operations that may block must go
/// through the [`do_io`] method.
///
/// [`do_io`]: IoSource::do_io
impl<T> Deref for IoSource<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

/// Be careful when using this method. All I/O operations that may block must go
/// through the [`do_io`] method.
///
/// [`do_io`]: IoSource::do_io
impl<T> DerefMut for IoSource<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

#[cfg(unix)]
impl<T> event::Source for IoSource<T>
where
    T: AsRawFd,
{
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        #[cfg(debug_assertions)]
        self.selector_id.associate_selector(registry)?;
        poll::selector(registry).register(self.inner.as_raw_fd(), token, interests)
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).reregister(self.inner.as_raw_fd(), token, interests)
    }

    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
        poll::selector(registry).deregister(self.inner.as_raw_fd())
    }
}

#[cfg(windows)]
impl<T> event::Source for IoSource<T>
where
    T: AsRawSocket,
{
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        #[cfg(debug_assertions)]
        self.selector_id.associate_selector(registry)?;
        self.state
            .register(registry, token, interests, self.inner.as_raw_socket())
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        self.state.reregister(registry, token, interests)
    }

    fn deregister(&mut self, _registry: &Registry) -> io::Result<()> {
        self.state.deregister()
    }
}

impl<T> fmt::Debug for IoSource<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}
<commit_msg>Change IoSource::do_io to be by reference<commit_after>#![allow(dead_code)] // Currently unused.

use std::ops::{Deref, DerefMut};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(windows)]
use std::os::windows::io::AsRawSocket;
use std::{fmt, io};

#[cfg(unix)]
use crate::poll;
#[cfg(debug_assertions)]
use crate::poll::SelectorId;
use crate::sys::IoSourceState;
use crate::{event, Interest, Registry, Token};

/// Adapter for a [`RawFd`] or [`RawSocket`] providing an [`event::Source`]
/// implementation.
///
/// `IoSource` enables registering any FD or socket wrapper with [`Poll`].
///
/// While only implementations for TCP, UDP, and UDS (Unix only) are provided,
/// Mio supports registering any FD or socket that can be registered with the
/// underlying OS selector. `IoSource` provides the necessary bridge.
///
/// [`RawFd`]: std::os::unix::io::RawFd
/// [`RawSocket`]: std::os::windows::io::RawSocket
///
/// # Notes
///
/// To handle the registrations and events properly **all** I/O operations (such
/// as `read`, `write`, etc.) must go through the [`do_io`] method to ensure the
/// internal state is updated accordingly.
///
/// [`Poll`]: crate::Poll
/// [`do_io`]: IoSource::do_io
/*
///
/// # Examples
///
/// Basic usage.
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Interest, Poll, Token};
/// use mio::IoSource;
///
/// use std::net;
///
/// let poll = Poll::new()?;
///
/// // Bind a std TCP listener.
/// let listener = net::TcpListener::bind("127.0.0.1:0")?;
/// // Wrap it in the `IoSource` type.
/// let mut listener = IoSource::new(listener);
///
/// // Register the listener.
/// poll.registry().register(&mut listener, Token(0), Interest::READABLE)?;
/// #     Ok(())
/// # }
/// ```
*/
pub struct IoSource<T> {
    state: IoSourceState,
    inner: T,
    #[cfg(debug_assertions)]
    selector_id: SelectorId,
}

impl<T> IoSource<T> {
    /// Create a new `IoSource`.
    pub fn new(io: T) -> IoSource<T> {
        IoSource {
            state: IoSourceState::new(),
            inner: io,
            #[cfg(debug_assertions)]
            selector_id: SelectorId::new(),
        }
    }

    /// Execute an I/O operations ensuring that the socket receives more events
    /// if it hit a [`WouldBlock`] error.
    ///
    /// # Notes
    ///
    /// This method is required to be called for **all** I/O operations to
    /// ensure the user will receive events once the socket is ready again after
    /// returning a [`WouldBlock`] error.
    ///
    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
    pub fn do_io<F, R>(&self, f: F) -> io::Result<R>
    where
        F: FnOnce(&T) -> io::Result<R>,
    {
        self.state.do_io(f, &self.inner)
    }

    /// Returns the I/O source, dropping the state.
    ///
    /// # Notes
    ///
    /// To ensure no more events are to be received for this I/O source first
    /// [`deregister`] it.
    ///
    /// [`deregister`]: Registry::deregister
    pub fn into_inner(self) -> T {
        self.inner
    }
}

/// Be careful when using this method. All I/O operations that may block must go
/// through the [`do_io`] method.
///
/// [`do_io`]: IoSource::do_io
impl<T> Deref for IoSource<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

/// Be careful when using this method. All I/O operations that may block must go
/// through the [`do_io`] method.
///
/// [`do_io`]: IoSource::do_io
impl<T> DerefMut for IoSource<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

#[cfg(unix)]
impl<T> event::Source for IoSource<T>
where
    T: AsRawFd,
{
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        #[cfg(debug_assertions)]
        self.selector_id.associate_selector(registry)?;
        poll::selector(registry).register(self.inner.as_raw_fd(), token, interests)
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        poll::selector(registry).reregister(self.inner.as_raw_fd(), token, interests)
    }

    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
        poll::selector(registry).deregister(self.inner.as_raw_fd())
    }
}

#[cfg(windows)]
impl<T> event::Source for IoSource<T>
where
    T: AsRawSocket,
{
    fn register(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        #[cfg(debug_assertions)]
        self.selector_id.associate_selector(registry)?;
        self.state
            .register(registry, token, interests, self.inner.as_raw_socket())
    }

    fn reregister(
        &mut self,
        registry: &Registry,
        token: Token,
        interests: Interest,
    ) -> io::Result<()> {
        self.state.reregister(registry, token, interests)
    }

    fn deregister(&mut self, _registry: &Registry) -> io::Result<()> {
        self.state.deregister()
    }
}

impl<T> fmt::Debug for IoSource<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(&self.inner, f)
    }
}
<|endoftext|>


<commit_before>// Welcome to Rustlings! If you're here, that means you've either successfully
// downloaded Rustlings, or are looking at this on GitHub. Either way, let me
// introduce you to one of the most basic elements of Rust:
//
// === VARIABLES ===
//
// Variables are essentially little containers that hold, well, something. Think
// of them as a little cardboard box that you put stuff into. What can you put
// into a virtual cardboard box in Rust? All kinds of stuff, it turns out!
// Numbers, words, sequences, and much more. Let's start out simple, though.
// Here's our first exercise:

pub fn exercise_one() {
    let x = 5;
    verify!(0, x, "Number assignment");
    //      ^  ^
    //      |  |
    // What's  The variable
    //  in it  itself
}

// Did you get all that? The "let" word basically tells us that we now want to
// define a variable, and what follows it, the "x" is the name of the variable.
// Each variable has a name, like a label you put on your cardboard box so you
// don't confuse it with another, similar looking one.
// The whole "verify!" deal essentially means that Rustlings is checking if you
// solved the exercise correctly. It compares the first argument with the
// second, so in this case "0" with "x", where "x" is the _value_ of the variable
// we called "x". When you write "x", you pull out the cardboard box labelled "x"
// and take out what's inside of it.
// Speaking of which, what *is* inside of our "x" cardboard box? I don't think it's
// "0"... do you know? Replace the "0" with the value of the variable we defined.
// After that, run "cargo run" in your command line, and see if you put in the
// right answer.

pub fn exec() {
    exercise_one();
}
<commit_msg>small fixes<commit_after>// Welcome to Rustlings! If you're here, that means you've either successfully
// downloaded Rustlings, or are looking at this on GitHub. Either way, let me
// introduce you to one of the most basic elements of Rust:
//
// === VARIABLES ===
//
// Variables are essentially little containers that hold, well, something. Think
// of them as a little cardboard box that you put stuff into. What can you put
// into a virtual cardboard box in Rust? All kinds of stuff, it turns out!
// Numbers, words, sequences, and much more. Let's start out simple, though.
// Here's our first exercise:

pub fn exercise_one() {
    let x = 5;
    verify!(0, x, "Number assignment");
    //      ^  ^
    //      |  |
    // What's  The variable
    //  in it  name
}

// Did you get all that? The "let" word basically tells us that we now want to
// define a variable, and what follows it (the "x") is the name of the variable.
// Each variable has a name, like a label you put on your cardboard box so you
// don't confuse it with another, similar looking one.
// The whole "verify!" deal essentially means that Rustlings is checking if you
// solved the exercise correctly. It compares the first argument with the
// second, so in this case "0" with "x", where "x" is the *value* of the variable
// we called "x". When you write "x", you pull out the cardboard box labelled "x"
// and take out what's inside of it.
// Speaking of which, what *is* inside of our "x" cardboard box? I don't think it's
// "0"... do you know? Replace the "0" with the value of the variable we defined.
// After that, run "cargo run" in your command line, and see if you put in the
// right answer.

pub fn exec() {
    exercise_one();
}
<|endoftext|>


<commit_before>mod page;
pub use self::page::Page;

use std::collections::BTreeMap;
use std::default::Default;
use std::env;
use std::str::FromStr;
use std::time::Duration;

use html5ever::tokenizer::BufferQueue;
use html5ever::tokenizer::Tokenizer;
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
use reqwest::Client as HttpClient;
use reqwest::Response as HttpResponse;
use reqwest::StatusCode;
use robotparser::RobotFileParser;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::RedisPool;
use url::Url;

const MAMAN_ENV: &str = "MAMAN_ENV";
const MAMAN_ENV_DEFAULT: &str = "development";

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Url>,
    pub unvisited_urls: Vec<Url>,
    pub env: String,
    pub limit: isize,
    pub mime_types: Vec<mime::Mime>,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(
        redis_pool: RedisPool,
        base_url: Url,
        limit: isize,
        mime_types: Vec<mime::Mime>,
    ) -> Spider<'a> {
        let maman_env =
            env::var(&MAMAN_ENV.to_owned()).unwrap_or_else(|_| MAMAN_ENV_DEFAULT.to_owned());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts = SidekiqClientOpts {
            namespace: Some(maman_env.to_string()),
        };
        let sidekiq = SidekiqClient::new(redis_pool, client_opts);
        Spider {
            base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit,
            mime_types,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in &page.urls {
            self.unvisited_urls.push(u.clone());
        }
        if let Err(err) = self.sidekiq.push(page.to_job()) {
            error!("SidekiqClient push failed: {}", err);
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref(), &self.mime_types) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref(), &self.mime_types) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        let mut input = BufferQueue::new();
        input.push_back(String::from(document).into());
        let _ = tok.feed(&mut input);
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            info!("{}", page_url);
            if let Some(page) = Spider::read_response(page_url, response) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser.can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url, mut response: HttpResponse) -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for (key, value) in response.headers().iter() {
                headers.insert(
                    key.as_str().to_string(),
                    value.to_str().unwrap_or("").to_string(),
                );
            }
        }
        match response.text() {
            Ok(content) => {
                let page = Page::new(
                    page_url.clone(),
                    content.to_string(),
                    headers,
                    response.status().to_string(),
                );
                let read = Spider::read_page(page, &content);
                Some(read.sink)
            }
            _ => None,
        }
    }

    fn load_url(url: &str, mime_types: &[mime::Mime]) -> Option<HttpResponse> {
        let client = HttpClient::builder()
            .timeout(Duration::from_secs(5))
            .build()
            .expect("HttpClient failed to construct");
        match client
            .get(url)
            .header(USER_AGENT, maman_user_agent!())
            .send()
        {
            Err(_) => None,
            Ok(response) => match response.status() {
                StatusCode::OK | StatusCode::NOT_MODIFIED => {
                    if mime_types.is_empty() {
                        Some(response)
                    } else {
                        let content_type = response
                            .headers()
                            .get(CONTENT_TYPE)
                            .and_then(|value| value.to_str().ok())
                            .and_then(|value| value.parse::<mime::Mime>().ok())
                            .and_then(|value| match (value.type_(), value.subtype()) {
                                (type_, subtype) => {
                                    let mut text = type_.to_string();
                                    text.push_str("/");
                                    text.push_str(subtype.as_ref());
                                    mime::Mime::from_str(&text).ok()
                                }
                            });
                        match content_type {
                            Some(ct) => {
                                if mime_types.contains(&ct) {
                                    Some(response)
                                } else {
                                    None
                                }
                            }
                            None => None,
                        }
                    }
                }
                _ => None,
            },
        }
    }
}
<commit_msg>Rewrite match with let statement<commit_after>mod page;
pub use self::page::Page;

use std::collections::BTreeMap;
use std::default::Default;
use std::env;
use std::str::FromStr;
use std::time::Duration;

use html5ever::tokenizer::BufferQueue;
use html5ever::tokenizer::Tokenizer;
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
use reqwest::Client as HttpClient;
use reqwest::Response as HttpResponse;
use reqwest::StatusCode;
use robotparser::RobotFileParser;
use sidekiq::Client as SidekiqClient;
use sidekiq::ClientOpts as SidekiqClientOpts;
use sidekiq::RedisPool;
use url::Url;

const MAMAN_ENV: &str = "MAMAN_ENV";
const MAMAN_ENV_DEFAULT: &str = "development";

pub struct Spider<'a> {
    pub base_url: Url,
    pub visited_urls: Vec<Url>,
    pub unvisited_urls: Vec<Url>,
    pub env: String,
    pub limit: isize,
    pub mime_types: Vec<mime::Mime>,
    sidekiq: SidekiqClient,
    robot_parser: RobotFileParser<'a>,
}

impl<'a> Spider<'a> {
    pub fn new(
        redis_pool: RedisPool,
        base_url: Url,
        limit: isize,
        mime_types: Vec<mime::Mime>,
    ) -> Spider<'a> {
        let maman_env =
            env::var(&MAMAN_ENV.to_owned()).unwrap_or_else(|_| MAMAN_ENV_DEFAULT.to_owned());
        let robots_txt = base_url.join("/robots.txt").unwrap();
        let robot_file_parser = RobotFileParser::new(robots_txt);
        let client_opts = SidekiqClientOpts {
            namespace: Some(maman_env.to_string()),
        };
        let sidekiq = SidekiqClient::new(redis_pool, client_opts);
        Spider {
            base_url,
            visited_urls: Vec::new(),
            unvisited_urls: Vec::new(),
            sidekiq,
            env: maman_env,
            robot_parser: robot_file_parser,
            limit,
            mime_types,
        }
    }

    pub fn visit_page(&mut self, page: Page) {
        self.visited_urls.push(page.url.clone());
        for u in &page.urls {
            self.unvisited_urls.push(u.clone());
        }
        if let Err(err) = self.sidekiq.push(page.to_job()) {
            error!("SidekiqClient push failed: {}", err);
        }
    }

    pub fn crawl(&mut self) {
        self.robot_parser.read();
        let base_url = self.base_url.clone();
        if let Some(response) = Spider::load_url(self.base_url.as_ref(), &self.mime_types) {
            self.visit(&base_url, response);
            while let Some(url) = self.unvisited_urls.pop() {
                if self.continue_to_crawl() {
                    if !self.visited_urls.contains(&url) {
                        if let Some(response) = Spider::load_url(url.as_ref(), &self.mime_types) {
                            self.visit(&url, response);
                        }
                    }
                } else {
                    break;
                }
            }
        }
    }

    pub fn read_page(page: Page, document: &str) -> Tokenizer<Page> {
        let mut tok = Tokenizer::new(page, Default::default());
        let mut input = BufferQueue::new();
        input.push_back(String::from(document).into());
        let _ = tok.feed(&mut input);
        tok.end();
        tok
    }

    fn visit(&mut self, page_url: &Url, response: HttpResponse) {
        if self.can_visit(page_url) {
            info!("{}", page_url);
            if let Some(page) = Spider::read_response(page_url, response) {
                self.visit_page(page);
            }
        }
    }

    fn continue_to_crawl(&self) -> bool {
        self.limit == 0 || (self.visited_urls.len() as isize) < self.limit
    }

    fn can_visit(&self, page_url: &Url) -> bool {
        self.robot_parser.can_fetch(maman_name!(), page_url.path())
    }

    fn read_response(page_url: &Url, mut response: HttpResponse) -> Option<Page> {
        let mut headers = BTreeMap::new();
        {
            for (key, value) in response.headers().iter() {
                headers.insert(
                    key.as_str().to_string(),
                    value.to_str().unwrap_or("").to_string(),
                );
            }
        }
        match response.text() {
            Ok(content) => {
                let page = Page::new(
                    page_url.clone(),
                    content.to_string(),
                    headers,
                    response.status().to_string(),
                );
                let read = Spider::read_page(page, &content);
                Some(read.sink)
            }
            _ => None,
        }
    }

    fn load_url(url: &str, mime_types: &[mime::Mime]) -> Option<HttpResponse> {
        let client = HttpClient::builder()
            .timeout(Duration::from_secs(5))
            .build()
            .expect("HttpClient failed to construct");
        match client
            .get(url)
            .header(USER_AGENT, maman_user_agent!())
            .send()
        {
            Err(_) => None,
            Ok(response) => match response.status() {
                StatusCode::OK | StatusCode::NOT_MODIFIED => {
                    if mime_types.is_empty() {
                        Some(response)
                    } else {
                        let content_type = response
                            .headers()
                            .get(CONTENT_TYPE)
                            .and_then(|value| value.to_str().ok())
                            .and_then(|value| value.parse::<mime::Mime>().ok())
                            .and_then(|value| {
                                let (type_, subtype) = (value.type_(), value.subtype());
                                {
                                    let mut text = type_.to_string();
                                    text.push_str("/");
                                    text.push_str(subtype.as_ref());
                                    mime::Mime::from_str(&text).ok()
                                }
                            });
                        match content_type {
                            Some(ct) => {
                                if mime_types.contains(&ct) {
                                    Some(response)
                                } else {
                                    None
                                }
                            }
                            None => None,
                        }
                    }
                }
                _ => None,
            },
        }
    }
}
<|endoftext|>


<commit_before>use syntax::{
    algo::SyntaxRewriter,
    ast::{self, edit::AstNodeEdit, VisibilityOwner},
    AstNode, SyntaxKind,
};

use crate::{
    assist_context::{AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: unmerge_use
//
// Extracts single use item from use list.
//
// ```
// use std::fmt::{Debug, Display$0};
// ```
// ->
// ```
// use std::fmt::{Debug};
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let tree: ast::UseTree = ctx.find_node_at_offset()?;

    let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
    if tree_list.use_trees().count() < 2 {
        return None;
    }

    let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
    let path = resolve_full_path(&tree)?;

    let target = tree.syntax().text_range();
    acc.add(
        AssistId("unmerge_use", AssistKind::RefactorRewrite),
        "Unmerge use",
        target,
        |builder| {
            let new_use = ast::make::use_(
                use_.visibility(),
                ast::make::use_tree(
                    path,
                    tree.use_tree_list(),
                    tree.rename(),
                    tree.star_token().is_some(),
                ),
            );

            let mut rewriter = SyntaxRewriter::default();
            rewriter += tree.remove();
            rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline());
            if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize {
                rewriter.insert_after(
                    use_.syntax(),
                    &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)),
                );
            }
            rewriter.insert_after(use_.syntax(), new_use.syntax());

            builder.rewrite(rewriter);
        },
    )
}

fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
    let mut paths = tree
        .syntax()
        .ancestors()
        .take_while(|n| n.kind() != SyntaxKind::USE_KW)
        .filter_map(ast::UseTree::cast)
        .filter_map(|t| t.path());

    let mut final_path = paths.next()?;
    for path in paths {
        final_path = ast::make::path_concat(path, final_path)
    }
    Some(final_path)
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn skip_single_use_item() {
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug$0;
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::{Debug$0};
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug as Dbg$0;
",
        );
    }

    #[test]
    fn skip_single_glob_import() {
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::*$0;
",
        );
    }

    #[test]
    fn unmerge_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display;
",
        );

        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, format$0, Display};
",
            r"
use std::fmt::{Debug, Display};
use std::fmt::format;
",
        );
    }

    #[test]
    fn unmerge_glob_import() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{*$0, Display};
",
            r"
use std::fmt::{Display};
use std::fmt::*;
",
        );
    }

    #[test]
    fn unmerge_renamed_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display as Disp$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display as Disp;
",
        );
    }

    #[test]
    fn unmerge_indented_use_item() {
        check_assist(
            unmerge_use,
            r"
mod format {
    use std::fmt::{Debug, Display$0 as Disp, format};
}
",
            r"
mod format {
    use std::fmt::{Debug, format};
    use std::fmt::Display as Disp;
}
",
        );
    }

    #[test]
    fn unmerge_nested_use_item() {
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz::{qux$0, foobar}, barbaz};
",
            r"
use foo::bar::{baz::{foobar}, barbaz};
use foo::bar::baz::qux;
",
        );
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz$0::{qux, foobar}, barbaz};
",
            r"
use foo::bar::{barbaz};
use foo::bar::baz::{qux, foobar};
",
        );
    }

    #[test]
    fn unmerge_use_item_with_visibility() {
        check_assist(
            unmerge_use,
            r"
pub use std::fmt::{Debug, Display$0};
",
            r"
pub use std::fmt::{Debug};
pub use std::fmt::Display;
",
        );
    }
}
<commit_msg>Add test mark for skipping single use item<commit_after>use syntax::{
    algo::SyntaxRewriter,
    ast::{self, edit::AstNodeEdit, VisibilityOwner},
    AstNode, SyntaxKind,
};
use test_utils::mark;

use crate::{
    assist_context::{AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: unmerge_use
//
// Extracts single use item from use list.
//
// ```
// use std::fmt::{Debug, Display$0};
// ```
// ->
// ```
// use std::fmt::{Debug};
// use std::fmt::Display;
// ```
pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let tree: ast::UseTree = ctx.find_node_at_offset()?;

    let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
    if tree_list.use_trees().count() < 2 {
        mark::hit!(skip_single_use_item);
        return None;
    }

    let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
    let path = resolve_full_path(&tree)?;

    let target = tree.syntax().text_range();
    acc.add(
        AssistId("unmerge_use", AssistKind::RefactorRewrite),
        "Unmerge use",
        target,
        |builder| {
            let new_use = ast::make::use_(
                use_.visibility(),
                ast::make::use_tree(
                    path,
                    tree.use_tree_list(),
                    tree.rename(),
                    tree.star_token().is_some(),
                ),
            );

            let mut rewriter = SyntaxRewriter::default();
            rewriter += tree.remove();
            rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline());
            if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize {
                rewriter.insert_after(
                    use_.syntax(),
                    &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)),
                );
            }
            rewriter.insert_after(use_.syntax(), new_use.syntax());

            builder.rewrite(rewriter);
        },
    )
}

fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
    let mut paths = tree
        .syntax()
        .ancestors()
        .take_while(|n| n.kind() != SyntaxKind::USE_KW)
        .filter_map(ast::UseTree::cast)
        .filter_map(|t| t.path());

    let mut final_path = paths.next()?;
    for path in paths {
        final_path = ast::make::path_concat(path, final_path)
    }
    Some(final_path)
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn skip_single_use_item() {
        mark::check!(skip_single_use_item);
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug$0;
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::{Debug$0};
",
        );
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::Debug as Dbg$0;
",
        );
    }

    #[test]
    fn skip_single_glob_import() {
        check_assist_not_applicable(
            unmerge_use,
            r"
use std::fmt::*$0;
",
        );
    }

    #[test]
    fn unmerge_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display;
",
        );

        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, format$0, Display};
",
            r"
use std::fmt::{Debug, Display};
use std::fmt::format;
",
        );
    }

    #[test]
    fn unmerge_glob_import() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{*$0, Display};
",
            r"
use std::fmt::{Display};
use std::fmt::*;
",
        );
    }

    #[test]
    fn unmerge_renamed_use_item() {
        check_assist(
            unmerge_use,
            r"
use std::fmt::{Debug, Display as Disp$0};
",
            r"
use std::fmt::{Debug};
use std::fmt::Display as Disp;
",
        );
    }

    #[test]
    fn unmerge_indented_use_item() {
        check_assist(
            unmerge_use,
            r"
mod format {
    use std::fmt::{Debug, Display$0 as Disp, format};
}
",
            r"
mod format {
    use std::fmt::{Debug, format};
    use std::fmt::Display as Disp;
}
",
        );
    }

    #[test]
    fn unmerge_nested_use_item() {
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz::{qux$0, foobar}, barbaz};
",
            r"
use foo::bar::{baz::{foobar}, barbaz};
use foo::bar::baz::qux;
",
        );
        check_assist(
            unmerge_use,
            r"
use foo::bar::{baz$0::{qux, foobar}, barbaz};
",
            r"
use foo::bar::{barbaz};
use foo::bar::baz::{qux, foobar};
",
        );
    }

    #[test]
    fn unmerge_use_item_with_visibility() {
        check_assist(
            unmerge_use,
            r"
pub use std::fmt::{Debug, Display$0};
",
            r"
pub use std::fmt::{Debug};
pub use std::fmt::Display;
",
        );
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use cita_database::error::DatabaseError;
use cita_database::{DataCategory, Database};
use parking_lot::RwLock;
use std::collections::HashMap;

#[derive(Debug)]
pub struct TrieDB<DB>
where
    DB: Database,
{
    db: Arc<DB>,
    cache: Arc<RwLock<HashMap<Vec<u8>, Vec<u8>>>>,
}

impl<DB> TrieDB<DB>
where
    DB: Database,
{
    pub fn new(db: Arc<DB>) -> Self {
        TrieDB {
            db,
            cache: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    pub fn database(&self) -> Arc<DB> {
        self.db.clone()
    }
}

/// "TrieDB" provides state read/write capabilities for executor.
impl<DB> cita_trie::DB for TrieDB<DB>
where
    DB: Database,
{
    type Error = DatabaseError;

    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
        match self.cache.read().get(key) {
            Some(v) => Ok(Some(v.to_vec())),
            None => self.db.get(Some(DataCategory::State), key),
        }
    }

    fn insert(&self, key: Vec<u8>, value: Vec<u8>) -> Result<(), Self::Error> {
        self.cache.write().insert(key, value);
        Ok(())
    }

    fn contains(&self, key: &[u8]) -> Result<bool, Self::Error> {
        if self.cache.read().contains_key(key) {
            Ok(true)
        } else {
            self.db.contains(Some(DataCategory::State), key)
        }
    }

    fn remove(&self, _key: &[u8]) -> Result<(), Self::Error> {
        unimplemented!()
    }

    fn insert_batch(&self, keys: Vec<Vec<u8>>, values: Vec<Vec<u8>>) -> Result<(), Self::Error> {
        let mut cache = self.cache.write();
        for i in 0..keys.len() {
            let key = keys[i].clone();
            let value = values[i].clone();
            cache.insert(key, value);
        }
        Ok(())
    }

    fn remove_batch(&self, _keys: &[Vec<u8>]) -> Result<(), Self::Error> {
        unimplemented!()
    }

    fn flush(&self) -> Result<(), Self::Error> {
        let len = self.cache.read().len();
        let mut keys = Vec::with_capacity(len);
        let mut values = Vec::with_capacity(len);

        for (key, value) in self.cache.write().drain() {
            keys.push(key);
            values.push(value);
        }

        self.db
            .insert_batch(Some(DataCategory::State), keys.to_vec(), values.to_vec())
    }
}

impl<DB> Clone for TrieDB<DB>
where
    DB: Database,
{
    fn clone(&self) -> Self {
        TrieDB {
            db: Arc::clone(&self.db),
            cache: Arc::clone(&self.cache),
        }
    }
}
<commit_msg>[skip ci]impl triedb func (#728)<commit_after>use std::sync::Arc;

use cita_database::error::DatabaseError;
use cita_database::{DataCategory, Database};
use parking_lot::RwLock;
use std::collections::HashMap;

#[derive(Debug)]
pub struct TrieDB<DB>
where
    DB: Database,
{
    db: Arc<DB>,
    cache: Arc<RwLock<HashMap<Vec<u8>, Vec<u8>>>>,
}

impl<DB> TrieDB<DB>
where
    DB: Database,
{
    pub fn new(db: Arc<DB>) -> Self {
        TrieDB {
            db,
            cache: Arc::new(RwLock::new(HashMap::new())),
        }
    }
}

/// "TrieDB" provides state read/write capabilities for executor.
impl<DB> cita_trie::DB for TrieDB<DB>
where
    DB: Database,
{
    type Error = DatabaseError;

    fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
        match self.cache.read().get(key) {
            Some(v) => Ok(Some(v.to_vec())),
            None => self.db.get(Some(DataCategory::State), key),
        }
    }

    fn insert(&self, key: Vec<u8>, value: Vec<u8>) -> Result<(), Self::Error> {
        self.cache.write().insert(key, value);
        Ok(())
    }

    fn contains(&self, key: &[u8]) -> Result<bool, Self::Error> {
        if self.cache.read().contains_key(key) {
            Ok(true)
        } else {
            self.db.contains(Some(DataCategory::State), key)
        }
    }

    fn remove(&self, key: &[u8]) -> Result<(), Self::Error> {
        self.cache.write().remove(key);
        self.db.remove(Some(DataCategory::State), key)
    }

    fn insert_batch(&self, keys: Vec<Vec<u8>>, values: Vec<Vec<u8>>) -> Result<(), Self::Error> {
        let mut cache = self.cache.write();
        for i in 0..keys.len() {
            let key = keys[i].clone();
            let value = values[i].clone();
            cache.insert(key, value);
        }
        Ok(())
    }

    fn remove_batch(&self, keys: &[Vec<u8>]) -> Result<(), Self::Error> {
        {
            let mut cache = self.cache.write();
            for key in keys {
                cache.remove(key);
            }
        }
        self.db.remove_batch(Some(DataCategory::State), keys)
    }

    fn flush(&self) -> Result<(), Self::Error> {
        let len = self.cache.read().len();
        let mut keys = Vec::with_capacity(len);
        let mut values = Vec::with_capacity(len);

        for (key, value) in self.cache.write().drain() {
            keys.push(key);
            values.push(value);
        }

        self.db
            .insert_batch(Some(DataCategory::State), keys.to_vec(), values.to_vec())
    }
}

impl<DB> Clone for TrieDB<DB>
where
    DB: Database,
{
    fn clone(&self) -> Self {
        TrieDB {
            db: Arc::clone(&self.db),
            cache: Arc::clone(&self.cache),
        }
    }
}
<|endoftext|>


<commit_before>//! Power Management Unit (PMU)
//!
//! The Power Management Unit (PMU) controls the chip's power states and clock
//! power, as well as allows the chip to interface with peripherals at different
//! voltage levels.
//!
//! There are three types of power domains:
//!
//!   1. VDDIOMR:
//!
//!     * Always-on main I/O voltage supply domain necessary for the running the
//!       core.
//!     * Nominal 3.3V
//!
//!   2. VDDIOA & VDDIOB:
//!
//!     * I/O voltage supply domains for external peripherals.
//!
//!     * Can be shut down at any moment (not critical for core functions).
//!
//!     * Designed for 1.8-3.6V
//!
//!   3. VDDIOF:
//!
//!     * I/O voltage supply domain for flash memory.
//!
//!     * Designed for 1.8-3.6V
//!

use common::volatile_cell::VolatileCell;
use core::mem::transmute;

/// Registers for the Power Management Unit (PMU)
// Non-public fields prefixed with "_" mark unused registers
#[repr(C, packed)]
pub struct PMURegisters {
    _reset: VolatileCell<u32>,
    _set_reset: VolatileCell<u32>,

    /// Clear register for the reset source
    pub clear_reset: VolatileCell<u32>,

    /// Status for source of last reset event
    ///
    /// Bits 0-7 correspond to:
    ///
    /// | bit | Description                                       |
    /// | --- | :------------------------------------------------ |
    /// | 0   | Power on reset                                    |
    /// | 1   | Low power exit                                    |
    /// | 2   | Watchdog reset                                    |
    /// | 3   | Lockup reset                                      |
    /// | 4   | SYSRESET                                          |
    /// | 5   | Software initiated reset through PMU_GLOBAL_RESET |
    /// | 6   | Fast burnout circuit                              |
    /// | 7   | Security breach reset                             |
    ///
    pub reset_source: VolatileCell<u32>,

    /// Global chip reset
    ///
    /// Initiates a reset of the system similar to toggling the external reset
    /// pin. To initiate a reset, write the key 0x7041776 to this register.
    pub global_reset: VolatileCell<u32>,

    pub low_power_disable: VolatileCell<u32>,

    pub low_power_bypass: VolatileCell<u32>,

    pub low_power_bypass_value: VolatileCell<u32>,

    pub set_wakeup_interrupt_controller: VolatileCell<u32>,

    pub clear_wakeup_interrupt_controller: VolatileCell<u32>,

    /// Value of the system vector table offset
    pub sysvtor: VolatileCell<u32>,

    /// Enable PMU to gate some clocks when processor is sleeping
    pub nap_enable: VolatileCell<u32>,

    _pmu_sw_pdb: VolatileCell<u32>,
    _pmu_vref: VolatileCell<u32>,
    _xtl_osc_bypass: VolatileCell<u32>,
    _flash_tm0_test_en_bypass: VolatileCell<u32>,

    /// Battery level indicator
    ///
    /// When non-zero, the voltage level is higher than specified in the vref
    /// register's BATMON field.
    pub battery_level_ok: VolatileCell<u32>,

    _b_reg_dig_ctrl: VolatileCell<u32>,
    _exitpd_mask: VolatileCell<u32>,
    _exitpd_src: VolatileCell<u32>,
    _exitpd_mon: VolatileCell<u32>,
    _osc_ctrl: VolatileCell<u32>,

    /// Turn on clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_set: VolatileCell<u32>,

    /// Turn off clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_clear: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_disable: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_disable: VolatileCell<u32>,
}

const PMU_BASE: isize = 0x40000000;

static mut PMU: *mut PMURegisters = PMU_BASE as *mut PMURegisters;

#[derive(Clone,Copy)]
pub enum PeripheralClock0 {
    Camo0,
    Crpyto0,
    Dma0,
    Flash0,
    Fuse0,
    GlobalSec,
    GlobalSecTimer,
    GlobalSecHs,
    Gpio0,
    Gpio1,
    I2C0,
    I2C1,
    I2CS0,
    KeyMgr0,
    PeriAPB0,
    PeriAPB1,
    PeriAPB2,
    PeriAPB2Timer,
    PeriAPB3,
    PeriAPB3Timer,
    PeriAPB3HS,
    PinMux,
    Pmu,
    RBox0,
    Rdd0,
    Rtc0,
    Rtc0Timer,
    Spi0Hs,
    Spi1Hs,
    Sps0,
    Sps0TimerHs,
    Swdp0,
    Temp0
}

#[derive(Clone,Copy)]
pub enum PeripheralClock1 {
    TimeHs0Timer,
    TimeHs1Timer,
    TimeLs0,
    TimeUs0Timer,
    Trng0,
    Uart0Timer,
    Uart1Timer,
    Uart2Timer,
    Usb0,
    Usb0TimerHs,
    Volt0,
    Watchdog0,
    Xo0,
    Xo0Timer,
    PeripheralMasterMatrix,
    PeripheralMatrix
}

#[derive(Clone,Copy)]
pub enum PeripheralClock {
    Bank0(PeripheralClock0),
    Bank1(PeripheralClock1)
}

/// Wrapper struct around `PeripheralClock` that can only be created by.
/// trusted code.
#[derive(Clone,Copy)]
pub struct Clock {
    // It's important that this field is private!
    clock: PeripheralClock
}

impl Clock {
    pub unsafe fn new(clock: PeripheralClock) -> Clock {
        Clock { clock: clock }
    }

    pub fn enable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_enable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_enable.set(1 << (clock as u32));
            }
        }
    }

    pub fn disable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_disable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_disable.set(1 << (clock as u32));
            }
        }
    }
}

<commit_msg>Hotel: Fix PMU off-by-one-register bug<commit_after>//! Power Management Unit (PMU)
//!
//! The Power Management Unit (PMU) controls the chip's power states and clock
//! power, as well as allows the chip to interface with peripherals at different
//! voltage levels.
//!
//! There are three types of power domains:
//!
//!   1. VDDIOMR:
//!
//!     * Always-on main I/O voltage supply domain necessary for the running the
//!       core.
//!     * Nominal 3.3V
//!
//!   2. VDDIOA & VDDIOB:
//!
//!     * I/O voltage supply domains for external peripherals.
//!
//!     * Can be shut down at any moment (not critical for core functions).
//!
//!     * Designed for 1.8-3.6V
//!
//!   3. VDDIOF:
//!
//!     * I/O voltage supply domain for flash memory.
//!
//!     * Designed for 1.8-3.6V
//!

use common::volatile_cell::VolatileCell;
use core::mem::transmute;

/// Registers for the Power Management Unit (PMU)
// Non-public fields prefixed with "_" mark unused registers
#[repr(C, packed)]
pub struct PMURegisters {
    _reset: VolatileCell<u32>,
    _set_reset: VolatileCell<u32>,

    /// Clear register for the reset source
    pub clear_reset: VolatileCell<u32>,

    /// Status for source of last reset event
    ///
    /// Bits 0-7 correspond to:
    ///
    /// | bit | Description                                       |
    /// | --- | :------------------------------------------------ |
    /// | 0   | Power on reset                                    |
    /// | 1   | Low power exit                                    |
    /// | 2   | Watchdog reset                                    |
    /// | 3   | Lockup reset                                      |
    /// | 4   | SYSRESET                                          |
    /// | 5   | Software initiated reset through PMU_GLOBAL_RESET |
    /// | 6   | Fast burnout circuit                              |
    /// | 7   | Security breach reset                             |
    ///
    pub reset_source: VolatileCell<u32>,

    /// Global chip reset
    ///
    /// Initiates a reset of the system similar to toggling the external reset
    /// pin. To initiate a reset, write the key 0x7041776 to this register.
    pub global_reset: VolatileCell<u32>,

    pub low_power_disable: VolatileCell<u32>,

    pub low_power_bypass: VolatileCell<u32>,

    pub low_power_bypass_value: VolatileCell<u32>,

    pub set_wakeup_interrupt_controller: VolatileCell<u32>,

    pub clear_wakeup_interrupt_controller: VolatileCell<u32>,

    /// Value of the system vector table offset
    pub sysvtor: VolatileCell<u32>,

    /// Enable PMU to gate some clocks when processor is sleeping
    pub nap_enable: VolatileCell<u32>,

    _pmu_sw_pdb: VolatileCell<u32>,
    _pmu_sw_pdb_secure: VolatileCell<u32>,
    _pmu_vref: VolatileCell<u32>,
    _xtl_osc_bypass: VolatileCell<u32>,
    _flash_tm0_test_en_bypass: VolatileCell<u32>,

    /// Battery level indicator
    ///
    /// When non-zero, the voltage level is higher than specified in the vref
    /// register's BATMON field.
    pub battery_level_ok: VolatileCell<u32>,

    _b_reg_dig_ctrl: VolatileCell<u32>,
    _exitpd_mask: VolatileCell<u32>,
    _exitpd_src: VolatileCell<u32>,
    _exitpd_mon: VolatileCell<u32>,
    _osc_ctrl: VolatileCell<u32>,

    /// Turn on clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_set: VolatileCell<u32>,

    /// Turn off clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_clear: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_disable: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_disable: VolatileCell<u32>,
}

const PMU_BASE: isize = 0x40000000;

static mut PMU: *mut PMURegisters = PMU_BASE as *mut PMURegisters;

#[derive(Clone,Copy)]
pub enum PeripheralClock0 {
    Camo0,
    Crpyto0,
    Dma0,
    Flash0,
    Fuse0,
    GlobalSec,
    GlobalSecTimer,
    GlobalSecHs,
    Gpio0,
    Gpio1,
    I2C0,
    I2C1,
    I2CS0,
    KeyMgr0,
    PeriAPB0,
    PeriAPB1,
    PeriAPB2,
    PeriAPB2Timer,
    PeriAPB3,
    PeriAPB3Timer,
    PeriAPB3HS,
    PinMux,
    Pmu,
    RBox0,
    Rdd0,
    Rtc0,
    Rtc0Timer,
    Spi0Hs,
    Spi1Hs,
    Sps0,
    Sps0TimerHs,
    Swdp0,
    Temp0
}

#[derive(Clone,Copy)]
pub enum PeripheralClock1 {
    TimeHs0Timer,
    TimeHs1Timer,
    TimeLs0,
    TimeUs0Timer,
    Trng0,
    Uart0Timer,
    Uart1Timer,
    Uart2Timer,
    Usb0,
    Usb0TimerHs,
    Volt0,
    Watchdog0,
    Xo0,
    Xo0Timer,
    PeripheralMasterMatrix,
    PeripheralMatrix
}

#[derive(Clone,Copy)]
pub enum PeripheralClock {
    Bank0(PeripheralClock0),
    Bank1(PeripheralClock1)
}

/// Wrapper struct around `PeripheralClock` that can only be created by.
/// trusted code.
#[derive(Clone,Copy)]
pub struct Clock {
    // It's important that this field is private!
    clock: PeripheralClock
}

impl Clock {
    pub unsafe fn new(clock: PeripheralClock) -> Clock {
        Clock { clock: clock }
    }

    pub fn enable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_enable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_enable.set(1 << (clock as u32));
            }
        }
    }

    pub fn disable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_disable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_disable.set(1 << (clock as u32));
            }
        }
    }
}

<|endoftext|>