<commit_before>//! This module provides `StaticIndex` which is used for powering
//! read-only code browsers and emitting LSIF

use std::collections::HashMap;

use hir::{db::HirDatabase, Crate, Module, Semantics};
use ide_db::{
    base_db::{FileId, FileRange, SourceDatabaseExt},
    defs::{Definition, IdentClass},
    FxHashSet, RootDatabase,
};
use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};

use crate::{
    hover::hover_for_definition,
    moniker::{crate_for_file, def_to_moniker, MonikerResult},
    Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
    TryToNav,
};

/// A static representation of fully analyzed source code.
///
/// The intended use-case is powering read-only code browsers and emitting LSIF
#[derive(Debug)]
pub struct StaticIndex<'a> {
    pub files: Vec<StaticIndexedFile>,
    pub tokens: TokenStore,
    analysis: &'a Analysis,
    db: &'a RootDatabase,
    def_map: HashMap<Definition, TokenId>,
}

#[derive(Debug)]
pub struct ReferenceData {
    pub range: FileRange,
    pub is_definition: bool,
}

#[derive(Debug)]
pub struct TokenStaticData {
    pub hover: Option<HoverResult>,
    pub definition: Option<FileRange>,
    pub references: Vec<ReferenceData>,
    pub moniker: Option<MonikerResult>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenId(usize);

impl TokenId {
    pub fn raw(self) -> usize {
        self.0
    }
}

#[derive(Default, Debug)]
pub struct TokenStore(Vec<TokenStaticData>);

impl TokenStore {
    pub fn insert(&mut self, data: TokenStaticData) -> TokenId {
        let id = TokenId(self.0.len());
        self.0.push(data);
        id
    }

    pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData> {
        self.0.get_mut(id.0)
    }

    pub fn get(&self, id: TokenId) -> Option<&TokenStaticData> {
        self.0.get(id.0)
    }

    pub fn iter(self) -> impl Iterator<Item = (TokenId, TokenStaticData)> {
        self.0.into_iter().enumerate().map(|(i, x)| (TokenId(i), x))
    }
}

#[derive(Debug)]
pub struct StaticIndexedFile {
    pub file_id: FileId,
    pub folds: Vec<Fold>,
    pub inlay_hints: Vec<InlayHint>,
    pub tokens: Vec<(TextRange, TokenId)>,
}

fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
    let mut worklist: Vec<_> =
        Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
    let mut modules = Vec::new();

    while let Some(module) = worklist.pop() {
        modules.push(module);
        worklist.extend(module.children(db));
    }

    modules
}

impl StaticIndex<'_> {
    fn add_file(&mut self, file_id: FileId) {
        let current_crate = crate_for_file(self.db, file_id);
        let folds = self.analysis.folding_ranges(file_id).unwrap();
        let inlay_hints = self
            .analysis
            .inlay_hints(
                &InlayHintsConfig {
                    render_colons: true,
                    type_hints: true,
                    parameter_hints: true,
                    chaining_hints: true,
                    closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
                    lifetime_elision_hints: crate::LifetimeElisionHints::Never,
                    reborrow_hints: crate::ReborrowHints::Never,
                    hide_named_constructor_hints: false,
                    hide_closure_initialization_hints: false,
                    param_names_for_lifetime_elision_hints: false,
                    binding_mode_hints: false,
                    max_length: Some(25),
                    closing_brace_hints_min_lines: Some(25),
                },
                file_id,
                None,
            )
            .unwrap();
        // hovers
        let sema = hir::Semantics::new(self.db);
        let tokens_or_nodes = sema.parse(file_id).syntax().clone();
        let tokens = tokens_or_nodes.descendants_with_tokens().filter_map(|x| match x {
            syntax::NodeOrToken::Node(_) => None,
            syntax::NodeOrToken::Token(x) => Some(x),
        });
        let hover_config = HoverConfig {
            links_in_hover: true,
            documentation: Some(HoverDocFormat::Markdown),
            keywords: true,
        };
        let tokens = tokens.filter(|token| {
            matches!(
                token.kind(),
                IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] | T![Self]
            )
        });
        let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] };
        for token in tokens {
            let range = token.text_range();
            let node = token.parent().unwrap();
            let def = match get_definition(&sema, token.clone()) {
                Some(x) => x,
                None => continue,
            };
            let id = if let Some(x) = self.def_map.get(&def) {
                *x
            } else {
                let x = self.tokens.insert(TokenStaticData {
                    hover: hover_for_definition(&sema, file_id, def, &node, &hover_config),
                    definition: def
                        .try_to_nav(self.db)
                        .map(|x| FileRange { file_id: x.file_id, range: x.focus_or_full_range() }),
                    references: vec![],
                    moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
                });
                self.def_map.insert(def, x);
                x
            };
            let token = self.tokens.get_mut(id).unwrap();
            token.references.push(ReferenceData {
                range: FileRange { range, file_id },
                is_definition: match def.try_to_nav(self.db) {
                    Some(x) => x.file_id == file_id && x.focus_or_full_range() == range,
                    None => false,
                },
            });
            result.tokens.push((range, id));
        }
        self.files.push(result);
    }

    pub fn compute(analysis: &Analysis) -> StaticIndex<'_> {
        let db = &*analysis.db;
        let work = all_modules(db).into_iter().filter(|module| {
            let file_id = module.definition_source(db).file_id.original_file(db);
            let source_root = db.file_source_root(file_id);
            let source_root = db.source_root(source_root);
            !source_root.is_library
        });
        let mut this = StaticIndex {
            files: vec![],
            tokens: Default::default(),
            analysis,
            db,
            def_map: Default::default(),
        };
        let mut visited_files = FxHashSet::default();
        for module in work {
            let file_id = module.definition_source(db).file_id.original_file(db);
            if visited_files.contains(&file_id) {
                continue;
            }
            this.add_file(file_id);
            // mark the file
            visited_files.insert(file_id);
        }
        this
    }
}

fn get_definition(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Definition> {
    for token in sema.descend_into_macros(token) {
        let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
        if let Some(&[x]) = def.as_deref() {
            return Some(x);
        } else {
            continue;
        };
    }
    None
}

#[cfg(test)]
mod tests {
    use crate::{fixture, StaticIndex};
    use ide_db::base_db::FileRange;
    use std::collections::HashSet;
    use syntax::TextSize;

    fn check_all_ranges(ra_fixture: &str) {
        let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
        let s = StaticIndex::compute(&analysis);
        let mut range_set: HashSet<_> = ranges.iter().map(|x| x.0).collect();
        for f in s.files {
            for (range, _) in f.tokens {
                let x = FileRange { file_id: f.file_id, range };
                if !range_set.contains(&x) {
                    panic!("additional range {:?}", x);
                }
                range_set.remove(&x);
            }
        }
        if !range_set.is_empty() {
            panic!("unfound ranges {:?}", range_set);
        }
    }

    fn check_definitions(ra_fixture: &str) {
        let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
        let s = StaticIndex::compute(&analysis);
        let mut range_set: HashSet<_> = ranges.iter().map(|x| x.0).collect();
        for (_, t) in s.tokens.iter() {
            if let Some(x) = t.definition {
                if x.range.start() == TextSize::from(0) {
                    // ignore definitions that are whole of file
                    continue;
                }
                if !range_set.contains(&x) {
                    panic!("additional definition {:?}", x);
                }
                range_set.remove(&x);
            }
        }
        if !range_set.is_empty() {
            panic!("unfound definitions {:?}", range_set);
        }
    }

    #[test]
    fn struct_and_enum() {
        check_all_ranges(
            r#"
struct Foo;
     //^^^
enum E { X(Foo) }
   //^   ^ ^^^
"#,
        );
        check_definitions(
            r#"
struct Foo;
     //^^^
enum E { X(Foo) }
   //^   ^
"#,
        );
    }

    #[test]
    fn multi_crate() {
        check_definitions(
            r#"
//- /main.rs crate:main deps:foo

use foo::func;

fn main() {
 //^^^^
    func();
}
//- /foo/lib.rs crate:foo

pub func() {

}
"#,
        );
    }

    #[test]
    fn derives() {
        check_all_ranges(
            r#"
//- minicore:derive
#[rustc_builtin_macro]
//^^^^^^^^^^^^^^^^^^^
pub macro Copy {}
        //^^^^
#[derive(Copy)]
//^^^^^^ ^^^^
struct Hello(i32);
     //^^^^^ ^^^
"#,
        );
    }
}
<commit_msg>Auto merge of #13461 - emilio:ide-cleanup-continue, r=Veykril<commit_after>//! This module provides `StaticIndex` which is used for powering
//! read-only code browsers and emitting LSIF

use std::collections::HashMap;

use hir::{db::HirDatabase, Crate, Module, Semantics};
use ide_db::{
    base_db::{FileId, FileRange, SourceDatabaseExt},
    defs::{Definition, IdentClass},
    FxHashSet, RootDatabase,
};
use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T};

