<commit_before>#[macro_use]
extern crate askama;

use askama::Template;

#[derive(Template)]
#[template(path = "simple.html")]
struct VariablesTemplate<'a> {
    strvar: &'a str,
    num: i64,
    i18n: String,
}

#[test]
fn test_variables() {
    let s = VariablesTemplate {
        strvar: "foo",
        num: 42,
        i18n: "Iñtërnâtiônàlizætiøn".to_string(),
    };
    assert_eq!(
        s.render().unwrap(),
        "\nhello world, foo\n\
         with number: 42\n\
         Iñtërnâtiônàlizætiøn is important\n\
         in vars too: Iñtërnâtiônàlizætiøn"
    );
}

#[derive(Template)]
#[template(path = "if.html")]
struct IfTemplate {
    cond: bool,
}

#[test]
fn test_if() {
    let s = IfTemplate { cond: true };
    assert_eq!(s.render().unwrap(), "true");
}

#[derive(Template)]
#[template(path = "else.html")]
struct ElseTemplate {
    cond: bool,
}

#[test]
fn test_else() {
    let s = ElseTemplate { cond: false };
    assert_eq!(s.render().unwrap(), "false");
}

#[derive(Template)]
#[template(path = "else-if.html")]
struct ElseIfTemplate {
    cond: bool,
    check: bool,
}

#[test]
fn test_else_if() {
    let s = ElseIfTemplate {
        cond: false,
        check: true,
    };
    assert_eq!(s.render().unwrap(), "checked");
}

#[derive(Template)]
#[template(path = "literals.html")]
struct LiteralsTemplate {}

#[test]
fn test_literals() {
    let s = LiteralsTemplate {};
    assert_eq!(s.render().unwrap(), "a");
}

struct Holder {
    a: usize,
}

#[derive(Template)]
#[template(path = "attr.html")]
struct AttrTemplate {
    inner: Holder,
}

#[test]
fn test_attr() {
    let t = AttrTemplate {
        inner: Holder { a: 5 },
    };
    assert_eq!(t.render().unwrap(), "5");
}

#[derive(Template)]
#[template(path = "tuple-attr.html")]
struct TupleAttrTemplate<'a> {
    tuple: (&'a str, &'a str),
}

#[test]
fn test_tuple_attr() {
    let t = TupleAttrTemplate {
        tuple: ("foo", "bar"),
    };
    assert_eq!(t.render().unwrap(), "foobar");
}

struct NestedHolder {
    holder: Holder,
}

#[derive(Template)]
#[template(path = "nested-attr.html")]
struct NestedAttrTemplate {
    inner: NestedHolder,
}

#[test]
fn test_nested_attr() {
    let t = NestedAttrTemplate {
        inner: NestedHolder {
            holder: Holder { a: 5 },
        },
    };
    assert_eq!(t.render().unwrap(), "5");
}

#[derive(Template)]
#[template(path = "option.html")]
struct OptionTemplate<'a> {
    var: Option<&'a str>,
}

#[test]
fn test_option() {
    let some = OptionTemplate { var: Some("foo") };
    assert_eq!(some.render().unwrap(), "some: foo");
    let none = OptionTemplate { var: None };
    assert_eq!(none.render().unwrap(), "none");
}

#[derive(Template)]
#[template(path = "generics.html")]
struct GenericsTemplate<T: std::fmt::Display, U = u8>
where
    U: std::fmt::Display,
{
    t: T,
    u: U,
}

#[test]
fn test_generics() {
    let t = GenericsTemplate { t: "a", u: 42 };
    assert_eq!(t.render().unwrap(), "a42");
}

#[derive(Template)]
#[template(path = "composition.html")]
struct CompositionTemplate {
    foo: IfTemplate,
}

#[test]
fn test_composition() {
    let t = CompositionTemplate {
        foo: IfTemplate { cond: true },
    };
    assert_eq!(t.render().unwrap(), "composed: true");
}

#[derive(PartialEq, Eq)]
enum Alphabet {
    Alpha,
}

#[derive(Template)]
#[template(source = "{% if x == Alphabet::Alpha %}true{% endif %}", ext = "txt")]
struct PathCompareTemplate {
    x: Alphabet,
}

#[test]
fn test_path_compare() {
    let t = PathCompareTemplate { x: Alphabet::Alpha };
    assert_eq!(t.render().unwrap(), "true");
}

#[derive(Template)]
#[template(source = "{% for i in [\"a\", \"\"] %}{{ i }}{% endfor %}", ext = "txt")]
struct ArrayTemplate {}

#[test]
fn test_slice_literal() {
    let t = ArrayTemplate {};
    assert_eq!(t.render().unwrap(), "a");
}

#[derive(Template)]
#[template(source = "  {# foo -#} ", ext = "txt")]
struct CommentTemplate {}

#[test]
fn test_comment() {
    let t = CommentTemplate {};
    assert_eq!(t.render().unwrap(), "  ");
}

#[derive(Template)]
#[template(source = "{% if !foo %}Hello{% endif %}", ext = "txt")]
struct NegationTemplate {
    foo: bool,
}

#[test]
fn test_negation() {
    let t = NegationTemplate { foo: false };
    assert_eq!(t.render().unwrap(), "Hello");
}

#[derive(Template)]
#[template(source = "{% if foo > -2 %}Hello{% endif %}", ext = "txt")]
struct MinusTemplate {
    foo: i8,
}

#[test]
fn test_minus() {
    let t = MinusTemplate { foo: 1 };
    assert_eq!(t.render().unwrap(), "Hello");
}
<commit_msg>Add test for Index operation<commit_after>#[macro_use]
extern crate askama;

use askama::Template;

use std::collections::HashMap;

#[derive(Template)]
#[template(path = "simple.html")]
struct VariablesTemplate<'a> {
    strvar: &'a str,
    num: i64,
    i18n: String,
}

#[test]
fn test_variables() {
    let s = VariablesTemplate {
        strvar: "foo",
        num: 42,
        i18n: "Iñtërnâtiônàlizætiøn".to_string(),
    };
    assert_eq!(
        s.render().unwrap(),
        "\nhello world, foo\n\
         with number: 42\n\
         Iñtërnâtiônàlizætiøn is important\n\
         in vars too: Iñtërnâtiônàlizætiøn"
    );
}

#[derive(Template)]
#[template(path = "if.html")]
struct IfTemplate {
    cond: bool,
}

#[test]
fn test_if() {
    let s = IfTemplate { cond: true };
    assert_eq!(s.render().unwrap(), "true");
}

#[derive(Template)]
#[template(path = "else.html")]
struct ElseTemplate {
    cond: bool,
}

#[test]
fn test_else() {
    let s = ElseTemplate { cond: false };
    assert_eq!(s.render().unwrap(), "false");
}

#[derive(Template)]
#[template(path = "else-if.html")]
struct ElseIfTemplate {
    cond: bool,
    check: bool,
}

#[test]
fn test_else_if() {
    let s = ElseIfTemplate {
        cond: false,
        check: true,
    };
    assert_eq!(s.render().unwrap(), "checked");
}

#[derive(Template)]
#[template(path = "literals.html")]
struct LiteralsTemplate {}

#[test]
fn test_literals() {
    let s = LiteralsTemplate {};
    assert_eq!(s.render().unwrap(), "a");
}

struct Holder {
    a: usize,
}

#[derive(Template)]
#[template(path = "attr.html")]
struct AttrTemplate {
    inner: Holder,
}

#[test]
fn test_attr() {
    let t = AttrTemplate {
        inner: Holder { a: 5 },
    };
    assert_eq!(t.render().unwrap(), "5");
}

#[derive(Template)]
#[template(path = "tuple-attr.html")]
struct TupleAttrTemplate<'a> {
    tuple: (&'a str, &'a str),
}

#[test]
fn test_tuple_attr() {
    let t = TupleAttrTemplate {
        tuple: ("foo", "bar"),
    };
    assert_eq!(t.render().unwrap(), "foobar");
}

struct NestedHolder {
    holder: Holder,
}

#[derive(Template)]
#[template(path = "nested-attr.html")]
struct NestedAttrTemplate {
    inner: NestedHolder,
}

#[test]
fn test_nested_attr() {
    let t = NestedAttrTemplate {
        inner: NestedHolder {
            holder: Holder { a: 5 },
        },
    };
    assert_eq!(t.render().unwrap(), "5");
}

#[derive(Template)]
#[template(path = "option.html")]
struct OptionTemplate<'a> {
    var: Option<&'a str>,
}

#[test]
fn test_option() {
    let some = OptionTemplate { var: Some("foo") };
    assert_eq!(some.render().unwrap(), "some: foo");
    let none = OptionTemplate { var: None };
    assert_eq!(none.render().unwrap(), "none");
}

#[derive(Template)]
#[template(path = "generics.html")]
struct GenericsTemplate<T: std::fmt::Display, U = u8>
where
    U: std::fmt::Display,
{
    t: T,
    u: U,
}

#[test]
fn test_generics() {
    let t = GenericsTemplate { t: "a", u: 42 };
    assert_eq!(t.render().unwrap(), "a42");
}

#[derive(Template)]
#[template(path = "composition.html")]
struct CompositionTemplate {
    foo: IfTemplate,
}

#[test]
fn test_composition() {
    let t = CompositionTemplate {
        foo: IfTemplate { cond: true },
    };
    assert_eq!(t.render().unwrap(), "composed: true");
}

#[derive(PartialEq, Eq)]
enum Alphabet {
    Alpha,
}

#[derive(Template)]
#[template(source = "{% if x == Alphabet::Alpha %}true{% endif %}", ext = "txt")]
struct PathCompareTemplate {
    x: Alphabet,
}

#[test]
fn test_path_compare() {
    let t = PathCompareTemplate { x: Alphabet::Alpha };
    assert_eq!(t.render().unwrap(), "true");
}

#[derive(Template)]
#[template(source = "{% for i in [\"a\", \"\"] %}{{ i }}{% endfor %}", ext = "txt")]
struct ArrayTemplate {}

#[test]
fn test_slice_literal() {
    let t = ArrayTemplate {};
    assert_eq!(t.render().unwrap(), "a");
}

#[derive(Template)]
#[template(source = "  {# foo -#} ", ext = "txt")]
struct CommentTemplate {}

#[test]
fn test_comment() {
    let t = CommentTemplate {};
    assert_eq!(t.render().unwrap(), "  ");
}

#[derive(Template)]
#[template(source = "{% if !foo %}Hello{% endif %}", ext = "txt")]
struct NegationTemplate {
    foo: bool,
}

#[test]
fn test_negation() {
    let t = NegationTemplate { foo: false };
    assert_eq!(t.render().unwrap(), "Hello");
}

#[derive(Template)]
#[template(source = "{% if foo > -2 %}Hello{% endif %}", ext = "txt")]
struct MinusTemplate {
    foo: i8,
}