use crate::{
    hover::hover_for_definition,
    moniker::{crate_for_file, def_to_moniker, MonikerResult},
    Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
    TryToNav,
};

/// A static representation of fully analyzed source code.
///
/// The intended use-case is powering read-only code browsers and emitting LSIF
#[derive(Debug)]
pub struct StaticIndex<'a> {
    pub files: Vec<StaticIndexedFile>,
    pub tokens: TokenStore,
    analysis: &'a Analysis,
    db: &'a RootDatabase,
    def_map: HashMap<Definition, TokenId>,
}

#[derive(Debug)]
pub struct ReferenceData {
    pub range: FileRange,
    pub is_definition: bool,
}

#[derive(Debug)]
pub struct TokenStaticData {
    pub hover: Option<HoverResult>,
    pub definition: Option<FileRange>,
    pub references: Vec<ReferenceData>,
    pub moniker: Option<MonikerResult>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenId(usize);

impl TokenId {
    pub fn raw(self) -> usize {
        self.0
    }
}

#[derive(Default, Debug)]
pub struct TokenStore(Vec<TokenStaticData>);

impl TokenStore {
    pub fn insert(&mut self, data: TokenStaticData) -> TokenId {
        let id = TokenId(self.0.len());
        self.0.push(data);
        id
    }

    pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData> {
        self.0.get_mut(id.0)
    }

    pub fn get(&self, id: TokenId) -> Option<&TokenStaticData> {
        self.0.get(id.0)
    }

    pub fn iter(self) -> impl Iterator<Item = (TokenId, TokenStaticData)> {
        self.0.into_iter().enumerate().map(|(i, x)| (TokenId(i), x))
    }
}

#[derive(Debug)]
pub struct StaticIndexedFile {
    pub file_id: FileId,
    pub folds: Vec<Fold>,
    pub inlay_hints: Vec<InlayHint>,
    pub tokens: Vec<(TextRange, TokenId)>,
}

fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
    let mut worklist: Vec<_> =
        Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
    let mut modules = Vec::new();

    while let Some(module) = worklist.pop() {
        modules.push(module);
        worklist.extend(module.children(db));
    }

    modules
}

impl StaticIndex<'_> {
    fn add_file(&mut self, file_id: FileId) {
        let current_crate = crate_for_file(self.db, file_id);
        let folds = self.analysis.folding_ranges(file_id).unwrap();
        let inlay_hints = self
            .analysis
            .inlay_hints(
                &InlayHintsConfig {
                    render_colons: true,
                    type_hints: true,
                    parameter_hints: true,
                    chaining_hints: true,
                    closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
                    lifetime_elision_hints: crate::LifetimeElisionHints::Never,
                    reborrow_hints: crate::ReborrowHints::Never,
                    hide_named_constructor_hints: false,
                    hide_closure_initialization_hints: false,
                    param_names_for_lifetime_elision_hints: false,
                    binding_mode_hints: false,
                    max_length: Some(25),
                    closing_brace_hints_min_lines: Some(25),
                },
                file_id,
                None,
            )
            .unwrap();
        // hovers
        let sema = hir::Semantics::new(self.db);
        let tokens_or_nodes = sema.parse(file_id).syntax().clone();
        let tokens = tokens_or_nodes.descendants_with_tokens().filter_map(|x| match x {
            syntax::NodeOrToken::Node(_) => None,
            syntax::NodeOrToken::Token(x) => Some(x),
        });
        let hover_config = HoverConfig {
            links_in_hover: true,
            documentation: Some(HoverDocFormat::Markdown),
            keywords: true,
        };
        let tokens = tokens.filter(|token| {
            matches!(
                token.kind(),
                IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] | T![Self]
            )
        });
        let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] };
        for token in tokens {
            let range = token.text_range();
            let node = token.parent().unwrap();
            let def = match get_definition(&sema, token.clone()) {
                Some(x) => x,
                None => continue,
            };
            let id = if let Some(x) = self.def_map.get(&def) {
                *x
            } else {
                let x = self.tokens.insert(TokenStaticData {
                    hover: hover_for_definition(&sema, file_id, def, &node, &hover_config),
                    definition: def
                        .try_to_nav(self.db)
                        .map(|x| FileRange { file_id: x.file_id, range: x.focus_or_full_range() }),
                    references: vec![],
                    moniker: current_crate.and_then(|cc| def_to_moniker(self.db, def, cc)),
                });
                self.def_map.insert(def, x);
                x
            };
            let token = self.tokens.get_mut(id).unwrap();
            token.references.push(ReferenceData {
                range: FileRange { range, file_id },
                is_definition: match def.try_to_nav(self.db) {
                    Some(x) => x.file_id == file_id && x.focus_or_full_range() == range,
                    None => false,
                },
            });
            result.tokens.push((range, id));
        }
        self.files.push(result);
    }

    pub fn compute(analysis: &Analysis) -> StaticIndex<'_> {
        let db = &*analysis.db;
        let work = all_modules(db).into_iter().filter(|module| {
            let file_id = module.definition_source(db).file_id.original_file(db);
            let source_root = db.file_source_root(file_id);
            let source_root = db.source_root(source_root);
            !source_root.is_library
        });
        let mut this = StaticIndex {
            files: vec![],
            tokens: Default::default(),
            analysis,
            db,
            def_map: Default::default(),
        };
        let mut visited_files = FxHashSet::default();
        for module in work {
            let file_id = module.definition_source(db).file_id.original_file(db);
            if visited_files.contains(&file_id) {
                continue;
            }
            this.add_file(file_id);
            // mark the file
            visited_files.insert(file_id);
        }
        this
    }
}