#[test]
fn test_minus() {
    let t = MinusTemplate { foo: 1 };
    assert_eq!(t.render().unwrap(), "Hello");
}

#[derive(Template)]
#[template(source = "{{ foo[\"bar\"] }}", ext = "txt", print = "code")]
struct IndexTemplate {
    foo: HashMap<String, String>,
}

#[test]
fn test_index() {
    let mut foo = HashMap::new();
    foo.insert("bar".into(), "baz".into());
    let t = IndexTemplate { foo };
    assert_eq!(t.render().unwrap(), "baz");
}
<|endoftext|>


<commit_before>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};

use {Pulse, Signal, Waiting, Signals};

pub struct Inner {
    pub count: AtomicUsize,
    pub trigger: Mutex<Option<Pulse>>
}

/// A `Barrier` can listen for 1 or more `Signals`. It will only transition
/// to a `Pulsed` state once all the `Signals` have `Pulsed`.
pub struct Barrier {
    inner: Arc<Inner>
}

pub struct Handle(pub Arc<Inner>);

impl Barrier {
    /// Create a new Barrier from an Vector of `Siganl`s
    pub fn new(pulses: &[Signal]) -> Barrier {
        // count items
        let inner = Arc::new(Inner{
            count: AtomicUsize::new(pulses.len()),
            trigger: Mutex::new(None)
        });

        for pulse in pulses {
            pulse.clone().arm(Waiting::barrier(Handle(inner.clone())));
        }

        Barrier { inner: inner }
    }

}

impl Signals for Barrier {
    fn signal(&self) -> Signal {
        let (p, t) = Signal::new();
        if self.inner.count.load(Ordering::Relaxed) == 0 {
            t.pulse();
        } else {
            let mut guard = self.inner.trigger.lock().unwrap();
            *guard = Some(t);
        }
        p
    }
}
<commit_msg>Lock the guard before checking the count.<commit_after>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};

use {Pulse, Signal, Waiting, Signals};

pub struct Inner {
    pub count: AtomicUsize,
    pub trigger: Mutex<Option<Pulse>>
}

/// A `Barrier` can listen for 1 or more `Signals`. It will only transition
/// to a `Pulsed` state once all the `Signals` have `Pulsed`.
pub struct Barrier {
    inner: Arc<Inner>
}

pub struct Handle(pub Arc<Inner>);

impl Barrier {
    /// Create a new Barrier from an Vector of `Siganl`s
    pub fn new(pulses: &[Signal]) -> Barrier {
        // count items
        let inner = Arc::new(Inner{
            count: AtomicUsize::new(pulses.len()),
            trigger: Mutex::new(None)
        });

        for pulse in pulses {
            pulse.clone().arm(Waiting::barrier(Handle(inner.clone())));
        }

        Barrier { inner: inner }
    }

}

impl Signals for Barrier {
    fn signal(&self) -> Signal {
        let mut guard = self.inner.trigger.lock().unwrap();
        let (p, t) = Signal::new();
        if self.inner.count.load(Ordering::Relaxed) == 0 {
            t.pulse();
        } else {
            *guard = Some(t);
        }
        p
    }
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    pub fn with_addr(addr: &'a str) -> GQTPRequest<'a> {
        GQTPRequest { addr: addr }
    }

    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // recv and check protocol header value
        let mut read_buf = vec![0; 8192];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas
        let mut msg = vec![0; size as usize];
        let _ = buf.read(&mut msg).unwrap();

        Ok(String::from_utf8(msg).unwrap())
    }
}

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

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }

    #[test]
    fn smoke_gqtp_call() {
        let req = GQTPRequest::new();
        // req.call("select --table Entries --filter \'content @ \"fast\"\'");
        let result_string = req.call("status").unwrap();
        assert_eq!(result_string.contains("version"), true);
    }
}
<commit_msg>document<commit_after>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    /// Create a GQTP client.
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    /// Set host address for GQTP server.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    ///
    /// groonga::GQTPRequest::new().with_addr("127.0.0.1:20043");
    /// ```
    pub fn with_addr(mut self, addr: &'a str) -> GQTPRequest<'a> {
        self.addr = addr;
        self
    }

    /// Send request and Receive response.
    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // receive and check protocol header value
        let mut read_buf = vec![0; 8192];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas

        // read body
        let mut msg = vec![0; size as usize];
        let _ = buf.read(&mut msg).unwrap();

        Ok(String::from_utf8(msg).unwrap())
    }
}

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

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::new().with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }
}
<|endoftext|>


<commit_before>/// Custom event handlers
use crate::{
    Cmd, EditMode, InputMode, InputState, KeyCode, KeyEvent, Modifiers, Refresher, RepeatCount,
};

use radix_trie::TrieKey;

/// Input event
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Event {
    /// Wildcard.
    /// Useful if you want to filter out some keys.
    Any,
    /// Key sequence
    KeySeq(Vec<KeyEvent>),
    /// TODO Mouse event
    Mouse(),
}

impl Event {
    /// See [`KeyEvent::normalize`]
    pub(crate) fn normalize(mut self) -> Self {
        if let Event::KeySeq(ref mut keys) = self {
            for key in keys.iter_mut() {
                *key = KeyEvent::normalize(*key);
            }
        }
        self
    }

    /// Return `i`th key event
    #[must_use]
    pub fn get(&self, i: usize) -> Option<&KeyEvent> {
        if let Event::KeySeq(ref ks) = self {
            ks.get(i)
        } else {
            None
        }
    }
}

impl From<KeyEvent> for Event {
    fn from(k: KeyEvent) -> Event {
        Event::KeySeq(vec![k])
    }
}

const BASE: u32 = 0x0010_ffff + 1;
const BASE_CONTROL: u32 = 0x0200_0000;
const BASE_META: u32 = 0x0400_0000;
const BASE_SHIFT: u32 = 0x0100_0000;
const ESCAPE: u32 = 27;
const PAGE_UP: u32 = BASE + 1;
const PAGE_DOWN: u32 = PAGE_UP + 1;
const DOWN: u32 = PAGE_DOWN + 1;
const UP: u32 = DOWN + 1;
const LEFT: u32 = UP + 1;
const RIGHT: u32 = LEFT + 1;
const HOME: u32 = RIGHT + 1;
const END: u32 = HOME + 1;
const DELETE: u32 = END + 1;
const INSERT: u32 = DELETE + 1;
//const F1: u32 = INSERT + 1;
const MOUSE: u32 = /* F24 + 1 */ INSERT + 25;
const PASTE_START: u32 = MOUSE + 1;
const PASTE_FINISH: u32 = PASTE_START + 1;
const ANY: u32 = PASTE_FINISH + 1;

impl KeyEvent {
    fn encode(&self) -> u32 {
        let mut u = match self.0 {
            KeyCode::UnknownEscSeq | KeyCode::Null => 0,
            KeyCode::Backspace => u32::from('\x7f'),
            KeyCode::BackTab => u32::from('\t') | BASE_SHIFT,
            KeyCode::BracketedPasteStart => PASTE_START,
            KeyCode::BracketedPasteEnd => PASTE_FINISH,
            KeyCode::Char(c) => u32::from(c),
            KeyCode::Delete => DELETE,
            KeyCode::Down => DOWN,
            KeyCode::End => END,
            KeyCode::Enter => u32::from('\r'),
            KeyCode::F(i) => INSERT + u32::from(i),
            KeyCode::Esc => ESCAPE,
            KeyCode::Home => HOME,
            KeyCode::Insert => INSERT,
            KeyCode::Left => LEFT,
            KeyCode::PageDown => PAGE_DOWN,
            KeyCode::PageUp => PAGE_UP,
            KeyCode::Right => RIGHT,
            KeyCode::Tab => u32::from('\t'),
            KeyCode::Up => UP,
        };
        if self.1.contains(Modifiers::CTRL) {
            u |= BASE_CONTROL;
        }
        if self.1.contains(Modifiers::ALT) {
            u |= BASE_META;
        }
        if self.1.contains(Modifiers::SHIFT) {
            u |= BASE_SHIFT;
        }
        u
    }
}

impl TrieKey for Event {
    fn encode_bytes(&self) -> Vec<u8> {
        match self {
            Event::Any => ANY.to_be_bytes().to_vec(),
            Event::KeySeq(keys) => {
                let mut dst = Vec::with_capacity(keys.len() * 4);
                for key in keys {
                    dst.extend_from_slice(&key.encode().to_be_bytes());
                }
                dst
            }
            Event::Mouse() => MOUSE.to_be_bytes().to_vec(),
        }
    }
}

/// Event handler
pub enum EventHandler {
    /// unconditional command
    Simple(Cmd),
    /// handler behaviour depends on input state
    Conditional(Box<dyn ConditionalEventHandler>),
    /* invoke multiple actions
     * TODO Macro(), */
}

impl From<Cmd> for EventHandler {
    fn from(c: Cmd) -> EventHandler {
        EventHandler::Simple(c)
    }
}

/// Give access to user input.
pub struct EventContext<'r> {
    mode: EditMode,
    input_mode: InputMode,
    wrt: &'r dyn Refresher,
}

impl<'r> EventContext<'r> {
    pub(crate) fn new(is: &InputState, wrt: &'r dyn Refresher) -> Self {
        EventContext {
            mode: is.mode,
            input_mode: is.input_mode,
            wrt,
        }
    }

    /// emacs or vi mode
    #[must_use]
    pub fn mode(&self) -> EditMode {
        self.mode
    }

    /// vi input mode
    #[must_use]
    pub fn input_mode(&self) -> InputMode {
        self.input_mode
    }

    /// Returns `true` if there is a hint displayed.
    #[must_use]
    pub fn has_hint(&self) -> bool {
        self.wrt.has_hint()
    }

    /// Returns the hint text that is shown after the current cursor position.
    #[must_use]
    pub fn hint_text(&self) -> Option<&str> {
        self.wrt.hint_text()
    }

    /// currently edited line
    #[must_use]
    pub fn line(&self) -> &str {
        self.wrt.line()
    }

    /// Current cursor position (byte position)
    #[must_use]
    pub fn pos(&self) -> usize {
        self.wrt.pos()
    }
}

/// May behave differently depending on:
///  * edit mode (emacs vs vi)
///  * vi input mode (insert vs replace vs command modes)
///  * empty line
///  * cursor position
///  * repeat count
///  * original key pressed (when same command is bound to different key)
///  * hint
///  * ...
pub trait ConditionalEventHandler: Send + Sync {
    /// Takes the current input state and
    /// returns the command to be performed or `None` to perform the default
    /// one.
    fn handle(
        &self,
        evt: &Event,
        n: RepeatCount,
        positive: bool,
        ctx: &EventContext,
    ) -> Option<Cmd>;
}

#[cfg(test)]
mod test {
    use core::mem::size_of;

    use super::{Event, EventHandler};
    use crate::{Cmd, KeyCode, KeyEvent, Modifiers};
    use radix_trie::Trie;

    #[test]
    fn encode() {
        let mut trie = Trie::new();
        let evt = Event::KeySeq(vec![KeyEvent::ctrl('X'), KeyEvent::ctrl('E')]);
        trie.insert(evt.clone(), EventHandler::from(Cmd::Noop));
        let prefix = Event::from(KeyEvent::ctrl('X'));
        let subtrie = trie.get_raw_descendant(&prefix);
        assert!(subtrie.is_some());
        let subtrie = subtrie.unwrap();
        let sub_result = subtrie.get(&evt);
        assert!(sub_result.is_ok());
        assert!(sub_result.unwrap().is_some());
        let prefix = Event::from(KeyEvent::ctrl('O'));
        let subtrie = trie.get_raw_descendant(&prefix);
        assert!(subtrie.is_none())
    }

    #[test]
    fn no_collision() {
        use {Event as E, EventHandler as H, KeyCode as C, KeyEvent as K, Modifiers as M};
        let mut trie = Trie::new();
        trie.insert(E::from(K(C::Backspace, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Enter, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Tab, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Backspace, M::CTRL)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Enter, M::CTRL)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Tab, M::CTRL)), H::from(Cmd::Noop));
    }

    #[test]
    fn size_of_event() {
        assert_eq!(size_of::<Event>(), 40);
    }
}
<commit_msg>Size of event enum as shrunk<commit_after>/// Custom event handlers
use crate::{
    Cmd, EditMode, InputMode, InputState, KeyCode, KeyEvent, Modifiers, Refresher, RepeatCount,
};

use radix_trie::TrieKey;

/// Input event
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Event {
    /// Wildcard.
    /// Useful if you want to filter out some keys.
    Any,
    /// Key sequence
    KeySeq(Vec<KeyEvent>),
    /// TODO Mouse event
    Mouse(),
}

impl Event {
    /// See [`KeyEvent::normalize`]
    pub(crate) fn normalize(mut self) -> Self {
        if let Event::KeySeq(ref mut keys) = self {
            for key in keys.iter_mut() {
                *key = KeyEvent::normalize(*key);
            }
        }
        self
    }

    /// Return `i`th key event
    #[must_use]
    pub fn get(&self, i: usize) -> Option<&KeyEvent> {
        if let Event::KeySeq(ref ks) = self {
            ks.get(i)
        } else {
            None
        }
    }
}

impl From<KeyEvent> for Event {
    fn from(k: KeyEvent) -> Event {
        Event::KeySeq(vec![k])
    }
}

const BASE: u32 = 0x0010_ffff + 1;
const BASE_CONTROL: u32 = 0x0200_0000;
const BASE_META: u32 = 0x0400_0000;
const BASE_SHIFT: u32 = 0x0100_0000;
const ESCAPE: u32 = 27;
const PAGE_UP: u32 = BASE + 1;
const PAGE_DOWN: u32 = PAGE_UP + 1;
const DOWN: u32 = PAGE_DOWN + 1;
const UP: u32 = DOWN + 1;
const LEFT: u32 = UP + 1;
const RIGHT: u32 = LEFT + 1;
const HOME: u32 = RIGHT + 1;
const END: u32 = HOME + 1;
const DELETE: u32 = END + 1;
const INSERT: u32 = DELETE + 1;
//const F1: u32 = INSERT + 1;
const MOUSE: u32 = /* F24 + 1 */ INSERT + 25;
const PASTE_START: u32 = MOUSE + 1;
const PASTE_FINISH: u32 = PASTE_START + 1;
const ANY: u32 = PASTE_FINISH + 1;

impl KeyEvent {
    fn encode(&self) -> u32 {
        let mut u = match self.0 {
            KeyCode::UnknownEscSeq | KeyCode::Null => 0,
            KeyCode::Backspace => u32::from('\x7f'),
            KeyCode::BackTab => u32::from('\t') | BASE_SHIFT,
            KeyCode::BracketedPasteStart => PASTE_START,
            KeyCode::BracketedPasteEnd => PASTE_FINISH,
            KeyCode::Char(c) => u32::from(c),
            KeyCode::Delete => DELETE,
            KeyCode::Down => DOWN,
            KeyCode::End => END,
            KeyCode::Enter => u32::from('\r'),
            KeyCode::F(i) => INSERT + u32::from(i),
            KeyCode::Esc => ESCAPE,
            KeyCode::Home => HOME,
            KeyCode::Insert => INSERT,
            KeyCode::Left => LEFT,
            KeyCode::PageDown => PAGE_DOWN,
            KeyCode::PageUp => PAGE_UP,
            KeyCode::Right => RIGHT,
            KeyCode::Tab => u32::from('\t'),
            KeyCode::Up => UP,
        };
        if self.1.contains(Modifiers::CTRL) {
            u |= BASE_CONTROL;
        }
        if self.1.contains(Modifiers::ALT) {
            u |= BASE_META;
        }
        if self.1.contains(Modifiers::SHIFT) {
            u |= BASE_SHIFT;
        }
        u
    }
}

impl TrieKey for Event {
    fn encode_bytes(&self) -> Vec<u8> {
        match self {
            Event::Any => ANY.to_be_bytes().to_vec(),
            Event::KeySeq(keys) => {
                let mut dst = Vec::with_capacity(keys.len() * 4);
                for key in keys {
                    dst.extend_from_slice(&key.encode().to_be_bytes());
                }
                dst
            }
            Event::Mouse() => MOUSE.to_be_bytes().to_vec(),
        }
    }
}

/// Event handler
pub enum EventHandler {
    /// unconditional command
    Simple(Cmd),
    /// handler behaviour depends on input state
    Conditional(Box<dyn ConditionalEventHandler>),
    /* invoke multiple actions
     * TODO Macro(), */
}

impl From<Cmd> for EventHandler {
    fn from(c: Cmd) -> EventHandler {
        EventHandler::Simple(c)
    }
}

/// Give access to user input.
pub struct EventContext<'r> {
    mode: EditMode,
    input_mode: InputMode,
    wrt: &'r dyn Refresher,
}

impl<'r> EventContext<'r> {
    pub(crate) fn new(is: &InputState, wrt: &'r dyn Refresher) -> Self {
        EventContext {
            mode: is.mode,
            input_mode: is.input_mode,
            wrt,
        }
    }

    /// emacs or vi mode
    #[must_use]
    pub fn mode(&self) -> EditMode {
        self.mode
    }

    /// vi input mode
    #[must_use]
    pub fn input_mode(&self) -> InputMode {
        self.input_mode
    }

    /// Returns `true` if there is a hint displayed.
    #[must_use]
    pub fn has_hint(&self) -> bool {
        self.wrt.has_hint()
    }

    /// Returns the hint text that is shown after the current cursor position.
    #[must_use]
    pub fn hint_text(&self) -> Option<&str> {
        self.wrt.hint_text()
    }

    /// currently edited line
    #[must_use]
    pub fn line(&self) -> &str {
        self.wrt.line()
    }

    /// Current cursor position (byte position)
    #[must_use]
    pub fn pos(&self) -> usize {
        self.wrt.pos()
    }
}

/// May behave differently depending on:
///  * edit mode (emacs vs vi)
///  * vi input mode (insert vs replace vs command modes)
///  * empty line
///  * cursor position
///  * repeat count
///  * original key pressed (when same command is bound to different key)
///  * hint
///  * ...
pub trait ConditionalEventHandler: Send + Sync {
    /// Takes the current input state and
    /// returns the command to be performed or `None` to perform the default
    /// one.
    fn handle(
        &self,
        evt: &Event,
        n: RepeatCount,
        positive: bool,
        ctx: &EventContext,
    ) -> Option<Cmd>;
}

#[cfg(test)]
mod test {
    use core::mem::size_of;

    use super::{Event, EventHandler};
    use crate::{Cmd, KeyCode, KeyEvent, Modifiers};
    use radix_trie::Trie;

    #[test]
    fn encode() {
        let mut trie = Trie::new();
        let evt = Event::KeySeq(vec![KeyEvent::ctrl('X'), KeyEvent::ctrl('E')]);
        trie.insert(evt.clone(), EventHandler::from(Cmd::Noop));
        let prefix = Event::from(KeyEvent::ctrl('X'));
        let subtrie = trie.get_raw_descendant(&prefix);
        assert!(subtrie.is_some());
        let subtrie = subtrie.unwrap();
        let sub_result = subtrie.get(&evt);
        assert!(sub_result.is_ok());
        assert!(sub_result.unwrap().is_some());
        let prefix = Event::from(KeyEvent::ctrl('O'));
        let subtrie = trie.get_raw_descendant(&prefix);
        assert!(subtrie.is_none())
    }

    #[test]
    fn no_collision() {
        use {Event as E, EventHandler as H, KeyCode as C, KeyEvent as K, Modifiers as M};
        let mut trie = Trie::new();
        trie.insert(E::from(K(C::Backspace, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Enter, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Tab, M::NONE)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Backspace, M::CTRL)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Enter, M::CTRL)), H::from(Cmd::Noop));
        trie.insert(E::from(K(C::Tab, M::CTRL)), H::from(Cmd::Noop));
    }

    #[test]
    fn size_of_event() {
        assert_eq!(size_of::<Event>(), 32);
    }
}
<|endoftext|>


<commit_before>extern crate rustyprefetch;
use rustyprefetch::librp::fileinfo;

#[test]
fn fileinfo_v26_test() {
    let v26_fileinfo_buffer: &[u8] = &[
        0x30,0x01,0x00,0x00,0x87,0x00,0x00,0x00,0x10,0x12,0x00,0x00,0xDA,0x28,0x00,0x00,
        0x48,0xFC,0x01,0x00,0x2C,0x47,0x00,0x00,0x78,0x43,0x02,0x00,0x01,0x00,0x00,0x00,
        0x44,0x0F,0x00,0x00,0x1B,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7A,0x8D,0xB2,0x2B,
        0x98,0xCE,0xCE,0x01,0x4A,0xC7,0xCC,0x2B,0x98,0xCE,0xCE,0x01,0xF9,0x48,0x1A,0x59,
        0x31,0xC0,0xCE,0x01,0xD2,0xF0,0xDE,0x58,0x31,0xC0,0xCE,0x01,0xDA,0x01,0x9B,0x7F,
        0x4B,0xBE,0xCE,0x01,0xD2,0x11,0x85,0x7F,0x4B,0xBE,0xCE,0x01,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
        0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    ];

    let v26_fileinfo = match fileinfo::get_fileinfo_v26(v26_fileinfo_buffer){
        Ok(v26_fileinfo) => v26_fileinfo,
        Err(error) => panic!(error)
    };

    assert_eq!(v26_fileinfo.metrics_array_offset, 304);
    assert_eq!(v26_fileinfo.metrics_entry_count, 135);
    assert_eq!(v26_fileinfo.trace_array_offset, 4624);
    assert_eq!(v26_fileinfo.trace_entry_count, 10458);
    assert_eq!(v26_fileinfo.filename_offset, 130120);
    assert_eq!(v26_fileinfo.filename_length, 18220);
    assert_eq!(v26_fileinfo.volume_info_offset, 148344);
    assert_eq!(v26_fileinfo.volume_info_count, 1);
    assert_eq!(v26_fileinfo.volume_info_size, 3908);
    assert_eq!(v26_fileinfo.unknown3, 4294967323);
    assert_eq!(v26_fileinfo.run_count, 6);
    assert_eq!(v26_fileinfo.unknown2, 6);
    assert_eq!(v26_fileinfo.unknown5, 3);
}
<commit_msg>Added fileinfo v17 and v26 tests<commit_after>extern crate rustyprefetch;
use rustyprefetch::librp::fileinfo;
use rustyprefetch::librp::utils;