fn get_definition(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Option<Definition> {
    for token in sema.descend_into_macros(token) {
        let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
        if let Some(&[x]) = def.as_deref() {
            return Some(x);
        }
    }
    None
}

#[cfg(test)]
mod tests {
    use crate::{fixture, StaticIndex};
    use ide_db::base_db::FileRange;
    use std::collections::HashSet;
    use syntax::TextSize;

    fn check_all_ranges(ra_fixture: &str) {
        let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
        let s = StaticIndex::compute(&analysis);
        let mut range_set: HashSet<_> = ranges.iter().map(|x| x.0).collect();
        for f in s.files {
            for (range, _) in f.tokens {
                let x = FileRange { file_id: f.file_id, range };
                if !range_set.contains(&x) {
                    panic!("additional range {:?}", x);
                }
                range_set.remove(&x);
            }
        }
        if !range_set.is_empty() {
            panic!("unfound ranges {:?}", range_set);
        }
    }

    fn check_definitions(ra_fixture: &str) {
        let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
        let s = StaticIndex::compute(&analysis);
        let mut range_set: HashSet<_> = ranges.iter().map(|x| x.0).collect();
        for (_, t) in s.tokens.iter() {
            if let Some(x) = t.definition {
                if x.range.start() == TextSize::from(0) {
                    // ignore definitions that are whole of file
                    continue;
                }
                if !range_set.contains(&x) {
                    panic!("additional definition {:?}", x);
                }
                range_set.remove(&x);
            }
        }
        if !range_set.is_empty() {
            panic!("unfound definitions {:?}", range_set);
        }
    }

    #[test]
    fn struct_and_enum() {
        check_all_ranges(
            r#"
struct Foo;
     //^^^
enum E { X(Foo) }
   //^   ^ ^^^
"#,
        );
        check_definitions(
            r#"
struct Foo;
     //^^^
enum E { X(Foo) }
   //^   ^
"#,
        );
    }

    #[test]
    fn multi_crate() {
        check_definitions(
            r#"
//- /main.rs crate:main deps:foo

use foo::func;

fn main() {
 //^^^^
    func();
}
//- /foo/lib.rs crate:foo

pub func() {

}
"#,
        );
    }

    #[test]
    fn derives() {
        check_all_ranges(
            r#"
//- minicore:derive
#[rustc_builtin_macro]
//^^^^^^^^^^^^^^^^^^^
pub macro Copy {}
        //^^^^
#[derive(Copy)]
//^^^^^^ ^^^^
struct Hello(i32);
     //^^^^^ ^^^
"#,
        );
    }
}
<|endoftext|>


<commit_before>// TODO Disable interrupt before entering those.
use spin::{Mutex};
use core::mem::{size_of};
use utils::{align_down, block_count};
use core::ptr::{Unique};
use super::{PTEntry, PT_P, PT_RW, flush, BASE_PAGE_LENGTH};
use arch::{object_pool_pt, object_pool_pt_mut, OBJECT_POOL_SIZE,
            OBJECT_POOL_START_VADDR};
use common::{PAddr, VAddr};

static _next_free: Mutex<usize> = Mutex::new(0);

fn with_object_unique<T, Return, F: Fn(Unique<T>) -> Return>(paddr: PAddr, f: F) -> Return {
    let size = size_of::<T>();
    let aligned = align_down(paddr, BASE_PAGE_LENGTH);
    let before_start = paddr.as_usize() - aligned.as_usize();
    let required_page_size = block_count((paddr + size).as_usize() - aligned.as_usize(), BASE_PAGE_LENGTH);

    log!("required_page_size: {}", required_page_size);

    let next_free_base;

    {
        let mut next_free = _next_free.lock();
        next_free_base = *next_free;

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::new(aligned + (i * BASE_PAGE_LENGTH), PT_P | PT_RW);
        }

        *next_free = next_free_base + required_page_size;
    }

    let vaddr = OBJECT_POOL_START_VADDR + ((next_free_base * BASE_PAGE_LENGTH) + before_start);
    let unique = unsafe { Unique::new(vaddr.as_usize() as *mut T) };

    let result = f(unique);

    {
        let mut next_free = _next_free.lock();
        assert!(next_free_base == (*next_free - required_page_size));

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::empty();
        }

        *next_free = next_free_base;
    }

    result
}

pub fn with_object<T, Return, F: Fn(&T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |unique| {
        f(unsafe { unique.get() })
    })
}

pub fn with_object_mut<T, Return, F: Fn(&mut T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |mut unique| {
        f(unsafe { unique.get_mut() })
    })
}
<commit_msg>Flush after change<commit_after>// TODO Disable interrupt before entering those.
use spin::{Mutex};
use core::mem::{size_of};
use utils::{align_down, block_count};
use core::ptr::{Unique};
use super::{PTEntry, PT_P, PT_RW, flush, BASE_PAGE_LENGTH};
use arch::{object_pool_pt, object_pool_pt_mut, OBJECT_POOL_SIZE,
           OBJECT_POOL_START_VADDR};
use common::{PAddr, VAddr};

static _next_free: Mutex<usize> = Mutex::new(0);

fn with_object_unique<T, Return, F: Fn(Unique<T>) -> Return>(paddr: PAddr, f: F) -> Return {
    let size = size_of::<T>();
    let aligned = align_down(paddr, BASE_PAGE_LENGTH);
    let before_start = paddr.as_usize() - aligned.as_usize();
    let required_page_size = block_count((paddr + size).as_usize() - aligned.as_usize(), BASE_PAGE_LENGTH);

    log!("required_page_size: {}", required_page_size);

    let next_free_base;

    {
        let mut next_free = _next_free.lock();
        next_free_base = *next_free;

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::new(aligned + (i * BASE_PAGE_LENGTH), PT_P | PT_RW);
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base + required_page_size;
    }

    let vaddr = OBJECT_POOL_START_VADDR + ((next_free_base * BASE_PAGE_LENGTH) + before_start);
    let unique = unsafe { Unique::new(vaddr.as_usize() as *mut T) };

    let result = f(unique);

    {
        let mut next_free = _next_free.lock();
        assert!(next_free_base == (*next_free - required_page_size));

        for i in 0..required_page_size {
            object_pool_pt_mut()[next_free_base + i] = PTEntry::empty();
            unsafe { flush(OBJECT_POOL_START_VADDR + (next_free_base * BASE_PAGE_LENGTH) + i * BASE_PAGE_LENGTH); }
        }

        *next_free = next_free_base;
    }

    result
}

pub fn with_object<T, Return, F: Fn(&T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |unique| {
        f(unsafe { unique.get() })
    })
}

pub fn with_object_mut<T, Return, F: Fn(&mut T) -> Return>(paddr: PAddr, f: F) -> Return {
    with_object_unique(paddr, |mut unique| {
        f(unsafe { unique.get_mut() })
    })
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate native;

fn main() {
    sdl2::init(sdl2::InitVideo);

    let window = match sdl2::video::Window::new("rust-sdl2 demo: Video", sdl2::video::PosCentered, sdl2::video::PosCentered, 800, 600, sdl2::video::OpenGL) {
        Ok(window) => window,
        Err(err) => fail!(format!("failed to create window: {}", err))
    };

    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::DriverAuto, sdl2::render::Accelerated) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("failed to create renderer: {}", err))
    };

    let _ = renderer.set_draw_color(sdl2::pixels::RGB(255, 0, 0));
    let _ = renderer.clear();
    renderer.present();

    'main : loop {
        'event : loop {
            match sdl2::event::poll_event() {
                sdl2::event::QuitEvent(_) => break 'main,
                sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                    if key == sdl2::keycode::EscapeKey {
                        break 'main
                    }
                },
                sdl2::event::NoEvent => break 'event,
                _ => {}
            }
        }
    }

    sdl2::quit();
}
<commit_msg>Now doing the same as the other samples<commit_after>extern crate sdl2;
extern crate native;

fn main() {
    sdl2::init(sdl2::InitEverything);

    let win = match sdl2::video::Window::new("Hello World!", sdl2::video::Positioned(100), sdl2::video::Positioned(100), 960, 540, sdl2::video::Shown) {
        Ok(window) => window,
        Err(err) => fail!(format!("SDL_CreateWindow Error: {}", err))
    };

    let ren = match sdl2::render::Renderer::from_window(win, sdl2::render::DriverAuto, sdl2::render::Accelerated) {
        Ok(renderer) => renderer,
        Err(err) => fail!(format!("SDL_CreateRenderer Error: {}", err))
    };

    let bmp = match sdl2::surface::Surface::from_bmp(&Path::new("../img/boxes.bmp")) {
    	Ok(bmp) => bmp,
	Err(err) => fail!(format!("SDL_LoadBMP Error: {}", err))
    };

    let tex = match ren.create_texture_from_surface(&bmp) {
    	Ok(tex) => tex,
	Err(err) => fail!(format!("SDL_CreateTextureFromSurface Error: {}", err))
    };

    let _ = ren.clear();
    let _ = ren.copy(&tex, None, None);
    ren.present();

    sdl2::timer::delay(2000);

    sdl2::quit();
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ops::Index;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub type ColumnId = usize;

#[derive(Clone, PartialEq, Debug)]
pub struct Constraint {
  pub nullable: bool,
  pub unique: bool,
  pub sorted: bool
}

pub struct Identifier {
  pub name: String,
  pub quoted: bool
}

impl Identifier {

  pub fn new<T: AsRef<str>>(name: T) -> Identifier {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: false
    }
  }

  pub fn new_quoted<T: AsRef<str>>(name: T, quoted: bool) -> Identifier {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: quoted
    }
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Field {
  pub name: String,
  pub decl: FieldDecl,
  pub cstr: Option<Constraint>
}

impl Field {

  pub fn new<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field {
    Field {
      name: name.as_ref().to_string(),
      decl: decl,
      cstr: None,
    }
  }

  pub fn scalar<T: AsRef<str>>(name: T, ty: Ty) -> Field {
    Field::new(name, FieldDecl::Scalar(ty))
  }

  pub fn array<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field {
    Field::new(name, FieldDecl::Array(Box::new(decl)))
  }

  pub fn map<T: AsRef<str>>(name: T, key_ty: FieldDecl, val_ty: FieldDecl) -> Field {
    Field::new(name, FieldDecl::Map(Box::new(key_ty), Box::new(val_ty)))
  }

  pub fn record<T: AsRef<str>>(name: T, r: Record) -> Field {
    Field::new(name, FieldDecl::Record(r))
  }

  pub fn record_from_vec<T: AsRef<str>>(name: T, fields: Vec<Field>) -> Field {
    Field::new(name, FieldDecl::Record(Record::new(fields)))
  }

  #[inline]
  pub fn name(&self) -> &str {
    &self.name
  }
}

impl fmt::Display for Field {

  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", display_field(self))
  }
}

#[inline]
fn display_field(f: &Field) -> String {
  format!("{} {}", f.name, f.decl)
}

#[inline]
fn display_fields(fields: &Vec<Field>) -> String {
  fields.iter().map(|f| display_field(f)).join(", ")
}

#[derive(Clone, PartialEq, Debug)]
pub enum FieldDecl {
  Scalar (Ty),
  Record (Record),
  Array  (Box<FieldDecl>),
  Map    (Box<FieldDecl>, Box<FieldDecl>)
}

impl FieldDecl {

  pub fn scalar(ty: Ty) -> FieldDecl {
    FieldDecl::Scalar(ty)
  }

  pub fn record_from_vec(fields: Vec<Field>) -> FieldDecl {
    FieldDecl::Record(Record::new(fields))
  }
}

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

fn display_field_decl(decl: &FieldDecl) -> String {
  match *decl {
    FieldDecl::Scalar(ref ty)         => ty.name().to_owned(),
    FieldDecl::Record(ref r)          => format!("record ({})", r),
    FieldDecl::Array (ref vt)         => format!("array<{}>", vt),
    FieldDecl::Map   (ref kt, ref vt) => format!("map<{},{}>", kt, vt)
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Record {
  fields: Vec<Field>
}

impl Record {
  pub fn new(fields: Vec<Field>) -> Record {
    Record {fields: fields}
  }

  pub fn size(&self) -> usize {
    self.fields.len()
  }

  pub fn find_id(&self, name: &str) -> Option<ColumnId> {
    self.fields.iter().position(|f| f.name == name)
  }

  pub fn find_by_name(&self, name : &str) -> Option<&Field> {
    self.fields.iter().filter(|&f| f.name == name).next()
  }

  pub fn iter(&self) -> Iter<Field> {
    self.fields.iter()
  }
}

impl Index<ColumnId> for Record {
  type Output = Field;
  fn index<'a>(&'a self, id: ColumnId) -> &'a Field {
    debug_assert!(id < self.fields.len(), "Field index is out of range");
    &self.fields[id]
  }
}

impl fmt::Display for Record {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", display_fields(&self.fields))
  }
}

#[allow(dead_code)]
fn create_test_schema() -> Record {
	Record::new(vec![
    Field::scalar("col1", *INT4_TY),
    Field::record_from_vec("col2", vec![
        Field::scalar("col3", *INT4_TY),
        Field::scalar("col4", *INT4_TY)
      ]
    ),
    Field::record_from_vec("col5", vec![
        Field::array("col6", FieldDecl::scalar(*INT8_TY)),
        Field::array("col7", FieldDecl::scalar(*INT8_TY)),
      ]
    ),
    Field::map("col8", FieldDecl::scalar(*INT4_TY), FieldDecl::record_from_vec(
      vec![
        Field::scalar("col9",  *TEXT_TY),
        Field::scalar("col10", *TEXT_TY),
      ])
    )
  ])
}

#[test]
fn test_schema_creation() {
  let schema = create_test_schema();
  assert_eq!(vec![
    "col1 int4, col2 record (col3 int4, col4 int4), col5 record (col6 array<int8>, ",
    "col7 array<int8>), col8 map<int4,record (col9 text, col10 text)>"
    ].concat(), format!("{}", schema));
}
<commit_msg>Changed coding converntion.<commit_after>use std::fmt;
use std::ops::Index;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub type ColumnId = usize;

#[derive(Clone, PartialEq, Debug)]
pub struct Constraint
{
  pub nullable: bool,
  pub unique: bool,
  pub sorted: bool
}

pub struct Identifier
{
  pub name: String,
  pub quoted: bool
}

impl Identifier
{
  pub fn new<T: AsRef<str>>(name: T) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: false
    }
  }

  pub fn new_quoted<T: AsRef<str>>(name: T, quoted: bool) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: quoted
    }
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Field
{
  pub name: String,
  pub decl: FieldDecl,
  pub cstr: Option<Constraint>
}

impl Field
{
  pub fn new<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field
  {
    Field {
      name: name.as_ref().to_string(),
      decl: decl,
      cstr: None,
    }
  }

  pub fn scalar<T: AsRef<str>>(name: T, ty: Ty) -> Field
  {
    Field::new(name, FieldDecl::Scalar(ty))
  }

  pub fn array<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Array(Box::new(decl)))
  }

  pub fn map<T: AsRef<str>>(name: T, key_ty: FieldDecl, val_ty: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Map(Box::new(key_ty), Box::new(val_ty)))
  }

  pub fn record<T: AsRef<str>>(name: T, r: Record) -> Field
  {
    Field::new(name, FieldDecl::Record(r))
  }

  pub fn record_from_vec<T: AsRef<str>>(name: T, fields: Vec<Field>) -> Field
  {
    Field::new(name, FieldDecl::Record(Record::new(fields)))
  }

  #[inline]
  pub fn name(&self) -> &str { &self.name }
}

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

#[inline]
fn display_field(f: &Field) -> String { format!("{} {}", f.name, f.decl) }

#[inline]
fn display_fields(fields: &Vec<Field>) -> String
{
  fields.iter().map(|f| display_field(f)).join(", ")
}

#[derive(Clone, PartialEq, Debug)]
pub enum FieldDecl
{
  Scalar (Ty),
  Record (Record),
  Array  (Box<FieldDecl>),
  Map    (Box<FieldDecl>, Box<FieldDecl>)
}

impl FieldDecl
{
  pub fn scalar(ty: Ty) -> FieldDecl { FieldDecl::Scalar(ty) }

  pub fn record_from_vec(fields: Vec<Field>) -> FieldDecl
  {
    FieldDecl::Record(Record::new(fields))
  }
}

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