#[test]
fn fileinfo_v17_test() {
    let v17_fileinfo_buffer: &[u8] = &[
        0x98,0x00,0x00,0x00,0x2C,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0xED,0x11,0x00,0x00,
        0x24,0xDB,0x00,0x00,0x6E,0x16,0x00,0x00,0x98,0xF1,0x00,0x00,0x01,0x00,0x00,0x00,
        0x7E,0x04,0x00,0x00,0x60,0xE8,0x89,0x95,0x35,0x11,0xCD,0x01,0x00,0x8C,0x86,0x47,
        0x00,0x00,0x00,0x00,0x00,0x8C,0x86,0x47,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
        0x05,0x00,0x00,0x00
    ];

    let v17_fileinfo = match fileinfo::get_fileinfo_v17(v17_fileinfo_buffer){
        Ok(v17_fileinfo) => v17_fileinfo,
        Err(error) => panic!(error)
    };

    assert_eq!(v17_fileinfo.metrics_array_offset, 152);
    assert_eq!(v17_fileinfo.metrics_entry_count, 44);
    assert_eq!(v17_fileinfo.trace_array_offset, 1032);
    assert_eq!(v17_fileinfo.trace_entry_count, 4589);
    assert_eq!(v17_fileinfo.filename_offset, 56100);
    assert_eq!(v17_fileinfo.filename_length, 5742);
    assert_eq!(v17_fileinfo.volume_info_offset, 61848);
    assert_eq!(v17_fileinfo.volume_info_count, 1);
    assert_eq!(v17_fileinfo.volume_info_size, 1150);
    assert_eq!(v17_fileinfo.last_run_time.0, 129778886103394400);
    assert_eq!(utils::to_hex_string(&v17_fileinfo.unknown1.0), "008C864700000000008C864700000000");
    assert_eq!(v17_fileinfo.run_count, 17);
    assert_eq!(v17_fileinfo.unknown2, 5);
}

#[test]
fn fileinfo_v26_test() {
    let v26_fileinfo_buffer: &[u8] = &[
        0x30,0x01,0x00,0x00,0x87,0x00,0x00,0x00,0x10,0x12,0x00,0x00,0xDA,0x28,0x00,0x00,
        0x48,0xFC,0x01,0x00,0x2C,0x47,0x00,0x00,0x78,0x43,0x02,0x00,0x01,0x00,0x00,0x00,
        0x44,0x0F,0x00,0x00,0x1B,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7A,0x8D,0xB2,0x2B,
        0x98,0xCE,0xCE,0x01,0x4A,0xC7,0xCC,0x2B,0x98,0xCE,0xCE,0x01,0xF9,0x48,0x1A,0x59,
        0x31,0xC0,0xCE,0x01,0xD2,0xF0,0xDE,0x58,0x31,0xC0,0xCE,0x01,0xDA,0x01,0x9B,0x7F,
        0x4B,0xBE,0xCE,0x01,0xD2,0x11,0x85,0x7F,0x4B,0xBE,0xCE,0x01,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
        0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    ];

    let v26_fileinfo = match fileinfo::get_fileinfo_v26(v26_fileinfo_buffer){
        Ok(v26_fileinfo) => v26_fileinfo,
        Err(error) => panic!(error)
    };

    assert_eq!(v26_fileinfo.metrics_array_offset, 304);
    assert_eq!(v26_fileinfo.metrics_entry_count, 135);
    assert_eq!(v26_fileinfo.trace_array_offset, 4624);
    assert_eq!(v26_fileinfo.trace_entry_count, 10458);
    assert_eq!(v26_fileinfo.filename_offset, 130120);
    assert_eq!(v26_fileinfo.filename_length, 18220);
    assert_eq!(v26_fileinfo.volume_info_offset, 148344);
    assert_eq!(v26_fileinfo.volume_info_count, 1);
    assert_eq!(v26_fileinfo.volume_info_size, 3908);
    assert_eq!(v26_fileinfo.unknown3, 4294967323);
    assert_eq!(v26_fileinfo.last_run_time[0].0, 130268592203795834);
    assert_eq!(v26_fileinfo.last_run_time[1].0, 130268592205514570);
    assert_eq!(v26_fileinfo.last_run_time[2].0, 130252757421148409);
    assert_eq!(v26_fileinfo.last_run_time[3].0, 130252757417259218);
    assert_eq!(v26_fileinfo.last_run_time[4].0, 130250670713012698);
    assert_eq!(v26_fileinfo.last_run_time[5].0, 130250670711574994);
    assert_eq!(v26_fileinfo.last_run_time[6].0, 0);
    assert_eq!(v26_fileinfo.last_run_time[7].0, 0);
    assert_eq!(
        utils::to_hex_string(&v26_fileinfo.unknown1.0),
        "00000000000000000000000000000000"
    );
    assert_eq!(v26_fileinfo.run_count, 6);
    assert_eq!(v26_fileinfo.unknown2, 6);
    assert_eq!(v26_fileinfo.unknown5, 3);
    assert_eq!(
        utils::to_hex_string(&v26_fileinfo.unknown4.0),
        "000000000000000000000000000000000000000000000000000000000000000000\
        0000000000000000000000000000000000000000000000000000000000000000000\
        0000000000000000000000000000000000000000000"
    );
}

#[test]
fn fileinfo_v30_test() {
    let v30_fileinfo_buffer: &[u8] = &[
        0x30,0x01,0x00,0x00,0xEE,0x00,0x00,0x00,0xF0,0x1E,0x00,0x00,0xFB,0x31,0x00,0x00,
        0xC8,0xAE,0x01,0x00,0x26,0xAB,0x00,0x00,0xF0,0x59,0x02,0x00,0x01,0x00,0x00,0x00,
        0x64,0x27,0x00,0x00,0x38,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x3F,0x9B,0x0C,0x92,
        0x54,0x9C,0xD2,0x01,0x73,0xA0,0xF9,0x0C,0x4B,0x9C,0xD2,0x01,0xC8,0xF9,0x44,0x76,
        0x2D,0x9C,0xD2,0x01,0x04,0x05,0x1B,0x02,0x99,0x9B,0xD2,0x01,0x10,0x91,0x2A,0x01,
        0x99,0x9B,0xD2,0x01,0x44,0xF7,0x75,0xD5,0xAA,0x9A,0xD2,0x01,0x7C,0x2C,0x99,0xD4,
        0xAA,0x9A,0xD2,0x01,0xC9,0xC0,0x73,0xAE,0x81,0x9A,0xD2,0x01,0x00,0x8C,0x86,0x47,
        0x00,0x00,0x00,0x00,0x00,0x8C,0x86,0x47,0x00,0x00,0x00,0x00,0x66,0x00,0x00,0x00,
        0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    ];

    let v30_fileinfo = match fileinfo::get_fileinfo_v30(v30_fileinfo_buffer){
        Ok(v30_fileinfo) => v30_fileinfo,
        Err(error) => panic!(error)
    };

    assert_eq!(v30_fileinfo.metrics_array_offset, 304);
    assert_eq!(v30_fileinfo.metrics_entry_count, 238);
    assert_eq!(v30_fileinfo.trace_array_offset, 7920);
    assert_eq!(v30_fileinfo.trace_entry_count, 12795);
    assert_eq!(v30_fileinfo.filename_offset, 110280);
    assert_eq!(v30_fileinfo.filename_length, 43814);
    assert_eq!(v30_fileinfo.volume_info_offset, 154096);
    assert_eq!(v30_fileinfo.volume_info_count, 1);
    assert_eq!(v30_fileinfo.volume_info_size, 10084);
    assert_eq!(v30_fileinfo.unknown3, 8589934648);
    assert_eq!(v30_fileinfo.last_run_time[0].0, 131339226188651327);
    assert_eq!(v30_fileinfo.last_run_time[1].0, 131339185301332083);
    assert_eq!(v30_fileinfo.last_run_time[2].0, 131339058218858952);
    assert_eq!(v30_fileinfo.last_run_time[3].0, 131338420614792452);
    assert_eq!(v30_fileinfo.last_run_time[4].0, 131338420599034128);
    assert_eq!(v30_fileinfo.last_run_time[5].0, 131337397663561540);
    assert_eq!(v30_fileinfo.last_run_time[6].0, 131337397649091708);
    assert_eq!(v30_fileinfo.last_run_time[7].0, 131337220915445961);
    assert_eq!(v30_fileinfo.run_count, 102);
    assert_eq!(
        utils::to_hex_string(&v30_fileinfo.unknown1.0),
        "008C864700000000008C864700000000"
    );
    assert_eq!(v30_fileinfo.unknown2, 6);
    assert_eq!(v30_fileinfo.unknown5, 3);
    assert_eq!(
        utils::to_hex_string(&v30_fileinfo.unknown4.0),
        "00000000000000000000000000000000000000000000000000000\
        0000000000000000000000000000000000000000000000000000000\
        0000000000000000000000000000000000000000000000000000000\
        0000000000000"
    );
}
<|endoftext|>


<commit_before>extern crate piston_window;

use piston_window::Transformed;

use piston_window as pw;

struct Game {
    rotation: f64,
	x: f64,
	y: f64,
	up: bool,
	down: bool,
	left: bool,
	right: bool,
}

impl Game {
    fn new() -> Game {
        Game { rotation: 0.0, x: 0., y: 0., up: false, down: false, left: false, right: false }
    }

    fn on_update(&mut self, args: &pw::UpdateArgs) {
        self.rotation += 3.0 * args.dt;

		if self.up {
			self.y += -50.0 * args.dt;
		}
		if self.down {
			self.y += 50.0 * args.dt;
		}
		if self.left {
			self.x += -50.0 * args.dt;
		}
		if self.right {
			self.x += 50.0 * args.dt;
		}
    }