fn display_field_decl(decl: &FieldDecl) -> String
{
  match *decl {
    FieldDecl::Scalar(ref ty)         => ty.name().to_owned(),
    FieldDecl::Record(ref r)          => format!("record ({})", r),
    FieldDecl::Array (ref vt)         => format!("array<{}>", vt),
    FieldDecl::Map   (ref kt, ref vt) => format!("map<{},{}>", kt, vt)
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Record { fields: Vec<Field> }

impl Record
{
  pub fn new(fields: Vec<Field>) -> Record { Record {fields: fields} }

  pub fn size(&self) -> usize { self.fields.len() }

  pub fn find_id(&self, name: &str) -> Option<ColumnId>
  {
    self.fields.iter().position(|f| f.name == name)
  }

  pub fn find_by_name(&self, name : &str) -> Option<&Field>
  {
    self.fields.iter().filter(|&f| f.name == name).next()
  }

  pub fn iter(&self) -> Iter<Field>
  {
    self.fields.iter()
  }
}

impl Index<ColumnId> for Record
{
  type Output = Field;
  fn index<'a>(&'a self, id: ColumnId) -> &'a Field
  {
    debug_assert!(id < self.fields.len(), "Field index is out of range");
    &self.fields[id]
  }
}

impl fmt::Display for Record
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_fields(&self.fields))
  }
}

#[allow(dead_code)]
fn create_test_schema() -> Record
{
	Record::new(vec![
    Field::scalar("col1", *INT4_TY),
    Field::record_from_vec("col2", vec![
        Field::scalar("col3", *INT4_TY),
        Field::scalar("col4", *INT4_TY)
      ]
    ),
    Field::record_from_vec("col5", vec![
        Field::array("col6", FieldDecl::scalar(*INT8_TY)),
        Field::array("col7", FieldDecl::scalar(*INT8_TY)),
      ]
    ),
    Field::map("col8", FieldDecl::scalar(*INT4_TY), FieldDecl::record_from_vec(
      vec![
        Field::scalar("col9",  *TEXT_TY),
        Field::scalar("col10", *TEXT_TY),
      ])
    )
  ])
}

#[test]
fn test_schema_creation()
{
  let schema = create_test_schema();
  assert_eq!(vec![
    "col1 int4, col2 record (col3 int4, col4 int4), col5 record (col6 array<int8>, ",
    "col7 array<int8>), col8 map<int4,record (col9 text, col10 text)>"
    ].concat(), format!("{}", schema));
}
<|endoftext|>


<commit_before><commit_msg>Fix lsn inequality on segment freeing<commit_after><|endoftext|>


<commit_before>fn main() {
    let mut tot: u32 = 0;
    for i in 3..1000 {
        if (i % 3 == 0) || (i % 5 == 0) {
            tot += i;
        }
    }
    let s: String = tot.to_string();
    println!("{}", s);
}
<commit_msg>removed unnecessary line in 001<commit_after>fn main() {
    let mut tot: u32 = 0;
    for i in 3..1000 {
        if (i % 3 == 0) || (i % 5 == 0) {
            tot += i;
        }
    }
    println!("{}", tot);
}
<|endoftext|>


<commit_before>use std::fmt;

use util::{CargoResult, Dirty, Fresh, Freshness};
use super::job_queue::JobState;

pub struct Job {
    dirty: Work,
    fresh: Work,
}

/// Each proc should send its description before starting.
/// It should send either once or close immediately.
pub struct Work {
    inner: Box<for<'a, 'b> FnBox<&'a JobState<'b>, CargoResult<()>> + Send>,
}

trait FnBox<A, R> {
    fn call_box(self: Box<Self>, a: A) -> R;
}

impl<A, R, F: FnOnce(A) -> R> FnBox<A, R> for F {
    #[cfg_attr(feature = "cargo-clippy", allow(boxed_local))] // The use of Box is intentional here
    fn call_box(self: Box<F>, a: A) -> R {
        (*self)(a)
    }
}

impl Work {
    pub fn new<F>(f: F) -> Work
    where
        F: FnOnce(&JobState) -> CargoResult<()> + Send + 'static,
    {
        Work { inner: Box::new(f) }
    }

    pub fn noop() -> Work {
        Work::new(|_| Ok(()))
    }

    pub fn call(self, tx: &JobState) -> CargoResult<()> {
        self.inner.call_box(tx)
    }

    pub fn then(self, next: Work) -> Work {
        Work::new(move |state| {
            self.call(state)?;
            next.call(state)
        })
    }
}

impl Job {
    /// Create a new job representing a unit of work.
    pub fn new(dirty: Work, fresh: Work) -> Job {
        Job { dirty, fresh }
    }

    /// Consumes this job by running it, returning the result of the
    /// computation.
    pub fn run(self, fresh: Freshness, state: &JobState) -> CargoResult<()> {
        match fresh {
            Fresh => self.fresh.call(state),
            Dirty => self.dirty.call(state),
        }
    }
}

impl fmt::Debug for Job {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Job {{ ... }}")
    }
}
<commit_msg>Add a link to the Clippy's false positive bug around boxed_local<commit_after>use std::fmt;

use util::{CargoResult, Dirty, Fresh, Freshness};
use super::job_queue::JobState;

pub struct Job {
    dirty: Work,
    fresh: Work,
}

/// Each proc should send its description before starting.
/// It should send either once or close immediately.
pub struct Work {
    inner: Box<for<'a, 'b> FnBox<&'a JobState<'b>, CargoResult<()>> + Send>,
}

trait FnBox<A, R> {
    fn call_box(self: Box<Self>, a: A) -> R;
}

impl<A, R, F: FnOnce(A) -> R> FnBox<A, R> for F {
    // False positive: https://github.com/rust-lang-nursery/rust-clippy/issues/1123
    #[cfg_attr(feature = "cargo-clippy", allow(boxed_local))]
    fn call_box(self: Box<F>, a: A) -> R {
        (*self)(a)
    }
}

impl Work {
    pub fn new<F>(f: F) -> Work
    where
        F: FnOnce(&JobState) -> CargoResult<()> + Send + 'static,
    {
        Work { inner: Box::new(f) }
    }

    pub fn noop() -> Work {
        Work::new(|_| Ok(()))
    }

    pub fn call(self, tx: &JobState) -> CargoResult<()> {
        self.inner.call_box(tx)
    }

    pub fn then(self, next: Work) -> Work {
        Work::new(move |state| {
            self.call(state)?;
            next.call(state)
        })
    }
}

impl Job {
    /// Create a new job representing a unit of work.
    pub fn new(dirty: Work, fresh: Work) -> Job {
        Job { dirty, fresh }
    }

    /// Consumes this job by running it, returning the result of the
    /// computation.
    pub fn run(self, fresh: Freshness, state: &JobState) -> CargoResult<()> {
        match fresh {
            Fresh => self.fresh.call(state),
            Dirty => self.dirty.call(state),
        }
    }
}

impl fmt::Debug for Job {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Job {{ ... }}")
    }
}
<|endoftext|>


<commit_before><commit_msg>Add ClipboardFormats and GlobalAllocFlags, add full set of clipboard formats and GlobalAlloc flags, and use them<commit_after><|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync)

use std::{collections::BTreeMap, time::Duration};

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_events::{
    collections::{
        all::{RoomEvent, StateEvent},
        only::Event as NonRoomEvent,
    },
    presence::PresenceEvent,
    stripped::AnyStrippedStateEvent,
    to_device::AnyToDeviceEvent,
    EventJson,
};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

use crate::r0::{filter::FilterDefinition, keys::KeyAlgorithm};

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,

        /// A point in time to continue a sync from.
        ///
        /// Should be a token from the `next_batch` field of a previous `/sync`
        /// request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,

        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        #[ruma_api(query)]
        pub full_state: bool,

        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        #[ruma_api(query)]
        pub set_presence: SetPresence,

        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(
            with = "ruma_serde::duration::opt_ms",
            default,
            skip_serializing_if = "Option::is_none",
        )]
        #[ruma_api(query)]
        pub timeout: Option<Duration>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,

        /// Updates to rooms.
        #[serde(default, skip_serializing_if = "Rooms::is_empty")]
        pub rooms: Rooms,

        /// Updates to the presence status of other users.
        #[serde(default, skip_serializing_if = "Presence::is_empty")]
        pub presence: Presence,

        /// The global private data created by this user.
        #[serde(default, skip_serializing_if = "AccountData::is_empty")]
        pub account_data: AccountData,

        /// Messages sent dirrectly between devices.
        #[serde(default, skip_serializing_if = "ToDevice::is_empty")]
        pub to_device: ToDevice,

        /// Information on E2E device updates.
        ///
        /// Only present on an incremental sync.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub device_lists: Option<DeviceLists>,

        /// For each key algorithm, the number of unclaimed one-time keys
        /// currently held on the server for a device.
        #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
        pub device_one_time_keys_count: BTreeMap<KeyAlgorithm, UInt>,
    }

    error: crate::Error
}

/// Whether to set presence or not during sync.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    Offline,

    /// Mark client as online explicitly. Assumed by default.
    Online,

    /// Mark client as being idle.
    Unavailable,
}

impl Default for SetPresence {
    fn default() -> Self {
        Self::Online
    }
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(untagged)]
pub enum Filter {
    // The filter definition needs to be (de)serialized twice because it is a URL-encoded JSON
    // string. Since #[ruma_api(query)] only does the latter and this is a very uncommon
    // setup, we implement it through custom serde logic for this specific enum variant rather than
    // adding another ruma_api attribute.
    //
    // On the deserialization side, because this is an enum with #[serde(untagged)], serde will
    // try the variants in order (https://serde.rs/enum-representations.html). That means because
    // FilterDefinition is the first variant, JSON decoding is attempted first which is almost
    // functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
    // (there are probably some corner cases like leading whitespace)
    #[serde(with = "ruma_serde::json_string")]
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),

    /// The ID of a filter saved on the server.
    FilterId(String),
}

/// Updates to rooms.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    pub leave: BTreeMap<RoomId, LeftRoom>,

    /// The rooms that the user has joined.
    pub join: BTreeMap<RoomId, JoinedRoom>,

    /// The rooms that the user has been invited to.
    pub invite: BTreeMap<RoomId, InvitedRoom>,
}

impl Rooms {
    fn is_empty(&self) -> bool {
        self.leave.is_empty() && self.join.is_empty() && self.invite.is_empty()
    }
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    pub timeline: Timeline,

    /// The state updates for the room up to the start of the timeline.
    pub state: State,

    /// The private data that this user has attached to this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub account_data: Option<AccountData>,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JoinedRoom {
    /// Information about the room which clients may need to correctly render it
    /// to users.
    pub summary: RoomSummary,

    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,

    /// The timeline of messages and state changes in the room.
    pub timeline: Timeline,

    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    pub state: State,

    /// The private data that this user has attached to this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub account_data: Option<AccountData>,

    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<UInt>,

    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<UInt>,
}

/// Events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limited: Option<bool>,

    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prev_batch: Option<String>,

    /// A list of events.
    pub events: Vec<EventJson<RoomEvent>>,
}

/// State events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct State {
    /// A list of state events.
    pub events: Vec<EventJson<StateEvent>>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccountData {
    /// A list of events.
    pub events: Vec<EventJson<NonRoomEvent>>,
}

impl AccountData {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ephemeral {
    /// A list of events.
    pub events: Vec<EventJson<NonRoomEvent>>,
}

/// Information about room for rendering to clients.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RoomSummary {
    /// Users which can be used to generate a room name if the room does not have
    /// one. Required if room name or canonical aliases are not set or empty.
    #[serde(rename = "m.heroes", default, skip_serializing_if = "Vec::is_empty")]
    pub heroes: Vec<String>,

    /// Number of users whose membership status is `join`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(
        rename = "m.joined_member_count",
        skip_serializing_if = "Option::is_none"
    )]
    pub joined_member_count: Option<UInt>,

    /// Number of users whose membership status is `invite`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(
        rename = "m.invited_member_count",
        skip_serializing_if = "Option::is_none"
    )]
    pub invited_member_count: Option<UInt>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteState {
    /// A list of state events.
    pub events: Vec<EventJson<AnyStrippedStateEvent>>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Presence {
    /// A list of events.
    pub events: Vec<EventJson<PresenceEvent>>,
}

impl Presence {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Messages sent dirrectly between devices.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ToDevice {
    /// A list of to-device events.
    pub events: Vec<EventJson<AnyToDeviceEvent>>,
}

impl ToDevice {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Information on E2E device udpates.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceLists {
    /// List of users who have updated their device identity keys or who now
    /// share an encrypted room with the client since the previous sync
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub changed: Vec<String>,

    /// List of users who no longer share encrypted rooms since the previous sync
    /// response.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub left: Vec<String>,
}

#[cfg(test)]
mod tests {
    use std::{convert::TryInto, time::Duration};

    use matches::assert_matches;

    use super::{Filter, Request, SetPresence};

    #[test]
    fn serialize_all_params() {
        let req: http::Request<Vec<u8>> = Request {
            filter: Some(Filter::FilterId("66696p746572".into())),
            since: Some("s72594_4483_1934".into()),
            full_state: true,
            set_presence: SetPresence::Offline,
            timeout: Some(Duration::from_millis(30000)),
        }
        .try_into()
        .unwrap();

        let uri = req.uri();
        let query = uri.query().unwrap();

        assert_eq!(uri.path(), "/_matrix/client/r0/sync");
        assert!(query.contains("filter=66696p746572"));
        assert!(query.contains("since=s72594_4483_1934"));
        assert!(query.contains("full_state=true"));
        assert!(query.contains("set_presence=offline"));
        assert!(query.contains("timeout=30000"))
    }

    #[test]
    fn deserialize_all_query_params() {
        let uri = http::Uri::builder()
            .scheme("https")
            .authority("matrix.org")
            .path_and_query(
                "/_matrix/client/r0/sync\
                 ?filter=myfilter\
                 &since=myts\
                 &full_state=false\
                 &set_presence=offline\
                 &timeout=5000",
            )
            .build()
            .unwrap();

        let req: Request = http::Request::builder()
            .uri(uri)
            .body(Vec::<u8>::new())
            .unwrap()
            .try_into()
            .unwrap();

        assert_matches!(req.filter, Some(Filter::FilterId(id)) if id == "myfilter");
        assert_eq!(req.since, Some("myts".into()));
        assert_eq!(req.full_state, false);
        assert_eq!(req.set_presence, SetPresence::Offline);
        assert_eq!(req.timeout, Some(Duration::from_millis(5000)));
    }

    #[test]
    fn deserialize_no_query_params() {
        let uri = http::Uri::builder()
            .scheme("https")
            .authority("matrix.org")
            .path_and_query("/_matrix/client/r0/sync")
            .build()
            .unwrap();

        let req: Request = http::Request::builder()
            .uri(uri)
            .body(Vec::<u8>::new())
            .unwrap()
            .try_into()
            .unwrap();

        assert_matches!(req.filter, None);
        assert_eq!(req.since, None);
        assert_eq!(req.full_state, false);
        assert_eq!(req.set_presence, SetPresence::Online);
        assert_eq!(req.timeout, None);
    }
}
<commit_msg>Add another test for sync_events request deserialization<commit_after>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync)

use std::{collections::BTreeMap, time::Duration};

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_events::{
    collections::{
        all::{RoomEvent, StateEvent},
        only::Event as NonRoomEvent,
    },
    presence::PresenceEvent,
    stripped::AnyStrippedStateEvent,
    to_device::AnyToDeviceEvent,
    EventJson,
};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

use crate::r0::{filter::FilterDefinition, keys::KeyAlgorithm};

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,

        /// A point in time to continue a sync from.
        ///
        /// Should be a token from the `next_batch` field of a previous `/sync`
        /// request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,

        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        #[ruma_api(query)]
        pub full_state: bool,

        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        #[ruma_api(query)]
        pub set_presence: SetPresence,

        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(
            with = "ruma_serde::duration::opt_ms",
            default,
            skip_serializing_if = "Option::is_none",
        )]
        #[ruma_api(query)]
        pub timeout: Option<Duration>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,

        /// Updates to rooms.
        #[serde(default, skip_serializing_if = "Rooms::is_empty")]
        pub rooms: Rooms,

        /// Updates to the presence status of other users.
        #[serde(default, skip_serializing_if = "Presence::is_empty")]
        pub presence: Presence,

        /// The global private data created by this user.
        #[serde(default, skip_serializing_if = "AccountData::is_empty")]
        pub account_data: AccountData,

        /// Messages sent dirrectly between devices.
        #[serde(default, skip_serializing_if = "ToDevice::is_empty")]
        pub to_device: ToDevice,

        /// Information on E2E device updates.
        ///
        /// Only present on an incremental sync.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub device_lists: Option<DeviceLists>,

        /// For each key algorithm, the number of unclaimed one-time keys
        /// currently held on the server for a device.
        #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
        pub device_one_time_keys_count: BTreeMap<KeyAlgorithm, UInt>,
    }

    error: crate::Error
}