    fn on_draw(&mut self, args: &pw::RenderArgs, window: &pw::PistonWindow) {
        window.draw_2d(|context, graphics| {
            pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let red = [1.0, 0.0, 0.0, 1.0];
            let square = pw::rectangle::square(0.0, 0.0, 100.0);
            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            pw::rectangle(red, square, center.trans(self.x, self.y).rot_rad(self.rotation).trans(-50.0, -50.0), graphics);
        });
    }

	fn on_input(&mut self, input: &pw::Input) {
		use piston_window::{Button, Key};

		match input {
			&pw::Input::Press(button) => {
				match button {
					Button::Keyboard(Key::Up) => { self.up = true; }
					Button::Keyboard(Key::Down) => { self.down = true; }
					Button::Keyboard(Key::Left) => { self.left = true; }
					Button::Keyboard(Key::Right) => { self.right = true; }
					_ => {}
				}
			}
			&pw::Input::Release(button) => {
				match button {
					Button::Keyboard(Key::Up) => { self.up = false; }
					Button::Keyboard(Key::Down) => { self.down = false; }
					Button::Keyboard(Key::Left) => { self.left = false; }
					Button::Keyboard(Key::Right) => { self.right = false; }
					_ => {}
				}
			}
			_ => {}
		}
	}
}

fn main() {
	use piston_window::Event;

    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

	let mut game = Game::new();

    for w in window {
		match w.event {
			Some(Event::Update(args)) => { game.on_update(&args); }
			Some(Event::Render(args)) => { game.on_draw(&args, &w); }
			Some(Event::Input(input)) => { game.on_input(&input); }
			_ => {}
		}
    }
}
<commit_msg>Tabs have been replaced by spaces<commit_after>extern crate piston_window;

use piston_window::Transformed;

use piston_window as pw;