/// Whether to set presence or not during sync.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    Offline,

    /// Mark client as online explicitly. Assumed by default.
    Online,

    /// Mark client as being idle.
    Unavailable,
}

impl Default for SetPresence {
    fn default() -> Self {
        Self::Online
    }
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(untagged)]
pub enum Filter {
    // The filter definition needs to be (de)serialized twice because it is a URL-encoded JSON
    // string. Since #[ruma_api(query)] only does the latter and this is a very uncommon
    // setup, we implement it through custom serde logic for this specific enum variant rather than
    // adding another ruma_api attribute.
    //
    // On the deserialization side, because this is an enum with #[serde(untagged)], serde will
    // try the variants in order (https://serde.rs/enum-representations.html). That means because
    // FilterDefinition is the first variant, JSON decoding is attempted first which is almost
    // functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
    // (there are probably some corner cases like leading whitespace)
    #[serde(with = "ruma_serde::json_string")]
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),

    /// The ID of a filter saved on the server.
    FilterId(String),
}

/// Updates to rooms.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    pub leave: BTreeMap<RoomId, LeftRoom>,

    /// The rooms that the user has joined.
    pub join: BTreeMap<RoomId, JoinedRoom>,

    /// The rooms that the user has been invited to.
    pub invite: BTreeMap<RoomId, InvitedRoom>,
}

impl Rooms {
    fn is_empty(&self) -> bool {
        self.leave.is_empty() && self.join.is_empty() && self.invite.is_empty()
    }
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    pub timeline: Timeline,

    /// The state updates for the room up to the start of the timeline.
    pub state: State,

    /// The private data that this user has attached to this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub account_data: Option<AccountData>,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JoinedRoom {
    /// Information about the room which clients may need to correctly render it
    /// to users.
    pub summary: RoomSummary,

    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,

    /// The timeline of messages and state changes in the room.
    pub timeline: Timeline,

    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    pub state: State,

    /// The private data that this user has attached to this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub account_data: Option<AccountData>,

    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<UInt>,

    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<UInt>,
}

/// Events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limited: Option<bool>,

    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prev_batch: Option<String>,

    /// A list of events.
    pub events: Vec<EventJson<RoomEvent>>,
}

/// State events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct State {
    /// A list of state events.
    pub events: Vec<EventJson<StateEvent>>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct AccountData {
    /// A list of events.
    pub events: Vec<EventJson<NonRoomEvent>>,
}

impl AccountData {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ephemeral {
    /// A list of events.
    pub events: Vec<EventJson<NonRoomEvent>>,
}

/// Information about room for rendering to clients.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RoomSummary {
    /// Users which can be used to generate a room name if the room does not have
    /// one. Required if room name or canonical aliases are not set or empty.
    #[serde(rename = "m.heroes", default, skip_serializing_if = "Vec::is_empty")]
    pub heroes: Vec<String>,

    /// Number of users whose membership status is `join`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(
        rename = "m.joined_member_count",
        skip_serializing_if = "Option::is_none"
    )]
    pub joined_member_count: Option<UInt>,

    /// Number of users whose membership status is `invite`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(
        rename = "m.invited_member_count",
        skip_serializing_if = "Option::is_none"
    )]
    pub invited_member_count: Option<UInt>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteState {
    /// A list of state events.
    pub events: Vec<EventJson<AnyStrippedStateEvent>>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Presence {
    /// A list of events.
    pub events: Vec<EventJson<PresenceEvent>>,
}

impl Presence {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Messages sent dirrectly between devices.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ToDevice {
    /// A list of to-device events.
    pub events: Vec<EventJson<AnyToDeviceEvent>>,
}

impl ToDevice {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

/// Information on E2E device udpates.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceLists {
    /// List of users who have updated their device identity keys or who now
    /// share an encrypted room with the client since the previous sync
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub changed: Vec<String>,

    /// List of users who no longer share encrypted rooms since the previous sync
    /// response.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub left: Vec<String>,
}

#[cfg(test)]
mod tests {
    use std::{convert::TryInto, time::Duration};

    use matches::assert_matches;

    use super::{Filter, Request, SetPresence};

    #[test]
    fn serialize_all_params() {
        let req: http::Request<Vec<u8>> = Request {
            filter: Some(Filter::FilterId("66696p746572".into())),
            since: Some("s72594_4483_1934".into()),
            full_state: true,
            set_presence: SetPresence::Offline,
            timeout: Some(Duration::from_millis(30000)),
        }
        .try_into()
        .unwrap();

        let uri = req.uri();
        let query = uri.query().unwrap();

        assert_eq!(uri.path(), "/_matrix/client/r0/sync");
        assert!(query.contains("filter=66696p746572"));
        assert!(query.contains("since=s72594_4483_1934"));
        assert!(query.contains("full_state=true"));
        assert!(query.contains("set_presence=offline"));
        assert!(query.contains("timeout=30000"))
    }

    #[test]
    fn deserialize_all_query_params() {
        let uri = http::Uri::builder()
            .scheme("https")
            .authority("matrix.org")
            .path_and_query(
                "/_matrix/client/r0/sync\
                 ?filter=myfilter\
                 &since=myts\
                 &full_state=false\
                 &set_presence=offline\
                 &timeout=5000",
            )
            .build()
            .unwrap();

        let req: Request = http::Request::builder()
            .uri(uri)
            .body(Vec::<u8>::new())
            .unwrap()
            .try_into()
            .unwrap();

        assert_matches!(req.filter, Some(Filter::FilterId(id)) if id == "myfilter");
        assert_eq!(req.since, Some("myts".into()));
        assert_eq!(req.full_state, false);
        assert_eq!(req.set_presence, SetPresence::Offline);
        assert_eq!(req.timeout, Some(Duration::from_millis(5000)));
    }

    #[test]
    fn deserialize_no_query_params() {
        let uri = http::Uri::builder()
            .scheme("https")
            .authority("matrix.org")
            .path_and_query("/_matrix/client/r0/sync")
            .build()
            .unwrap();

        let req: Request = http::Request::builder()
            .uri(uri)
            .body(Vec::<u8>::new())
            .unwrap()
            .try_into()
            .unwrap();

        assert_matches!(req.filter, None);
        assert_eq!(req.since, None);
        assert_eq!(req.full_state, false);
        assert_eq!(req.set_presence, SetPresence::Online);
        assert_eq!(req.timeout, None);
    }

    #[test]
    fn deserialize_some_query_params() {
        let uri = http::Uri::builder()
            .scheme("https")
            .authority("matrix.org")
            .path_and_query(
                "/_matrix/client/r0/sync\
                 ?filter=EOKFFmdZYF\
                 &timeout=0",
            )
            .build()
            .unwrap();

        let req: Request = http::Request::builder()
            .uri(uri)
            .body(Vec::<u8>::new())
            .unwrap()
            .try_into()
            .unwrap();

        assert_matches!(req.filter, Some(Filter::FilterId(id)) if id == "EOKFFmdZYF");
        assert_eq!(req.since, None);
        assert_eq!(req.full_state, false);
        assert_eq!(req.set_presence, SetPresence::Online);
        assert_eq!(req.timeout, Some(Duration::from_millis(0)));
    }
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, colpos: usize, coltype: &types::Type) -> String {
    let val: String = match *coltype {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>, is_header: bool) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        match is_header {
            false   => print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i]))),
            true    => print!(" {} ", color_text(&format_field(&col, colwidths[i], Align::Center), Color::BoldWhite)),
        };
    }

    println!("");

    match is_header {
        false   => {},
        true    => {
            for (i, col) in colwidths.iter().enumerate() {
                if i > 0 {
                    print!("{}", color_text("|", Color::BoldWhite));
                }

                print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
            }

            println!("");
        },
    };

}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();
    let mut args = std::env::args();

    if args.len() == 1 {
        println!("{} {}", color_text("error:", Color::BoldRed), color_text("a DBURI is required!", Color::BoldWhite));
        println!("{} cat file.sql | first [DBURI]", color_text("usage:", Color::BoldBlue));
        std::process::exit(1);
    }

    let connstr: String = args.nth(1).unwrap();
    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect(&connstr as &str, SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = match ret.is_some() {
                true    => parse_result(&row, i, &coltypes[i]),
                false   => String::from(""),
            };

            colwidths[i] = match col.len() > colwidths[i] {
                true    => col.len(),
                false   => colwidths[i]
            };

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_row(&Vec::new(), &colwidths, &colnames, true);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata, false);
    }
}
<commit_msg>was using the wrong separator<commit_after>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, colpos: usize, coltype: &types::Type) -> String {
    let val: String = match *coltype {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>, is_header: bool) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        match is_header {
            false   => print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i]))),
            true    => print!(" {} ", color_text(&format_field(&col, colwidths[i], Align::Center), Color::BoldWhite)),
        };
    }

    println!("");

    match is_header {
        false   => {},
        true    => {
            for (i, col) in colwidths.iter().enumerate() {
                if i > 0 {
                    print!("{}", color_text("+", Color::BoldWhite));
                }

                print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
            }

            println!("");
        },
    };

}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();
    let mut args = std::env::args();

    if args.len() == 1 {
        println!("{} {}", color_text("error:", Color::BoldRed), color_text("a DBURI is required!", Color::BoldWhite));
        println!("{} cat file.sql | first [DBURI]", color_text("usage:", Color::BoldBlue));
        std::process::exit(1);
    }

    let connstr: String = args.nth(1).unwrap();
    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect(&connstr as &str, SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = match ret.is_some() {
                true    => parse_result(&row, i, &coltypes[i]),
                false   => String::from(""),
            };

            colwidths[i] = match col.len() > colwidths[i] {
                true    => col.len(),
                false   => colwidths[i]
            };

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_row(&Vec::new(), &colwidths, &colnames, true);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata, false);
    }
}
<|endoftext|>


<commit_before>use std::io::File; /* input/output */
use std::string::String;
use std::os;
use core::CPU;

mod core;

static MAX_RAM : uint = 0xFFF;
static START_RAM :uint = 0x200;

/* Reads a ROM file and returns a vector containing
 * its bytes if successful. Otherwise an error string
 * if the file is too large or IoError is raised */
fn read_rom(file_path: String) -> Result<Vec<u8>,String> {

    match File::open(&Path::new(file_path)).read_to_end() {

        Ok(rom_contents) =>  {
            /* Programs start at address 0x200, in original implementation
             * 0x000 - 0x1FF reserved for VM, just pad start of mem with
             * 0s in this case */
            let mem = Vec::from_elem(START_RAM, 0u8) + rom_contents;
            let size = mem.len();

            if size <= MAX_RAM {
                    Ok(mem)
            } else { /* Memory read in from game ROM is too large */
                Err(format!("game image is too large
                    ({} bytes), must be a maximum of {} bytes"
                    ,size , MAX_RAM - START_RAM).to_string())
            }
        },
        /* Error reading file */
        Err(e) => Err(e.detail.unwrap_or("".to_string()))
    }
}

fn main() {
    let mut args = os::args();

   let file_name = match args.remove(1)  {
       Some(name) => name,
       None => fail!("No file name specified")
   };

    //debug!("reading file {}",file_name);

    let memory = match read_rom(file_name) {
        Ok(mem) => mem,
        Err(e) => fail!("{}",e)
    };

    assert!(memory.len() <=  MAX_RAM);

    let mut chip8 = core::CPU::new(memory);
    loop {
    //for i in range(0, 51) {
        chip8.perform_cycle();
    }
}

<commit_msg>Added timings for controlling speed of the emulator<commit_after>extern crate time;

use std::io::File; /* input/output */
use std::string::String;
use std::os;
use core::CPU;
use std::io::timer;

mod core;

static MAX_RAM : uint = 0xFFF;
static START_RAM :uint = 0x200;

static INSTRUCTIONS_PER_SEC : u64 = 500;
static CYCLES_CHECK : u64 = 20;

/* Reads a ROM file and returns a vector containing
 * its bytes if successful. Otherwise an error string
 * if the file is too large or IoError is raised */
fn read_rom(file_path: String) -> Result<Vec<u8>,String> {

    match File::open(&Path::new(file_path)).read_to_end() {

        Ok(rom_contents) =>  {
            /* Programs start at address 0x200, in original implementation
             * 0x000 - 0x1FF reserved for VM, just pad start of mem with
             * 0s in this case */
            let mem = Vec::from_elem(START_RAM, 0u8) + rom_contents;
            let size = mem.len();

            if size <= MAX_RAM {
                    Ok(mem)
            } else { /* Memory read in from game ROM is too large */
                Err(format!("game image is too large
                    ({} bytes), must be a maximum of {} bytes"
                    ,size , MAX_RAM - START_RAM).to_string())
            }
        },
        /* Error reading file */
        Err(e) => Err(e.detail.unwrap_or("".to_string()))
    }
}

fn get_time_ms() -> u64 { time::precise_time_ns()/1000000 }

fn wait_for_next_cycle(old_time:u64, instructions:u64, ins_per_sec:u64 )  {
    let current_time = get_time_ms();
    if old_time < current_time {
        timer::sleep(((current_time - old_time) * instructions) / ins_per_sec);
    }
}

fn run_program(mut chip8 :core::CPU, cycle_max: u64, ins_per_sec: u64)  {

    loop {
        let start_timer = get_time_ms();
        for _ in range(0, cycle_max) {
            chip8.perform_cycle();
        }
        wait_for_next_cycle(start_timer, cycle_max, ins_per_sec);
    }
}

fn main() {
    let mut args = os::args();

   let file_name = match args.remove(1)  {
       Some(name) => name,
       None => fail!("No file name specified")
   };

    //debug!("reading file {}",file_name);

    let memory = match read_rom(file_name) {
        Ok(mem) => mem,
        Err(e) => fail!("{}",e)
    };

    assert!(memory.len() <=  MAX_RAM);

    run_program(core::CPU::new(memory), CYCLES_CHECK, INSTRUCTIONS_PER_SEC);
}

<|endoftext|>