struct Game {
    rotation: f64,
    x: f64,
    y: f64,
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Game {
    fn new() -> Game {
        Game { rotation: 0.0, x: 0., y: 0., up: false, down: false, left: false, right: false }
    }

    fn on_update(&mut self, args: &pw::UpdateArgs) {
        self.rotation += 3.0 * args.dt;

        if self.up {
            self.y += -50.0 * args.dt;
        }
        if self.down {
            self.y += 50.0 * args.dt;
        }
        if self.left {
            self.x += -50.0 * args.dt;
        }
        if self.right {
            self.x += 50.0 * args.dt;
        }
    }

    fn on_draw(&mut self, args: &pw::RenderArgs, window: &pw::PistonWindow) {
        window.draw_2d(|context, graphics| {
            pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let red = [1.0, 0.0, 0.0, 1.0];
            let square = pw::rectangle::square(0.0, 0.0, 100.0);
            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            pw::rectangle(red, square, center.trans(self.x, self.y).rot_rad(self.rotation).trans(-50.0, -50.0), graphics);
        });
    }

    fn on_input(&mut self, input: &pw::Input) {
        use piston_window::{Button, Key};

        match input {
            &pw::Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &pw::Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn main() {
    use piston_window::Event;

    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut game = Game::new();

    for w in window {
        match w.event {
            Some(Event::Update(args)) => { game.on_update(&args); }
            Some(Event::Render(args)) => { game.on_draw(&args, &w); }
            Some(Event::Input(input)) => { game.on_input(&input); }
            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>use iron::prelude::*;
use base::framework::{ResponseData, temp_response,
                      json_error_response, json_ok_response,
                      not_found_response};
use urlencoded::UrlEncodedBody;
use base::db::MyPool;
use base::validator::{Validator, Checker, Str, StrValue, Int, IntValue, Max, Min, Lambda};
use base::framework::LoginUser;
use base::util::render_html;
use iron_login::User as U;
use persistent::Read;
use chrono::*;
use router::Router;
use mysql as my;
use base::model::{Article, User, Category, Comment};
use rustc_serialize::json::ToJson;
use base::util;
use base::util::gen_gravatar_url;
use base::constant;
use std::sync::Arc;

pub fn new_load(req: &mut Request) -> IronResult<Response> {
    let mut data = ResponseData::new(req);
    data.insert("categories", util::gen_categories_json(None));
    temp_response("article/new_load", &data)
}

pub fn new(req: &mut Request) -> IronResult<Response> {
    let mut validator = Validator::new();
    validator
        .add_checker(Checker::new("category", Int, "类别") << Lambda(Box::new(Arc::new(|v| {
            !(constant::CATEGORY::ALL.iter().find(|c|**c as i64 == v.downcast_ref_unchecked::<IntValue>().value()).is_none())
        }))))
        .add_checker(Checker::new("title", Str, "标题") << Min(3) << Max(64))
        .add_checker(Checker::new("content", Str, "内容") << Min(7));

    validator.validate(req.get::<UrlEncodedBody>());
    if !validator.is_valid() {
        return json_error_response(&validator.messages[0]);
    }

    let category = validator.get_valid::<IntValue>("category").value();
    let title = validator.get_valid::<StrValue>("title").value();
    let content = validator.get_valid::<StrValue>("content").value();
    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let now = Local::now().naive_local();
    let mut stmt = pool.prepare("INSERT INTO article(category, title, content, \
                                 user_id, create_time, update_time) \
                                 VALUES (?, ?, ?, ?, ?)").unwrap();
    let result = stmt.execute((category, title, content, user.id, now, now));
    result.unwrap();
    json_ok_response()
}

pub fn show(req: &mut Request) -> IronResult<Response> {
    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut result = pool.prep_exec(
        "SELECT a.id, a.category, a.title, a.content, a.comments_count, \
         a.create_time, u.id as user_id, u.username, u.email from article \
         as a join user as u on a.user_id=u.id where a.id=? and a.status=?",
        (&article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

    let raw_row = result.next();
    if raw_row.is_none() {
        return not_found_response();
    }
    let row = raw_row.unwrap().unwrap();
    let (id, category, title, content, comments_count, create_time, user_id, username, email) = my::from_row::<(_,_,_,_,_,_,_,_,String)>(row);
    let mut article = Article {
        id: id,
        category: Category::from_value(category),
        title: title,
        content: content,
        comments_count: comments_count,
        user: User{
            id: user_id,
            avatar: gen_gravatar_url(&email),
            username: username,
            email: email,
            create_time: *constant::DEFAULT_DATETIME,
        },
        create_time: create_time,
        update_time: *constant::DEFAULT_DATETIME,
        flag: 0,
        comments: Vec::new(),
    };
    article.content = render_html(&article.content);

    let result = pool.prep_exec(
        "SELECT c.id, c.content, c.create_time, u.id as user_id, \
         u.username, u.email from comment \
         as c join user as u on c.user_id=u.id where c.article_id=? \
         order by c.create_time", (&article_id, )).unwrap();

    article.comments = result.map(|x| x.unwrap()).map(|row|{
        let (id, content, create_time, user_id, username, email) = my::from_row::<(_,String,_,_,_,String)>(row);
        Comment {
            id: id,
            content: render_html(&content),
            user: User {
                id: user_id,
                avatar: gen_gravatar_url(&email),
                username: username,
                email: email,
                create_time: *constant::DEFAULT_DATETIME,
            },
            create_time: create_time,
            article: None,
        }
    }).collect();

    // judge whether is my article
    let mut is_my_own = false;
    let raw_login_user = LoginUser::get_login(req).get_user();
    if let Some(login_user) = raw_login_user {
        if login_user.id == article.user.id {
            is_my_own = true;
        }
    }

    let mut data = ResponseData::new(req);
    data.insert("article", article.to_json());
    data.insert("comments_count", article.comments.len().to_json());
    let mentions: Vec<String> = article.comments.into_iter().map(|c|c.user.username).collect();
    data.insert("mentions", mentions.to_json());
    data.insert("is_my_own", is_my_own.to_json());
    temp_response("article/show", &data)
}

pub fn edit_load(req: &mut Request) -> IronResult<Response> {
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut result = pool.prep_exec(
        "SELECT a.id, a.category, a.title, a.content, a.comments_count, \
         a.create_time, u.id as user_id, u.username, u.email from article \
         as a join user as u on a.user_id=u.id where a.id=? and a.status=?",
        (&article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

    let raw_row = result.next();
    if raw_row.is_none() {
        return not_found_response();
    }
    let row = raw_row.unwrap().unwrap();
    let (id, category, title, content, comments_count,
         create_time, user_id, username, email) = my::from_row::<
            (_,_,_,_,_,_,_,_,String)>(row);

    if user_id != user.id {
        return not_found_response();
    }

    let article = Article {
        id: id,
        category: Category::from_value(category),
        title: title,
        content: content,
        comments_count: comments_count,
        user: User{
            id: user_id,
            avatar: gen_gravatar_url(&email),
            username: username,
            email: email,
            create_time: *constant::DEFAULT_DATETIME,
        },
        create_time: create_time,
        update_time: *constant::DEFAULT_DATETIME,
        flag: 0,
        comments: Vec::new(),
    };

    let mut data = ResponseData::new(req);

    data.insert("categories", util::gen_categories_json(Some(category)));
    data.insert("article", article.to_json());
    temp_response("article/edit_load", &data)
}

pub fn edit(req: &mut Request) -> IronResult<Response> {
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let mut validator = Validator::new();
    validator
        .add_checker(Checker::new("category", Int, "类别") << Lambda(Box::new(Arc::new(|v| {
            !(constant::CATEGORY::ALL.iter().find(|c|**c as i64 == v.downcast_ref_unchecked::<IntValue>().value()).is_none())
        }))))
        .add_checker(Checker::new("title", Str, "标题") << Min(3) << Max(64))
        .add_checker(Checker::new("content", Str, "内容") << Min(7));

    validator.validate(req.get::<UrlEncodedBody>());
    if !validator.is_valid() {
        return json_error_response(&validator.messages[0]);
    }

    let category = validator.get_valid::<IntValue>("category").value();
    let title = validator.get_valid::<StrValue>("title").value();
    let content = validator.get_valid::<StrValue>("content").value();
    let now = Local::now().naive_local();

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut trans = pool.start_transaction(false, None, None).unwrap();

    {
        let mut result = trans.prep_exec(
            "SELECT u.id as user_id from article \
             as a join user as u on a.user_id=u.id \
             where a.id=? and a.status=? for update",
            (article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

        let raw_row = result.next();
        if raw_row.is_none() {
            return not_found_response();
        }

        let row = raw_row.unwrap().unwrap();
        let user_id = my::from_row::<u64>(row);

        if user_id != user.id {
            return json_error_response("非法请求");
        }
    }

    trans.prep_exec("UPDATE article set category=?, title=?, content=?, \
                     update_time=? where id=?",
                    (category, title, content, now, article_id)).unwrap();

    trans.commit().unwrap();

    json_ok_response()
}
<commit_msg>fix a mysql bug when create article<commit_after>use iron::prelude::*;
use base::framework::{ResponseData, temp_response,
                      json_error_response, json_ok_response,
                      not_found_response};
use urlencoded::UrlEncodedBody;
use base::db::MyPool;
use base::validator::{Validator, Checker, Str, StrValue, Int, IntValue, Max, Min, Lambda};
use base::framework::LoginUser;
use base::util::render_html;
use iron_login::User as U;
use persistent::Read;
use chrono::*;
use router::Router;
use mysql as my;
use base::model::{Article, User, Category, Comment};
use rustc_serialize::json::ToJson;
use base::util;
use base::util::gen_gravatar_url;
use base::constant;
use std::sync::Arc;

pub fn new_load(req: &mut Request) -> IronResult<Response> {
    let mut data = ResponseData::new(req);
    data.insert("categories", util::gen_categories_json(None));
    temp_response("article/new_load", &data)
}

pub fn new(req: &mut Request) -> IronResult<Response> {
    let mut validator = Validator::new();
    validator
        .add_checker(Checker::new("category", Int, "类别") << Lambda(Box::new(Arc::new(|v| {
            !(constant::CATEGORY::ALL.iter().find(|c|**c as i64 == v.downcast_ref_unchecked::<IntValue>().value()).is_none())
        }))))
        .add_checker(Checker::new("title", Str, "标题") << Min(3) << Max(64))
        .add_checker(Checker::new("content", Str, "内容") << Min(7));

    validator.validate(req.get::<UrlEncodedBody>());
    if !validator.is_valid() {
        return json_error_response(&validator.messages[0]);
    }

    let category = validator.get_valid::<IntValue>("category").value();
    let title = validator.get_valid::<StrValue>("title").value();
    let content = validator.get_valid::<StrValue>("content").value();
    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let now = Local::now().naive_local();
    let mut stmt = pool.prepare("INSERT INTO article(category, title, content, \
                                 user_id, create_time, update_time) \
                                 VALUES (?, ?, ?, ?, ?, ?)").unwrap();
    let result = stmt.execute((category, title, content, user.id, now, now));
    result.unwrap();
    json_ok_response()
}

pub fn show(req: &mut Request) -> IronResult<Response> {
    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut result = pool.prep_exec(
        "SELECT a.id, a.category, a.title, a.content, a.comments_count, \
         a.create_time, u.id as user_id, u.username, u.email from article \
         as a join user as u on a.user_id=u.id where a.id=? and a.status=?",
        (&article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

    let raw_row = result.next();
    if raw_row.is_none() {
        return not_found_response();
    }
    let row = raw_row.unwrap().unwrap();
    let (id, category, title, content, comments_count, create_time, user_id, username, email) = my::from_row::<(_,_,_,_,_,_,_,_,String)>(row);
    let mut article = Article {
        id: id,
        category: Category::from_value(category),
        title: title,
        content: content,
        comments_count: comments_count,
        user: User{
            id: user_id,
            avatar: gen_gravatar_url(&email),
            username: username,
            email: email,
            create_time: *constant::DEFAULT_DATETIME,
        },
        create_time: create_time,
        update_time: *constant::DEFAULT_DATETIME,
        flag: 0,
        comments: Vec::new(),
    };
    article.content = render_html(&article.content);

    let result = pool.prep_exec(
        "SELECT c.id, c.content, c.create_time, u.id as user_id, \
         u.username, u.email from comment \
         as c join user as u on c.user_id=u.id where c.article_id=? \
         order by c.create_time", (&article_id, )).unwrap();

    article.comments = result.map(|x| x.unwrap()).map(|row|{
        let (id, content, create_time, user_id, username, email) = my::from_row::<(_,String,_,_,_,String)>(row);
        Comment {
            id: id,
            content: render_html(&content),
            user: User {
                id: user_id,
                avatar: gen_gravatar_url(&email),
                username: username,
                email: email,
                create_time: *constant::DEFAULT_DATETIME,
            },
            create_time: create_time,
            article: None,
        }
    }).collect();

    // judge whether is my article
    let mut is_my_own = false;
    let raw_login_user = LoginUser::get_login(req).get_user();
    if let Some(login_user) = raw_login_user {
        if login_user.id == article.user.id {
            is_my_own = true;
        }
    }

    let mut data = ResponseData::new(req);
    data.insert("article", article.to_json());
    data.insert("comments_count", article.comments.len().to_json());
    let mentions: Vec<String> = article.comments.into_iter().map(|c|c.user.username).collect();
    data.insert("mentions", mentions.to_json());
    data.insert("is_my_own", is_my_own.to_json());
    temp_response("article/show", &data)
}

pub fn edit_load(req: &mut Request) -> IronResult<Response> {
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut result = pool.prep_exec(
        "SELECT a.id, a.category, a.title, a.content, a.comments_count, \
         a.create_time, u.id as user_id, u.username, u.email from article \
         as a join user as u on a.user_id=u.id where a.id=? and a.status=?",
        (&article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

    let raw_row = result.next();
    if raw_row.is_none() {
        return not_found_response();
    }
    let row = raw_row.unwrap().unwrap();
    let (id, category, title, content, comments_count,
         create_time, user_id, username, email) = my::from_row::<
            (_,_,_,_,_,_,_,_,String)>(row);

    if user_id != user.id {
        return not_found_response();
    }

    let article = Article {
        id: id,
        category: Category::from_value(category),
        title: title,
        content: content,
        comments_count: comments_count,
        user: User{
            id: user_id,
            avatar: gen_gravatar_url(&email),
            username: username,
            email: email,
            create_time: *constant::DEFAULT_DATETIME,
        },
        create_time: create_time,
        update_time: *constant::DEFAULT_DATETIME,
        flag: 0,
        comments: Vec::new(),
    };

    let mut data = ResponseData::new(req);

    data.insert("categories", util::gen_categories_json(Some(category)));
    data.insert("article", article.to_json());
    temp_response("article/edit_load", &data)
}

pub fn edit(req: &mut Request) -> IronResult<Response> {
    let login = LoginUser::get_login(req);
    let user = login.get_user().unwrap();

    let article_id = try!(req.extensions.get::<Router>().unwrap()
                       .find("article_id").unwrap()
                       .parse::<u64>().map_err(|_| not_found_response().unwrap_err()));

    let mut validator = Validator::new();
    validator
        .add_checker(Checker::new("category", Int, "类别") << Lambda(Box::new(Arc::new(|v| {
            !(constant::CATEGORY::ALL.iter().find(|c|**c as i64 == v.downcast_ref_unchecked::<IntValue>().value()).is_none())
        }))))
        .add_checker(Checker::new("title", Str, "标题") << Min(3) << Max(64))
        .add_checker(Checker::new("content", Str, "内容") << Min(7));

    validator.validate(req.get::<UrlEncodedBody>());
    if !validator.is_valid() {
        return json_error_response(&validator.messages[0]);
    }

    let category = validator.get_valid::<IntValue>("category").value();
    let title = validator.get_valid::<StrValue>("title").value();
    let content = validator.get_valid::<StrValue>("content").value();
    let now = Local::now().naive_local();

    let pool = req.get::<Read<MyPool>>().unwrap().value();
    let mut trans = pool.start_transaction(false, None, None).unwrap();

    {
        let mut result = trans.prep_exec(
            "SELECT u.id as user_id from article \
             as a join user as u on a.user_id=u.id \
             where a.id=? and a.status=? for update",
            (article_id, constant::ARTICLE::STATUS::NORMAL)).unwrap();

        let raw_row = result.next();
        if raw_row.is_none() {
            return not_found_response();
        }

        let row = raw_row.unwrap().unwrap();
        let user_id = my::from_row::<u64>(row);

        if user_id != user.id {
            return json_error_response("非法请求");
        }
    }

    trans.prep_exec("UPDATE article set category=?, title=?, content=?, \
                     update_time=? where id=?",
                    (category, title, content, now, article_id)).unwrap();

    trans.commit().unwrap();

    json_ok_response()
}
<|endoftext|>


<commit_before>#![allow(missing_copy_implementations)]

use UpdateBigFloat;
use BigFloat;

pub struct BigFloatBuilder;

macro_rules! impl_building {
    ($target:ty, $constructor:expr) => {
        impl $target {
            #[inline]
            pub fn fresh(self) -> BigFloat {
                $constructor(self)
            }

            #[inline]
            pub fn from<T: UpdateBigFloat>(self, value: T) -> BigFloat {
                let mut r = self.fresh();
                r.set_to(value);
                r
            }

            #[inline]
            pub fn const_log2(self) -> BigFloat {
                let mut r = self.fresh();
                r.set_to_const_log2();
                r
            }

            #[inline]
            pub fn const_pi(self) -> BigFloat {
                let mut r = self.fresh();
                r.set_to_const_pi();
                r
            }

            #[inline]
            pub fn const_euler(self) -> BigFloat {
                let mut r = self.fresh();
                r.set_to_const_euler();
                r
            }

            #[inline]
            pub fn const_catalan(self) -> BigFloat {
                let mut r = self.fresh();
                r.set_to_const_catalan();
                r
            }
        }
    }
}

impl BigFloatBuilder {
    #[inline]
    pub fn with_prec(self, precision: usize) -> BigFloatBuilderWithPrec {
        BigFloatBuilderWithPrec(precision)
    }
}

impl_building! { BigFloatBuilder, |:_| BigFloat::fresh() }

pub struct BigFloatBuilderWithPrec(usize);

impl_building! {
    BigFloatBuilderWithPrec,
    |: this: BigFloatBuilderWithPrec| BigFloat::fresh_with_prec(this.0)
}
<commit_msg>Refactored const methods in builder<commit_after>#![allow(missing_copy_implementations)]

use UpdateBigFloat;
use BigFloat;

pub struct BigFloatBuilder;

macro_rules! generate_const_methods {
    ($target:ty, $($method:ident -> $setter:ident),+) => {
        impl $target {
            $(
            #[inline]
            pub fn $method(self) -> BigFloat {
                let mut r = self.fresh();
                r.$setter();
                r
            }
            )+
        }
    }
}

macro_rules! impl_building {
    ($target:ty, $constructor:expr) => {
        impl $target {
            #[inline]
            pub fn fresh(self) -> BigFloat {
                $constructor(self)
            }

            #[inline]
            pub fn from<T: UpdateBigFloat>(self, value: T) -> BigFloat {
                let mut r = self.fresh();
                r.set_to(value);
                r
            }
        }

        generate_const_methods! { $target,
            const_log2 -> set_to_const_log2,
            const_pi -> set_to_const_pi,
            const_euler -> set_to_const_euler,
            const_catalan -> set_to_const_catalan
        }
    }
}

impl BigFloatBuilder {
    #[inline]
    pub fn with_prec(self, precision: usize) -> BigFloatBuilderWithPrec {
        BigFloatBuilderWithPrec(precision)
    }
}

impl_building! { BigFloatBuilder, |:_| BigFloat::fresh() }

pub struct BigFloatBuilderWithPrec(usize);

impl_building! {
    BigFloatBuilderWithPrec,
    |: this: BigFloatBuilderWithPrec| BigFloat::fresh_with_prec(this.0)
}
<|endoftext|>


<commit_before>use super::*;

pub enum InsertSearchResult {
    External,
    Internal(NodeCellRef),
    RightNode(NodeCellRef),
}

pub enum InsertToNodeResult {
    NoSplit,
    Split(NodeWriteGuard, NodeCellRef, Option<EntryKey>),
    SplitParentChanged,
}

pub enum RemoveSearchResult {
    External,
    RightNode(NodeCellRef),
    Internal(NodeCellRef, SubNodeStatus),
}

pub enum SubNodeStatus {
    ExtNodeEmpty,
    InNodeEmpty,
    Relocate(usize, usize),
    Merge(usize, usize),
    Ok,
}

pub struct NodeSplit {
    pub new_right_node: NodeCellRef,
    pub left_node_latch: NodeWriteGuard,
    pub pivot: EntryKey,
    pub parent_latch: Option<NodeWriteGuard>,
}

pub enum NodeSplitResult {
    Split(NodeSplit),
    Retry,
}

pub enum NodeData {
    External(Box<ExtNode>),
    Internal(Box<InNode>),
    None,
}

impl NodeData {
    pub fn is_none(&self) -> bool {
        match self {
            &NodeData::None => true,
            _ => false,
        }
    }
    pub fn search(&self, key: &EntryKey) -> usize {
        let len = self.len();
        if self.is_ext() {
            self.extnode().keys[..len]
                .binary_search(key)
                .unwrap_or_else(|i| i)
        } else {
            self.innode().keys[..len]
                .binary_search(key)
                .map(|i| i + 1)
                .unwrap_or_else(|i| i)
        }
    }

    pub fn remove(&mut self, pos: usize) {
        match self {
            &mut NodeData::External(ref mut node) => node.remove_at(pos),
            &mut NodeData::Internal(ref mut node) => node.remove_at(pos),
            &mut NodeData::None => unreachable!(),
        }
    }
    pub fn is_ext(&self) -> bool {
        match self {
            &NodeData::External(_) => true,
            &NodeData::Internal(_) => false,
            &NodeData::None => panic!(),
        }
    }
    pub fn first_key(&self) -> EntryKey {
        if self.is_ext() {
            self.extnode().keys[0].to_owned()
        } else {
            self.innode().keys[0].to_owned()
        }
    }
    pub fn len(&self) -> usize {
        if self.is_ext() {
            self.extnode().len
        } else {
            self.innode().len
        }
    }
    pub fn is_half_full(&self) -> bool {
        self.len() >= NUM_KEYS / 2
    }
    pub fn cannot_merge(&self) -> bool {
        self.len() > NUM_KEYS / 2
    }
    pub fn extnode_mut(&mut self) -> &mut ExtNode {
        match self {
            &mut NodeData::External(ref mut node) => node,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn innode_mut(&mut self) -> &mut InNode {
        match self {
            &mut NodeData::Internal(ref mut n) => n,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn extnode(&self) -> &ExtNode {
        match self {
            &NodeData::External(ref node) => node,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn ext_id(&self) -> Id {
        match self {
            &NodeData::External(ref node) => node.id,
            &NodeData::None => Id::unit_id(),
            &NodeData::Internal(ref node) => unreachable!(self.type_name()),
        }
    }
    pub fn innode(&self) -> &InNode {
        match self {
            &NodeData::Internal(ref n) => n,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn type_name(&self) -> &'static str {
        match self {
            &NodeData::Internal(_) => "internal",
            &NodeData::External(_) => "external",
            &NodeData::None => "none",
        }
    }
    pub fn key_at_right_node(&self, key: &EntryKey) -> Option<&NodeCellRef> {
        // return None;
        if self.len() > 0 {
            match self {
                &NodeData::Internal(ref n) => {
                    if &n.keys[n.len - 1] < key {
                        let right_node = n.right.read_unchecked();
                        if !right_node.is_none() {
                            let right_innode = right_node.innode();
                            if right_innode.keys.len() > 0 && &right_innode.keys[0] < key {
                                debug!(
                                    "found key to put to right internal page {:?}/{:?}",
                                    key, &right_innode.keys[0]
                                );
                                return Some(&n.right);
                            }
                        }
                    }
                }
                &NodeData::External(ref n) => {
                    if &n.keys[n.len - 1] < key {
                        let right_node = n.next.read_unchecked();
                        if !right_node.is_none() {
                            let right_extnode = right_node.extnode();
                            if right_extnode.keys.len() > 0 && &right_extnode.keys[0] < key {
                                debug!(
                                    "found key to put to right external page {:?}/{:?}",
                                    key, &right_extnode.keys[0]
                                );
                                return Some(&n.next);
                            }
                        }
                    }
                }
                _ => unreachable!(),
            }
        }
        return None;
    }
}

pub fn write_key_page(search_page: NodeWriteGuard, key: &EntryKey) -> NodeWriteGuard {
    // return search_page;
    if search_page.len() > 0 {
        match &*search_page {
            &NodeData::Internal(ref n) => {
                if &n.keys[n.len - 1] < key {
                    let right_ref = &n.right;
                    debug!("Obtain latch for internal write key page");
                    let right_node = right_ref.write();
                    if !right_node.is_none()
                        && right_node.len() > 0
                        && &right_node.innode().keys[0] < key
                    {
                        debug_assert!(!right_node.is_ext());
                        debug!("will write to right internal page");
                        return write_key_page(right_node, key);
                    }
                }
            }
            &NodeData::External(ref n) => {
                if &n.keys[n.len - 1] < key {
                    let right_ref = &n.next;
                    debug!("Obtain latch for external write key page");
                    let right_node = right_ref.write();
                    if !right_node.is_none()
                        && right_node.len() > 0
                        && &right_node.extnode().keys[0] < key
                    {
                        debug_assert!(right_node.is_ext());
                        debug!("will write to right external page");
                        return write_key_page(right_node, key);
                    }
                }
            }
            _ => unreachable!(),
        }
        return search_page;
    } else {
        return search_page;
    }
}

const LATCH_FLAG: usize = !(!0 >> 1);

pub struct Node {
    data: UnsafeCell<NodeData>,
    cc: AtomicUsize,
}

impl Node {
    pub fn new(data: NodeData) -> Self {
        Node {
            data: UnsafeCell::new(data),
            cc: AtomicUsize::new(0),
        }
    }

    pub fn internal(innode: InNode) -> Self {
        Self::new(NodeData::Internal(box innode))
    }

    pub fn external(extnode: ExtNode) -> Self {
        Self::new(NodeData::External(box extnode))
    }

    pub fn none() -> Self {
        Self::new(NodeData::None)
    }
    pub fn none_ref() -> NodeCellRef {
        Arc::new(Node::none())
    }
    pub fn new_external(id: Id) -> Self {
        Self::external(ExtNode::new(id))
    }

    pub fn write(&self) -> NodeWriteGuard {
        let cc = &self.cc;
        loop {
            let cc_num = cc.load(Relaxed);
            let expected = cc_num & (!LATCH_FLAG);
            if cc.compare_and_swap(expected, cc_num | LATCH_FLAG, Relaxed) == expected {
                return NodeWriteGuard {
                    data: self.data.get(),
                    cc: &self.cc as *const AtomicUsize,
                    version: node_version(cc_num),
                };
            }
            debug!("acquire latch failed, retry {:b}", cc_num);
        }
    }

    pub fn read<'a, F: FnMut(&NodeReadHandler) -> R + 'a, R: 'a>(&'a self, mut func: F) -> R {
        let mut handler = NodeReadHandler {
            ptr: self.data.get(),
            version: 0,
        };
        let cc = &self.cc;
        loop {
            let cc_num = cc.load(Relaxed);
            if cc_num & LATCH_FLAG == LATCH_FLAG {
                debug!("read have a latch, retry {:b}", cc_num);
                continue;
            }
            handler.version = cc_num & (!LATCH_FLAG);
            let res = func(&handler);
            let new_cc_num = cc.load(Relaxed);
            if new_cc_num == cc_num {
                return res;
            }
            debug!("read version changed, retry {:b}", cc_num);
        }
    }

    pub fn read_unchecked(&self) -> &NodeData {
        unsafe { &*self.data.get() }
    }

    pub fn version(&self) -> usize {
        node_version(self.cc.load(Relaxed))
    }
}

pub fn node_version(cc_num: usize) -> usize {
    cc_num & (!LATCH_FLAG)
}

pub struct NodeWriteGuard {
    pub data: *mut NodeData,
    pub cc: *const AtomicUsize,
    pub version: usize,
}

impl Deref for NodeWriteGuard {
    type Target = NodeData;

    fn deref(&self) -> &<Self as Deref>::Target {
        debug_assert_ne!(self.data as usize, 0);
        unsafe { &*self.data }
    }
}

impl DerefMut for NodeWriteGuard {
    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
        debug_assert_ne!(self.data as usize, 0);
        unsafe { &mut *self.data }
    }
}

impl Drop for NodeWriteGuard {
    fn drop(&mut self) {
        // cope with null pointer
        if self.cc as usize != 0 {
            let cc = unsafe { &*self.cc };
            let cc_num = cc.load(Relaxed);
            cc.store((cc_num & (!LATCH_FLAG)) + 1, Relaxed);
        }
    }
}

impl Default for NodeWriteGuard {
    fn default() -> Self {
        NodeWriteGuard {
            data: 0 as *mut NodeData,
            cc: 0 as *const AtomicUsize,
            version: 0,
        }
    }
}

pub struct NodeReadHandler {
    pub ptr: *const NodeData,
    pub version: usize,
}

impl Deref for NodeReadHandler {
    type Target = NodeData;

    fn deref(&self) -> &<Self as Deref>::Target {
        unsafe { &*self.ptr }
    }
}

pub struct RemoveStatus {
    pub item_found: bool,
    pub removed: bool,
}

impl Default for Node {
    fn default() -> Self {
        Node::none()
    }
}

pub fn insert_into_split<T, S>(
    item: T,
    x: &mut S,
    y: &mut S,
    xlen: &mut usize,
    ylen: &mut usize,
    pos: usize,
) where
    S: Slice<Item = T> + BTreeSlice<T>,
    T: Default,
{
    debug!(
        "insert into split left len {}, right len {}, pos {}",
        xlen, ylen, pos
    );
    if pos < *xlen {
        debug!("insert into left part, pos: {}", pos);
        x.insert_at(item, pos, xlen);
    } else {
        let right_pos = pos - *xlen;
        debug!("insert into right part, pos: {}", right_pos);
        y.insert_at(item, right_pos, ylen);
    }
}
<commit_msg>tackling ordering<commit_after>use super::*;
use std::sync::atomic::fence;
use std::sync::atomic::Ordering::AcqRel;
use std::sync::atomic::Ordering::Acquire;
use std::sync::atomic::Ordering::Release;

pub enum InsertSearchResult {
    External,
    Internal(NodeCellRef),
    RightNode(NodeCellRef),
}

pub enum InsertToNodeResult {
    NoSplit,
    Split(NodeWriteGuard, NodeCellRef, Option<EntryKey>),
    SplitParentChanged,
}

pub enum RemoveSearchResult {
    External,
    RightNode(NodeCellRef),
    Internal(NodeCellRef, SubNodeStatus),
}

pub enum SubNodeStatus {
    ExtNodeEmpty,
    InNodeEmpty,
    Relocate(usize, usize),
    Merge(usize, usize),
    Ok,
}

pub struct NodeSplit {
    pub new_right_node: NodeCellRef,
    pub left_node_latch: NodeWriteGuard,
    pub pivot: EntryKey,
    pub parent_latch: Option<NodeWriteGuard>,
}

pub enum NodeSplitResult {
    Split(NodeSplit),
    Retry,
}

pub enum NodeData {
    External(Box<ExtNode>),
    Internal(Box<InNode>),
    None,
}

impl NodeData {
    pub fn is_none(&self) -> bool {
        match self {
            &NodeData::None => true,
            _ => false,
        }
    }
    pub fn search(&self, key: &EntryKey) -> usize {
        let len = self.len();
        if self.is_ext() {
            self.extnode().keys[..len]
                .binary_search(key)
                .unwrap_or_else(|i| i)
        } else {
            self.innode().keys[..len]
                .binary_search(key)
                .map(|i| i + 1)
                .unwrap_or_else(|i| i)
        }
    }

    pub fn remove(&mut self, pos: usize) {
        match self {
            &mut NodeData::External(ref mut node) => node.remove_at(pos),
            &mut NodeData::Internal(ref mut node) => node.remove_at(pos),
            &mut NodeData::None => unreachable!(),
        }
    }
    pub fn is_ext(&self) -> bool {
        match self {
            &NodeData::External(_) => true,
            &NodeData::Internal(_) => false,
            &NodeData::None => panic!(),
        }
    }
    pub fn first_key(&self) -> EntryKey {
        if self.is_ext() {
            self.extnode().keys[0].to_owned()
        } else {
            self.innode().keys[0].to_owned()
        }
    }
    pub fn len(&self) -> usize {
        if self.is_ext() {
            self.extnode().len
        } else {
            self.innode().len
        }
    }
    pub fn is_half_full(&self) -> bool {
        self.len() >= NUM_KEYS / 2
    }
    pub fn cannot_merge(&self) -> bool {
        self.len() > NUM_KEYS / 2
    }
    pub fn extnode_mut(&mut self) -> &mut ExtNode {
        match self {
            &mut NodeData::External(ref mut node) => node,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn innode_mut(&mut self) -> &mut InNode {
        match self {
            &mut NodeData::Internal(ref mut n) => n,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn extnode(&self) -> &ExtNode {
        match self {
            &NodeData::External(ref node) => node,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn ext_id(&self) -> Id {
        match self {
            &NodeData::External(ref node) => node.id,
            &NodeData::None => Id::unit_id(),
            &NodeData::Internal(ref node) => unreachable!(self.type_name()),
        }
    }
    pub fn innode(&self) -> &InNode {
        match self {
            &NodeData::Internal(ref n) => n,
            _ => unreachable!(self.type_name()),
        }
    }
    pub fn type_name(&self) -> &'static str {
        match self {
            &NodeData::Internal(_) => "internal",
            &NodeData::External(_) => "external",
            &NodeData::None => "none",
        }
    }
    pub fn key_at_right_node(&self, key: &EntryKey) -> Option<&NodeCellRef> {
        // return None;
        if self.len() > 0 {
            match self {
                &NodeData::Internal(ref n) => {
                    if &n.keys[n.len - 1] < key {
                        let right_node = n.right.read_unchecked();
                        if !right_node.is_none() {
                            let right_innode = right_node.innode();
                            if right_innode.keys.len() > 0 && &right_innode.keys[0] < key {
                                debug!(
                                    "found key to put to right internal page {:?}/{:?}",
                                    key, &right_innode.keys[0]
                                );
                                return Some(&n.right);
                            }
                        }
                    }
                }
                &NodeData::External(ref n) => {
                    if &n.keys[n.len - 1] < key {
                        let right_node = n.next.read_unchecked();
                        if !right_node.is_none() {
                            let right_extnode = right_node.extnode();
                            if right_extnode.keys.len() > 0 && &right_extnode.keys[0] < key {
                                debug!(
                                    "found key to put to right external page {:?}/{:?}",
                                    key, &right_extnode.keys[0]
                                );
                                return Some(&n.next);
                            }
                        }
                    }
                }
                _ => unreachable!(),
            }
        }
        return None;
    }
}

pub fn write_key_page(search_page: NodeWriteGuard, key: &EntryKey) -> NodeWriteGuard {
    // return search_page;
    if search_page.len() > 0 {
        match &*search_page {
            &NodeData::Internal(ref n) => {
                if &n.keys[n.len - 1] < key {
                    let right_ref = &n.right;
                    debug!("Obtain latch for internal write key page");
                    let right_node = right_ref.write();
                    if !right_node.is_none()
                        && right_node.len() > 0
                        && &right_node.innode().keys[0] < key
                    {
                        debug_assert!(!right_node.is_ext());
                        debug!("will write to right internal page");
                        return write_key_page(right_node, key);
                    }
                }
            }
            &NodeData::External(ref n) => {
                if &n.keys[n.len - 1] < key {
                    let right_ref = &n.next;
                    debug!("Obtain latch for external write key page");
                    let right_node = right_ref.write();
                    if !right_node.is_none()
                        && right_node.len() > 0
                        && &right_node.extnode().keys[0] < key
                    {
                        debug_assert!(right_node.is_ext());
                        debug!("will write to right external page");
                        return write_key_page(right_node, key);
                    }
                }
            }
            _ => unreachable!(),
        }
        return search_page;
    } else {
        return search_page;
    }
}

const LATCH_FLAG: usize = !(!0 >> 1);

pub struct Node {
    data: UnsafeCell<NodeData>,
    cc: AtomicUsize,
}

impl Node {
    pub fn new(data: NodeData) -> Self {
        Node {
            data: UnsafeCell::new(data),
            cc: AtomicUsize::new(0),
        }
    }

    pub fn internal(innode: InNode) -> Self {
        Self::new(NodeData::Internal(box innode))
    }

    pub fn external(extnode: ExtNode) -> Self {
        Self::new(NodeData::External(box extnode))
    }

    pub fn none() -> Self {
        Self::new(NodeData::None)
    }
    pub fn none_ref() -> NodeCellRef {
        Arc::new(Node::none())
    }
    pub fn new_external(id: Id) -> Self {
        Self::external(ExtNode::new(id))
    }

    pub fn write(&self) -> NodeWriteGuard {
        let cc = &self.cc;
        loop {
            let cc_num = cc.load(Relaxed);
            let expected = cc_num & (!LATCH_FLAG);

            match cc.compare_exchange_weak(expected, cc_num | LATCH_FLAG, Acquire, Relaxed) {
                Ok(num) if num == expected => return NodeWriteGuard {
                    data: self.data.get(),
                    cc: &self.cc as *const AtomicUsize,
                    version: node_version(cc_num),
                },
                _ => {}
            }

            debug!("acquire latch failed, retry {:b}", cc_num);
        }
    }

    pub fn read<'a, F: FnMut(&NodeReadHandler) -> R + 'a, R: 'a>(&'a self, mut func: F) -> R {
        let mut handler = NodeReadHandler {
            ptr: self.data.get(),
            version: 0,
        };
        let cc = &self.cc;
        loop {
            let cc_num = cc.load(SeqCst);
            if cc_num & LATCH_FLAG == LATCH_FLAG {
                debug!("read have a latch, retry {:b}", cc_num);
                continue;
            }
            handler.version = cc_num & (!LATCH_FLAG);
            let res = func(&handler);
            let new_cc_num = cc.load(SeqCst);
            if new_cc_num == cc_num {
                return res;
            }
            debug!("read version changed, retry {:b}", cc_num);
        }
    }

    pub fn read_unchecked(&self) -> &NodeData {
        unsafe { &*self.data.get() }
    }

    pub fn version(&self) -> usize {
        node_version(self.cc.load(SeqCst))
    }
}

pub fn node_version(cc_num: usize) -> usize {
    cc_num & (!LATCH_FLAG)
}

pub struct NodeWriteGuard {
    pub data: *mut NodeData,
    pub cc: *const AtomicUsize,
    pub version: usize,
}

impl Deref for NodeWriteGuard {
    type Target = NodeData;

    fn deref(&self) -> &<Self as Deref>::Target {
        debug_assert_ne!(self.data as usize, 0);
        unsafe { &*self.data }
    }
}

impl DerefMut for NodeWriteGuard {
    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
        debug_assert_ne!(self.data as usize, 0);
        unsafe { &mut *self.data }
    }
}

impl Drop for NodeWriteGuard {
    fn drop(&mut self) {
        // cope with null pointer
        if self.cc as usize != 0 {
            let cc = unsafe { &*self.cc };
            let cc_num = cc.load(SeqCst);
            cc.store((cc_num & (!LATCH_FLAG)) + 1, Release);
        }
    }
}

impl Default for NodeWriteGuard {
    fn default() -> Self {
        NodeWriteGuard {
            data: 0 as *mut NodeData,
            cc: 0 as *const AtomicUsize,
            version: 0,
        }
    }
}

pub struct NodeReadHandler {
    pub ptr: *const NodeData,
    pub version: usize,
}

impl Deref for NodeReadHandler {
    type Target = NodeData;

    fn deref(&self) -> &<Self as Deref>::Target {
        unsafe { &*self.ptr }
    }
}

pub struct RemoveStatus {
    pub item_found: bool,
    pub removed: bool,
}

impl Default for Node {
    fn default() -> Self {
        Node::none()
    }
}

pub fn insert_into_split<T, S>(
    item: T,
    x: &mut S,
    y: &mut S,
    xlen: &mut usize,
    ylen: &mut usize,
    pos: usize,
) where
    S: Slice<Item = T> + BTreeSlice<T>,
    T: Default,
{
    debug!(
        "insert into split left len {}, right len {}, pos {}",
        xlen, ylen, pos
    );
    if pos < *xlen {
        debug!("insert into left part, pos: {}", pos);
        x.insert_at(item, pos, xlen);
    } else {
        let right_pos = pos - *xlen;
        debug!("insert into right part, pos: {}", right_pos);
        y.insert_at(item, right_pos, ylen);
    }
}
<|endoftext|>