<commit_before>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, WebsocatConfiguration};

#[test]
fn trivial() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let s1 = spec("literal:qwerty").unwrap();
    let s2 = spec("assert:qwerty").unwrap();
    let websocat = WebsocatConfiguration {
        opts: Default::default(),
        s1,
        s2,
    };

    let prog = websocat.serve(
        core.handle(),
        std::rc::Rc::new(|_| {
            panic!();
        }),
    );

    core.run(prog).map_err(|()| panic!()).unwrap();
}

#[test]
fn tcp() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let prog1 = {
        let s1 = spec("literal:qwert2y").unwrap();
        let s2 = spec("tcp-l:127.0.0.1:45912").unwrap();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        websocat.serve(
            core.handle(),
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
    let prog2 = {
        let s1 = spec("tcp:127.0.0.1:45912").unwrap();
        let s2 = spec("assert:qwert2y").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };

    let prog = prog1.join(prog2);
    core.run(prog).map_err(|()| panic!()).unwrap();
}

#[test]
fn ws() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let prog1 = {
        let s1 = spec("literal:qwert3y").unwrap();
        let s2 = spec("ws-l:127.0.0.1:45913").unwrap();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        websocat.serve(
            core.handle(),
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
    let prog2 = {
        let s1 = spec("ws://127.0.0.1:45913/ololo").unwrap();
        let s2 = spec("assert:qwert3y").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };

    let prog = prog1.join(prog2);
    core.run(prog).map_err(|()| panic!()).unwrap();
}

#[test]
fn ws_persist() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let prog1 = {
        let s1 = spec("ws-l:127.0.0.1:45914").unwrap();
        let s2 = spec("literal:qwert4y").unwrap();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        websocat.serve(
            core.handle(),
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
    let prog2 = {
        let s1 = spec("literal:invalid_connection_request").unwrap();
        let s2 = spec("tcp:127.0.0.1:45914").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };
    let prog3 = {
        let s1 = spec("ws://127.0.0.1:45914/ololo").unwrap();
        let s2 = spec("assert:qwert4y").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    core.run(prog).map_err(|()| panic!()).unwrap();
}

#[test]
#[cfg(unix)]
fn unix() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let prog1 = {
        let s1 = spec("literal:qwert3y").unwrap();
        let s2 = spec("unix-l:zxc").unwrap();

        let mut opts: websocat::Options = Default::default();
        opts.unlink_unix_socket = true;
        let websocat = WebsocatConfiguration { opts, s1, s2 };

        websocat.serve(
            core.handle(),
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
    let prog2 = {
        let s1 = spec("unix-c:zxc").unwrap();
        let s2 = spec("assert:qwert3y").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };

    let prog = prog1.join(prog2);
    core.run(prog).map_err(|()| panic!()).unwrap();
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    let _ = env_logger::try_init();
    let mut core = Core::new().unwrap();

    let prog1 = {
        let s1 = spec("literal:qwert4y").unwrap();
        let s2 = spec("abstract-l:zxc").unwrap();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        websocat.serve(
            core.handle(),
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
    let prog2 = {
        let s1 = spec("abstract-c:zxc").unwrap();
        let s2 = spec("assert:qwert4y").unwrap();
        let h2 = core.handle();

        let websocat = WebsocatConfiguration {
            opts: Default::default(),
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, 200_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            websocat.serve(
                h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
        })
    };

    let prog = prog1.join(prog2);
    core.run(prog).map_err(|()| panic!()).unwrap();
}
<commit_msg>Refactor the test<commit_after>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, WebsocatConfiguration, Options};

fn dflt() -> Options {
    Default::default()
}

macro_rules! wt {
    ($core:ident, $s1:expr, $s2:expr, noopts, delay=$ms:expr) => {
        wt!($core, $s1, $s2, opts=Default::default(), delay=$ms);
    };
    ($core:ident, $s1:expr, $s2:expr, noopts, nodelay) => {
        wt!($core, $s1, $s2, opts=Default::default(), nodelay);
    };
    ($core:ident, $s1:expr, $s2:expr, opts=$opts:expr, delay=$ms:expr) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let websocat = WebsocatConfiguration {
            opts: $opts,
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t.sleep(std::time::Duration::new(0, $ms*1_000_000))
            .map_err(|_| ());

        delay.and_then(|()| {
            wt!(wss, websocat, h2)
        })
    }};
    ($core:ident, $s1:expr, $s2:expr, opts=$opts:expr, nodelay) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let websocat = WebsocatConfiguration {
            opts: $opts,
            s1,
            s2,
        };

        wt!(wss, websocat, h2)
    }};
    (wss, $websocat:ident, $h2:ident) => {
        $websocat.serve(
                $h2,
                std::rc::Rc::new(|e| {
                    eprintln!("{}", e);
                    panic!();
                }),
            )
    };
}

macro_rules! prepare {
    ($core:ident) => {
        let _ = env_logger::try_init();
        let mut $core = Core::new().unwrap();
    };
}
macro_rules! run {
    ($core:ident, $prog:expr) => {
        $core.run($prog).map_err(|()| panic!()).unwrap();
    };
}

#[test]
fn trivial() {
    prepare!(core);
    let prog = wt!(core,
        "literal:qwerty",
        "assert:qwerty",
        noopts,
        nodelay);
    run!(core, prog);
}

#[test]
fn tcp() {
    prepare!(core);
    let prog1 = wt!(core,
        "literal:qwert2y",
        "tcp-l:127.0.0.1:45912",
        noopts,
        nodelay);
    let prog2 = wt!(core,
        "tcp:127.0.0.1:45912",
        "assert:qwert2y",
        noopts,
        delay=200);

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws() {
    prepare!(core);
    let prog1 = wt!(core,
        "literal:qwert3y",
        "ws-l:127.0.0.1:45913",
        noopts,
        nodelay);
    let prog2 = wt!(core,
        "ws://127.0.0.1:45913/ololo",
        "assert:qwert3y",
        noopts,
        delay=200);

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws_persist() {
    prepare!(core);
    let prog1 = wt!(core,
        "ws-l:127.0.0.1:45914",
        "literal:qwert4y",
        noopts,
        nodelay);
    let prog2 = wt!(core,
        "literal:invalid_connection_request",
        "tcp:127.0.0.1:45914",
        noopts,
        delay=200 );
    let prog3 = wt!(core,
        "ws://127.0.0.1:45914/ololo",
        "assert:qwert4y",
        noopts,
        delay=400 );

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    run!(core, prog);
}

#[test]
#[cfg(unix)]
fn unix() {
    prepare!(core);
    let prog1 = wt!(core,
        "literal:qwert3y",
        "unix-l:zxc",
        opts=Options { unlink_unix_socket: true, ..dflt() },
        nodelay);
    let prog2 = wt!(core,
        "unix-c:zxc",
        "assert:qwert3y",
        noopts,
        delay=200);

    let prog = prog1.join(prog2);
    run!(core, prog);
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    prepare!(core);
    let prog1 = wt!(core,
        "literal:qwert4y",
        "abstract-l:zxc",
        noopts,
        nodelay);
    let prog2 = wt!(core,
        "abstract-c:zxc",
        "assert:qwert4y",
        noopts,
        delay=200);

    let prog = prog1.join(prog2);
    run!(core, prog);
}
<|endoftext|>


<commit_before>//! Provides a way to attach fixes to the diagnostics.
//! The same module also has all curret custom fixes for the diagnostics implemented.
use ast::MethodCallExpr;
use hir::{
    db::AstDatabase,
    diagnostics::{
        Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField,
        RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnresolvedModule,
    },
    HasSource, HirDisplay, InFile, Semantics, VariantDef,
};
use ide_db::{
    base_db::{AnchoredPathBuf, FileId},
    source_change::{FileSystemEdit, SourceChange},
    RootDatabase,
};
use syntax::{
    algo,
    ast::{self, edit::IndentLevel, make, ArgList},
    AstNode, TextRange,
};
use text_edit::TextEdit;

use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition};

/// A [Diagnostic] that potentially has a fix available.
///
/// [Diagnostic]: hir::diagnostics::Diagnostic
pub(crate) trait DiagnosticWithFix: Diagnostic {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>;
}

impl DiagnosticWithFix for UnresolvedModule {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let unresolved_module = self.decl.to_node(&root);
        Some(Fix::new(
            "Create module",
            FileSystemEdit::CreateFile {
                dst: AnchoredPathBuf {
                    anchor: self.file.original_file(sema.db),
                    path: self.candidate.clone(),
                },
                initial_contents: "".to_string(),
            }
            .into(),
            unresolved_module.syntax().text_range(),
        ))
    }
}

impl DiagnosticWithFix for NoSuchField {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        missing_record_expr_field_fix(
            &sema,
            self.file.original_file(sema.db),
            &self.field.to_node(&root),
        )
    }
}

impl DiagnosticWithFix for MissingFields {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        // Note that although we could add a diagnostics to
        // fill the missing tuple field, e.g :
        // `struct A(usize);`
        // `let a = A { 0: () }`
        // but it is uncommon usage and it should not be encouraged.
        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
            return None;
        }

        let root = sema.db.parse_or_expand(self.file)?;
        let field_list_parent = self.field_list_parent.to_node(&root);
        let old_field_list = field_list_parent.record_expr_field_list()?;
        let mut new_field_list = old_field_list.clone();
        for f in self.missed_fields.iter() {
            let field =
                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
            new_field_list = new_field_list.append_field(&field);
        }

        let edit = {
            let mut builder = TextEdit::builder();
            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
                .into_text_edit(&mut builder);
            builder.finish()
        };
        Some(Fix::new(
            "Fill struct fields",
            SourceChange::from_text_edit(self.file.original_file(sema.db), edit),
            sema.original_range(&field_list_parent.syntax()).range,
        ))
    }
}

impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let tail_expr = self.expr.to_node(&root);
        let tail_expr_range = tail_expr.syntax().text_range();
        let replacement = format!("{}({})", self.required, tail_expr.syntax());
        let edit = TextEdit::replace(tail_expr_range, replacement);
        let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
        let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
        Some(Fix::new(name, source_change, tail_expr_range))
    }
}

impl DiagnosticWithFix for RemoveThisSemicolon {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;

        let semicolon = self
            .expr
            .to_node(&root)
            .syntax()
            .parent()
            .and_then(ast::ExprStmt::cast)
            .and_then(|expr| expr.semicolon_token())?
            .text_range();

        let edit = TextEdit::delete(semicolon);
        let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);

        Some(Fix::new("Remove this semicolon", source_change, semicolon))
    }
}

impl DiagnosticWithFix for IncorrectCase {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let name_node = self.ident.to_node(&root);

        let name_node = InFile::new(self.file, name_node.syntax());
        let frange = name_node.original_file_range(sema.db);
        let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };

        let rename_changes =
            rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;

        let label = format!("Rename to {}", self.suggested_text);
        Some(Fix::new(&label, rename_changes, frange.range))
    }
}

impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let next_expr = self.next_expr.to_node(&root);
        let next_call = MethodCallExpr::cast(next_expr.syntax().clone())?;

        let filter_map_call = MethodCallExpr::cast(next_call.receiver()?.syntax().clone())?;
        let filter_map_name_range = filter_map_call.name_ref()?.ident_token()?.text_range();
        let filter_map_args = filter_map_call.syntax().children().find_map(ArgList::cast)?;

        let range_to_replace =
            TextRange::new(filter_map_name_range.start(), next_expr.syntax().text_range().end());
        let replacement = format!("find_map{}", filter_map_args.syntax().text());
        let trigger_range = next_expr.syntax().text_range();

        let edit = TextEdit::replace(range_to_replace, replacement);

        let source_change =
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();

        Some(Fix::new(
            "Replace filter_map(..).next() with find_map()",
            source_change,
            trigger_range,
        ))
    }
}

fn missing_record_expr_field_fix(
    sema: &Semantics<RootDatabase>,
    usage_file_id: FileId,
    record_expr_field: &ast::RecordExprField,
) -> Option<Fix> {
    let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
    let def_id = sema.resolve_variant(record_lit)?;
    let module;
    let def_file_id;
    let record_fields = match VariantDef::from(def_id) {
        VariantDef::Struct(s) => {
            module = s.module(sema.db);
            let source = s.source(sema.db)?;
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
        VariantDef::Union(u) => {
            module = u.module(sema.db);
            let source = u.source(sema.db)?;
            def_file_id = source.file_id;
            source.value.record_field_list()?
        }
        VariantDef::Variant(e) => {
            module = e.module(sema.db);
            let source = e.source(sema.db)?;
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
    };
    let def_file_id = def_file_id.original_file(sema.db);

    let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?;
    if new_field_type.is_unknown() {
        return None;
    }
    let new_field = make::record_field(
        None,
        make::name(record_expr_field.field_name()?.text()),
        make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
    );

    let last_field = record_fields.fields().last()?;
    let last_field_syntax = last_field.syntax();
    let indent = IndentLevel::from_node(last_field_syntax);

    let mut new_field = new_field.to_string();
    if usage_file_id != def_file_id {
        new_field = format!("pub(crate) {}", new_field);
    }
    new_field = format!("\n{}{}", indent, new_field);

    let needs_comma = !last_field_syntax.to_string().ends_with(',');
    if needs_comma {
        new_field = format!(",{}", new_field);
    }

    let source_change = SourceChange::from_text_edit(
        def_file_id,
        TextEdit::insert(last_field_syntax.text_range().end(), new_field),
    );
    return Some(Fix::new("Create field", source_change, record_expr_field.syntax().text_range()));

    fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
        match field_def_list {
            ast::FieldList::RecordFieldList(it) => Some(it),
            ast::FieldList::TupleFieldList(_) => None,
        }
    }
}
<commit_msg>Address review comments<commit_after>//! Provides a way to attach fixes to the diagnostics.
//! The same module also has all curret custom fixes for the diagnostics implemented.
use hir::{
    db::AstDatabase,
    diagnostics::{
        Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField,
        RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnresolvedModule,
    },
    HasSource, HirDisplay, InFile, Semantics, VariantDef,
};
use ide_db::{
    base_db::{AnchoredPathBuf, FileId},
    source_change::{FileSystemEdit, SourceChange},
    RootDatabase,
};
use syntax::{AstNode, TextRange, algo, ast::{self, ArgListOwner, edit::IndentLevel, make}};
use text_edit::TextEdit;

use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition};

/// A [Diagnostic] that potentially has a fix available.
///
/// [Diagnostic]: hir::diagnostics::Diagnostic
pub(crate) trait DiagnosticWithFix: Diagnostic {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>;
}

impl DiagnosticWithFix for UnresolvedModule {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let unresolved_module = self.decl.to_node(&root);
        Some(Fix::new(
            "Create module",
            FileSystemEdit::CreateFile {
                dst: AnchoredPathBuf {
                    anchor: self.file.original_file(sema.db),
                    path: self.candidate.clone(),
                },
                initial_contents: "".to_string(),
            }
            .into(),
            unresolved_module.syntax().text_range(),
        ))
    }
}

impl DiagnosticWithFix for NoSuchField {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        missing_record_expr_field_fix(
            &sema,
            self.file.original_file(sema.db),
            &self.field.to_node(&root),
        )
    }
}

impl DiagnosticWithFix for MissingFields {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        // Note that although we could add a diagnostics to
        // fill the missing tuple field, e.g :
        // `struct A(usize);`
        // `let a = A { 0: () }`
        // but it is uncommon usage and it should not be encouraged.
        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
            return None;
        }

        let root = sema.db.parse_or_expand(self.file)?;
        let field_list_parent = self.field_list_parent.to_node(&root);
        let old_field_list = field_list_parent.record_expr_field_list()?;
        let mut new_field_list = old_field_list.clone();
        for f in self.missed_fields.iter() {
            let field =
                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
            new_field_list = new_field_list.append_field(&field);
        }

        let edit = {
            let mut builder = TextEdit::builder();
            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
                .into_text_edit(&mut builder);
            builder.finish()
        };
        Some(Fix::new(
            "Fill struct fields",
            SourceChange::from_text_edit(self.file.original_file(sema.db), edit),
            sema.original_range(&field_list_parent.syntax()).range,
        ))
    }
}

impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let tail_expr = self.expr.to_node(&root);
        let tail_expr_range = tail_expr.syntax().text_range();
        let replacement = format!("{}({})", self.required, tail_expr.syntax());
        let edit = TextEdit::replace(tail_expr_range, replacement);
        let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
        let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" };
        Some(Fix::new(name, source_change, tail_expr_range))
    }
}

impl DiagnosticWithFix for RemoveThisSemicolon {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;

        let semicolon = self
            .expr
            .to_node(&root)
            .syntax()
            .parent()
            .and_then(ast::ExprStmt::cast)
            .and_then(|expr| expr.semicolon_token())?
            .text_range();

        let edit = TextEdit::delete(semicolon);
        let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);

        Some(Fix::new("Remove this semicolon", source_change, semicolon))
    }
}

impl DiagnosticWithFix for IncorrectCase {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let name_node = self.ident.to_node(&root);

        let name_node = InFile::new(self.file, name_node.syntax());
        let frange = name_node.original_file_range(sema.db);
        let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };

        let rename_changes =
            rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;

        let label = format!("Rename to {}", self.suggested_text);
        Some(Fix::new(&label, rename_changes, frange.range))
    }
}

impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let next_expr = self.next_expr.to_node(&root);
        let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;

        let filter_map_call = ast::MethodCallExpr::cast(next_call.receiver()?.syntax().clone())?;
        let filter_map_name_range = filter_map_call.name_ref()?.ident_token()?.text_range();
        let filter_map_args = filter_map_call.arg_list()?;

        let range_to_replace =
            TextRange::new(filter_map_name_range.start(), next_expr.syntax().text_range().end());
        let replacement = format!("find_map{}", filter_map_args.syntax().text());
        let trigger_range = next_expr.syntax().text_range();

        let edit = TextEdit::replace(range_to_replace, replacement);

        let source_change =
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();

        Some(Fix::new(
            "Replace filter_map(..).next() with find_map()",
            source_change,
            trigger_range,
        ))
    }
}

fn missing_record_expr_field_fix(
    sema: &Semantics<RootDatabase>,
    usage_file_id: FileId,
    record_expr_field: &ast::RecordExprField,
) -> Option<Fix> {
    let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
    let def_id = sema.resolve_variant(record_lit)?;
    let module;
    let def_file_id;
    let record_fields = match VariantDef::from(def_id) {
        VariantDef::Struct(s) => {
            module = s.module(sema.db);
            let source = s.source(sema.db)?;
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
        VariantDef::Union(u) => {
            module = u.module(sema.db);
            let source = u.source(sema.db)?;
            def_file_id = source.file_id;
            source.value.record_field_list()?
        }
        VariantDef::Variant(e) => {
            module = e.module(sema.db);
            let source = e.source(sema.db)?;
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
    };
    let def_file_id = def_file_id.original_file(sema.db);

    let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?;
    if new_field_type.is_unknown() {
        return None;
    }
    let new_field = make::record_field(
        None,
        make::name(record_expr_field.field_name()?.text()),
        make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
    );

    let last_field = record_fields.fields().last()?;
    let last_field_syntax = last_field.syntax();
    let indent = IndentLevel::from_node(last_field_syntax);

    let mut new_field = new_field.to_string();
    if usage_file_id != def_file_id {
        new_field = format!("pub(crate) {}", new_field);
    }
    new_field = format!("\n{}{}", indent, new_field);

    let needs_comma = !last_field_syntax.to_string().ends_with(',');
    if needs_comma {
        new_field = format!(",{}", new_field);
    }

    let source_change = SourceChange::from_text_edit(
        def_file_id,
        TextEdit::insert(last_field_syntax.text_range().end(), new_field),
    );
    return Some(Fix::new("Create field", source_change, record_expr_field.syntax().text_range()));

    fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
        match field_def_list {
            ast::FieldList::RecordFieldList(it) => Some(it),
            ast::FieldList::TupleFieldList(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>//! Driver for proc macro server

use crate::{expand_task, list_macros};
use ra_proc_macro::msg::{self, Message};
use std::io;

pub fn run() {
    loop {
        let req = match read_request() {
            Err(err) => {
                // Panic here, as the stdin pipe may be closed.
                // Otherwise, client will be restart the service anyway.
                panic!("Read message error on ra_proc_macro_srv: {}", err);
            }
            Ok(None) => continue,
            Ok(Some(req)) => req,
        };

        let res = match req {
            msg::Request::ListMacro(task) => Ok(msg::Response::ListMacro(list_macros(&task))),
            msg::Request::ExpansionMacro(task) => {
                expand_task(&task).map(msg::Response::ExpansionMacro)
            }
        };

        let msg = res.unwrap_or_else(|err| {
            msg::Response::Error(msg::ResponseError {
                code: msg::ErrorCode::ExpansionError,
                message: err,
            })
        });

        if let Err(err) = write_response(msg) {
            eprintln!("Write message error: {}", err);
        }
    }
}

fn read_request() -> io::Result<Option<msg::Request>> {
    msg::Request::read(&mut io::stdin().lock())
}

fn write_response(msg: msg::Response) -> io::Result<()> {
    msg.write(&mut io::stdout().lock())
}
<commit_msg>Fix typo<commit_after>//! Driver for proc macro server

use crate::{expand_task, list_macros};
use ra_proc_macro::msg::{self, Message};
use std::io;

pub fn run() {
    loop {
        let req = match read_request() {
            Err(err) => {
                // Panic here, as the stdin pipe may be closed.
                // Otherwise, client will be restarted the service anyway.
                panic!("Read message error on ra_proc_macro_srv: {}", err);
            }
            Ok(None) => continue,
            Ok(Some(req)) => req,
        };

        let res = match req {
            msg::Request::ListMacro(task) => Ok(msg::Response::ListMacro(list_macros(&task))),
            msg::Request::ExpansionMacro(task) => {
                expand_task(&task).map(msg::Response::ExpansionMacro)
            }
        };

        let msg = res.unwrap_or_else(|err| {
            msg::Response::Error(msg::ResponseError {
                code: msg::ErrorCode::ExpansionError,
                message: err,
            })
        });

        if let Err(err) = write_response(msg) {
            eprintln!("Write message error: {}", err);
        }
    }
}

fn read_request() -> io::Result<Option<msg::Request>> {
    msg::Request::read(&mut io::stdin().lock())
}

fn write_response(msg: msg::Response) -> io::Result<()> {
    msg.write(&mut io::stdout().lock())
}
<|endoftext|>


<commit_before>//! Helpers for writing generators

use clap::{Arg, Command};

/// Gets all subcommands including child subcommands in the form of `("name", "bin_name")`.
///
/// Subcommand `rustup toolchain install` would be converted to
/// `("install", "rustup toolchain install")`.
pub fn all_subcommands(cmd: &Command) -> Vec<(String, String)> {
    let mut subcmds: Vec<_> = subcommands(cmd);

    for sc_v in cmd.get_subcommands().map(all_subcommands) {
        subcmds.extend(sc_v);
    }

    subcmds
}

/// Finds the subcommand [`clap::Command`] from the given [`clap::Command`] with the given path.
///
/// **NOTE:** `path` should not contain the root `bin_name`.
pub fn find_subcommand_with_path<'cmd>(p: &'cmd Command, path: Vec<&str>) -> &'cmd Command {
    let mut cmd = p;

    for sc in path {
        cmd = cmd.find_subcommand(sc).unwrap();
    }

    cmd
}

/// Gets subcommands of [`clap::Command`] in the form of `("name", "bin_name")`.
///
/// Subcommand `rustup toolchain install` would be converted to
/// `("install", "rustup toolchain install")`.
pub fn subcommands(p: &Command) -> Vec<(String, String)> {
    debug!("subcommands: name={}", p.get_name());
    debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());

    let mut subcmds = vec![];

    if !p.has_subcommands() {
        return subcmds;
    }

    for sc in p.get_subcommands() {
        let sc_bin_name = sc.get_bin_name().unwrap();

        debug!(
            "subcommands:iter: name={}, bin_name={}",
            sc.get_name(),
            sc_bin_name
        );

        subcmds.push((sc.get_name().to_string(), sc_bin_name.to_string()));
    }

    subcmds
}

/// Gets all the short options, their visible aliases and flags of a [`clap::Command`].
/// Includes `h` and `V` depending on the [`clap::Command`] settings.
pub fn shorts_and_visible_aliases(p: &Command) -> Vec<char> {
    debug!("shorts: name={}", p.get_name());

    p.get_arguments()
        .filter_map(|a| {
            if !a.is_positional() {
                if a.get_visible_short_aliases().is_some() && a.get_short().is_some() {
                    let mut shorts_and_visible_aliases = a.get_visible_short_aliases().unwrap();
                    shorts_and_visible_aliases.push(a.get_short().unwrap());
                    Some(shorts_and_visible_aliases)
                } else if a.get_visible_short_aliases().is_none() && a.get_short().is_some() {
                    Some(vec![a.get_short().unwrap()])
                } else {
                    None
                }
            } else {
                None
            }
        })
        .flatten()
        .collect()
}

/// Gets all the long options, their visible aliases and flags of a [`clap::Command`].
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn longs_and_visible_aliases(p: &Command) -> Vec<String> {
    debug!("longs: name={}", p.get_name());

    p.get_arguments()
        .filter_map(|a| {
            if !a.is_positional() {
                if a.get_visible_aliases().is_some() && a.get_long().is_some() {
                    let mut visible_aliases: Vec<_> = a
                        .get_visible_aliases()
                        .unwrap()
                        .into_iter()
                        .map(|s| s.to_string())
                        .collect();
                    visible_aliases.push(a.get_long().unwrap().to_string());
                    Some(visible_aliases)
                } else if a.get_visible_aliases().is_none() && a.get_long().is_some() {
                    Some(vec![a.get_long().unwrap().to_string()])
                } else {
                    None
                }
            } else {
                None
            }
        })
        .flatten()
        .collect()
}

/// Gets all the flags of a [`clap::Command`](Command).
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn flags(p: &Command) -> Vec<Arg> {
    debug!("flags: name={}", p.get_name());
    p.get_arguments()
        .filter(|a| !a.get_num_args().expect("built").takes_values() && !a.is_positional())
        .cloned()
        .collect()
}

/// Get the possible values for completion
pub fn possible_values(a: &Arg) -> Option<Vec<clap::builder::PossibleValue>> {
    if !a.get_num_args().expect("built").takes_values() {
        None
    } else {
        a.get_value_parser()
            .possible_values()
            .map(|pvs| pvs.collect())
    }
}

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

    fn common_app() -> Command {
        Command::new("myapp")
            .subcommand(
                Command::new("test").subcommand(Command::new("config")).arg(
                    Arg::new("file")
                        .short('f')
                        .short_alias('c')
                        .visible_short_alias('p')
                        .long("file")
                        .action(ArgAction::SetTrue)
                        .visible_alias("path"),
                ),
            )
            .subcommand(Command::new("hello"))
            .bin_name("my-cmd")
    }

    fn built() -> Command {
        let mut cmd = common_app();

        cmd.build();
        cmd
    }

    fn built_with_version() -> Command {
        let mut cmd = common_app().version("3.0");

        cmd.build();
        cmd
    }

    #[test]
    fn test_subcommands() {
        let cmd = built_with_version();

        assert_eq!(
            subcommands(&cmd),
            vec![
                ("test".to_string(), "my-cmd test".to_string()),
                ("hello".to_string(), "my-cmd hello".to_string()),
                ("help".to_string(), "my-cmd help".to_string()),
            ]
        );
    }

    #[test]
    fn test_all_subcommands() {
        let cmd = built_with_version();

        assert_eq!(
            all_subcommands(&cmd),
            vec![
                ("test".to_string(), "my-cmd test".to_string()),
                ("hello".to_string(), "my-cmd hello".to_string()),
                ("help".to_string(), "my-cmd help".to_string()),
                ("config".to_string(), "my-cmd test config".to_string()),
                ("help".to_string(), "my-cmd test help".to_string()),
                ("config".to_string(), "my-cmd test help config".to_string()),
                ("help".to_string(), "my-cmd test help help".to_string()),
                ("test".to_string(), "my-cmd help test".to_string()),
                ("hello".to_string(), "my-cmd help hello".to_string()),
                ("help".to_string(), "my-cmd help help".to_string()),
                ("config".to_string(), "my-cmd help test config".to_string()),
            ]
        );
    }

    #[test]
    fn test_find_subcommand_with_path() {
        let cmd = built_with_version();
        let sc_app = find_subcommand_with_path(&cmd, "test config".split(' ').collect());

        assert_eq!(sc_app.get_name(), "config");
    }

    #[test]
    fn test_flags() {
        let cmd = built_with_version();
        let actual_flags = flags(&cmd);

        assert_eq!(actual_flags.len(), 2);
        assert_eq!(actual_flags[0].get_long(), Some("help"));
        assert_eq!(actual_flags[1].get_long(), Some("version"));

        let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_flags.len(), 2);
        assert_eq!(sc_flags[0].get_long(), Some("file"));
        assert_eq!(sc_flags[1].get_long(), Some("help"));
    }

    #[test]
    fn test_flag_subcommand() {
        let cmd = built();
        let actual_flags = flags(&cmd);

        assert_eq!(actual_flags.len(), 1);
        assert_eq!(actual_flags[0].get_long(), Some("help"));

        let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_flags.len(), 2);
        assert_eq!(sc_flags[0].get_long(), Some("file"));
        assert_eq!(sc_flags[1].get_long(), Some("help"));
    }

    #[test]
    fn test_shorts() {
        let cmd = built_with_version();
        let shorts = shorts_and_visible_aliases(&cmd);

        assert_eq!(shorts.len(), 2);
        assert_eq!(shorts[0], 'h');
        assert_eq!(shorts[1], 'V');

        let sc_shorts = shorts_and_visible_aliases(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_shorts.len(), 3);
        assert_eq!(sc_shorts[0], 'p');
        assert_eq!(sc_shorts[1], 'f');
        assert_eq!(sc_shorts[2], 'h');
    }

    #[test]
    fn test_longs() {
        let cmd = built_with_version();
        let longs = longs_and_visible_aliases(&cmd);

        assert_eq!(longs.len(), 2);
        assert_eq!(longs[0], "help");
        assert_eq!(longs[1], "version");

        let sc_longs = longs_and_visible_aliases(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_longs.len(), 3);
        assert_eq!(sc_longs[0], "path");
        assert_eq!(sc_longs[1], "file");
        assert_eq!(sc_longs[2], "help");
    }
}
<commit_msg>refactor(complete): Remove unnecessary early return<commit_after>//! Helpers for writing generators

use clap::{Arg, Command};

/// Gets all subcommands including child subcommands in the form of `("name", "bin_name")`.
///
/// Subcommand `rustup toolchain install` would be converted to
/// `("install", "rustup toolchain install")`.
pub fn all_subcommands(cmd: &Command) -> Vec<(String, String)> {
    let mut subcmds: Vec<_> = subcommands(cmd);

    for sc_v in cmd.get_subcommands().map(all_subcommands) {
        subcmds.extend(sc_v);
    }

    subcmds
}

/// Finds the subcommand [`clap::Command`] from the given [`clap::Command`] with the given path.
///
/// **NOTE:** `path` should not contain the root `bin_name`.
pub fn find_subcommand_with_path<'cmd>(p: &'cmd Command, path: Vec<&str>) -> &'cmd Command {
    let mut cmd = p;

    for sc in path {
        cmd = cmd.find_subcommand(sc).unwrap();
    }

    cmd
}

/// Gets subcommands of [`clap::Command`] in the form of `("name", "bin_name")`.
///
/// Subcommand `rustup toolchain install` would be converted to
/// `("install", "rustup toolchain install")`.
pub fn subcommands(p: &Command) -> Vec<(String, String)> {
    debug!("subcommands: name={}", p.get_name());
    debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());

    let mut subcmds = vec![];

    for sc in p.get_subcommands() {
        let sc_bin_name = sc.get_bin_name().unwrap();

        debug!(
            "subcommands:iter: name={}, bin_name={}",
            sc.get_name(),
            sc_bin_name
        );

        subcmds.push((sc.get_name().to_string(), sc_bin_name.to_string()));
    }

    subcmds
}

/// Gets all the short options, their visible aliases and flags of a [`clap::Command`].
/// Includes `h` and `V` depending on the [`clap::Command`] settings.
pub fn shorts_and_visible_aliases(p: &Command) -> Vec<char> {
    debug!("shorts: name={}", p.get_name());

    p.get_arguments()
        .filter_map(|a| {
            if !a.is_positional() {
                if a.get_visible_short_aliases().is_some() && a.get_short().is_some() {
                    let mut shorts_and_visible_aliases = a.get_visible_short_aliases().unwrap();
                    shorts_and_visible_aliases.push(a.get_short().unwrap());
                    Some(shorts_and_visible_aliases)
                } else if a.get_visible_short_aliases().is_none() && a.get_short().is_some() {
                    Some(vec![a.get_short().unwrap()])
                } else {
                    None
                }
            } else {
                None
            }
        })
        .flatten()
        .collect()
}

/// Gets all the long options, their visible aliases and flags of a [`clap::Command`].
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn longs_and_visible_aliases(p: &Command) -> Vec<String> {
    debug!("longs: name={}", p.get_name());

    p.get_arguments()
        .filter_map(|a| {
            if !a.is_positional() {
                if a.get_visible_aliases().is_some() && a.get_long().is_some() {
                    let mut visible_aliases: Vec<_> = a
                        .get_visible_aliases()
                        .unwrap()
                        .into_iter()
                        .map(|s| s.to_string())
                        .collect();
                    visible_aliases.push(a.get_long().unwrap().to_string());
                    Some(visible_aliases)
                } else if a.get_visible_aliases().is_none() && a.get_long().is_some() {
                    Some(vec![a.get_long().unwrap().to_string()])
                } else {
                    None
                }
            } else {
                None
            }
        })
        .flatten()
        .collect()
}

/// Gets all the flags of a [`clap::Command`](Command).
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn flags(p: &Command) -> Vec<Arg> {
    debug!("flags: name={}", p.get_name());
    p.get_arguments()
        .filter(|a| !a.get_num_args().expect("built").takes_values() && !a.is_positional())
        .cloned()
        .collect()
}

/// Get the possible values for completion
pub fn possible_values(a: &Arg) -> Option<Vec<clap::builder::PossibleValue>> {
    if !a.get_num_args().expect("built").takes_values() {
        None
    } else {
        a.get_value_parser()
            .possible_values()
            .map(|pvs| pvs.collect())
    }
}

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

    fn common_app() -> Command {
        Command::new("myapp")
            .subcommand(
                Command::new("test").subcommand(Command::new("config")).arg(
                    Arg::new("file")
                        .short('f')
                        .short_alias('c')
                        .visible_short_alias('p')
                        .long("file")
                        .action(ArgAction::SetTrue)
                        .visible_alias("path"),
                ),
            )
            .subcommand(Command::new("hello"))
            .bin_name("my-cmd")
    }

    fn built() -> Command {
        let mut cmd = common_app();

        cmd.build();
        cmd
    }

    fn built_with_version() -> Command {
        let mut cmd = common_app().version("3.0");

        cmd.build();
        cmd
    }

    #[test]
    fn test_subcommands() {
        let cmd = built_with_version();

        assert_eq!(
            subcommands(&cmd),
            vec![
                ("test".to_string(), "my-cmd test".to_string()),
                ("hello".to_string(), "my-cmd hello".to_string()),
                ("help".to_string(), "my-cmd help".to_string()),
            ]
        );
    }

    #[test]
    fn test_all_subcommands() {
        let cmd = built_with_version();

        assert_eq!(
            all_subcommands(&cmd),
            vec![
                ("test".to_string(), "my-cmd test".to_string()),
                ("hello".to_string(), "my-cmd hello".to_string()),
                ("help".to_string(), "my-cmd help".to_string()),
                ("config".to_string(), "my-cmd test config".to_string()),
                ("help".to_string(), "my-cmd test help".to_string()),
                ("config".to_string(), "my-cmd test help config".to_string()),
                ("help".to_string(), "my-cmd test help help".to_string()),
                ("test".to_string(), "my-cmd help test".to_string()),
                ("hello".to_string(), "my-cmd help hello".to_string()),
                ("help".to_string(), "my-cmd help help".to_string()),
                ("config".to_string(), "my-cmd help test config".to_string()),
            ]
        );
    }

    #[test]
    fn test_find_subcommand_with_path() {
        let cmd = built_with_version();
        let sc_app = find_subcommand_with_path(&cmd, "test config".split(' ').collect());

        assert_eq!(sc_app.get_name(), "config");
    }

    #[test]
    fn test_flags() {
        let cmd = built_with_version();
        let actual_flags = flags(&cmd);

        assert_eq!(actual_flags.len(), 2);
        assert_eq!(actual_flags[0].get_long(), Some("help"));
        assert_eq!(actual_flags[1].get_long(), Some("version"));

        let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_flags.len(), 2);
        assert_eq!(sc_flags[0].get_long(), Some("file"));
        assert_eq!(sc_flags[1].get_long(), Some("help"));
    }

    #[test]
    fn test_flag_subcommand() {
        let cmd = built();
        let actual_flags = flags(&cmd);

        assert_eq!(actual_flags.len(), 1);
        assert_eq!(actual_flags[0].get_long(), Some("help"));

        let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_flags.len(), 2);
        assert_eq!(sc_flags[0].get_long(), Some("file"));
        assert_eq!(sc_flags[1].get_long(), Some("help"));
    }

    #[test]
    fn test_shorts() {
        let cmd = built_with_version();
        let shorts = shorts_and_visible_aliases(&cmd);

        assert_eq!(shorts.len(), 2);
        assert_eq!(shorts[0], 'h');
        assert_eq!(shorts[1], 'V');

        let sc_shorts = shorts_and_visible_aliases(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_shorts.len(), 3);
        assert_eq!(sc_shorts[0], 'p');
        assert_eq!(sc_shorts[1], 'f');
        assert_eq!(sc_shorts[2], 'h');
    }

    #[test]
    fn test_longs() {
        let cmd = built_with_version();
        let longs = longs_and_visible_aliases(&cmd);

        assert_eq!(longs.len(), 2);
        assert_eq!(longs[0], "help");
        assert_eq!(longs[1], "version");

        let sc_longs = longs_and_visible_aliases(find_subcommand_with_path(&cmd, vec!["test"]));

        assert_eq!(sc_longs.len(), 3);
        assert_eq!(sc_longs[0], "path");
        assert_eq!(sc_longs[1], "file");
        assert_eq!(sc_longs[2], "help");
    }
}
<|endoftext|>


<commit_before>//! Asynchronous streams
//!
//! See [Asynchronous Programming in Rust](https://aturon.github.io/apr/) for an
//! overview.

use Poll;
use task;

/// A stream of values produced asynchronously.
///
/// If `Future` is an asynchronous version of `Result`, then `Stream` is an
/// asynchronous version of `Iterator`. A stream represents a sequence of
/// value-producing events that occur asynchronously to the caller.
///
/// The trait is modeled after `Future`, but allows `poll` to be called even
/// after a value has been produced, yielding `None` once the stream has been
/// fully exhausted.
///
/// # Errors
///
/// Streams, like futures, also bake in errors through an associated `Error`
/// type. An error on a stream **does not terminate the stream**. That is,
/// after one error is received, another value may be received from the same
/// stream (it's valid to keep polling). Thus a stream is somewhat like an
/// `Iterator<Item = Result<T, E>>`, and is always terminated by returning
/// `None`.
pub trait Stream {
    /// Values yielded by the stream.
    type Item;

    /// Errors yielded by the stream.
    type Error;

    /// Attempt to pull out the next value of this stream, returning `None` if
    /// the stream is finished.
    ///
    /// This method, like [`Future::poll`](::future::Future::poll), makes
    /// progress on producing the next value in the stream, but does not block
    /// if one is not available yet; it instead queues the current task to be
    /// woken up when more progress is possible.
    ///
    /// # Return value
    ///
    /// There are several possible return values, each indicating a distinct
    /// stream state:
    ///
    /// - [`Ok(Pending)`](::Async) means that this stream's next value is not
    /// ready yet. Implementations will ensure that the current task will be
    /// notified when the next value may be ready.
    ///
    /// - [`Ok(Ready(Some(val)))`](::Async) means that the stream has
    /// successfully produced a value, `val`, and may produce further values
    /// on subsequent `poll` calls.
    ///
    /// - [`Ok(Ready(None))`](::Async) means that the stream has terminated, and
    /// `poll` should not be invoked again.
    ///
    /// - `Err(err)` means that the stream encountered an error while trying to
    /// `poll`. Subsequent calls to `poll` *are* allowed, and may return further
    /// values or errors.
    ///
    /// # Panics
    ///
    /// Once a stream is finished, i.e. `Ready(None)` has been returned, further
    /// calls to `poll` may result in a panic or other "bad behavior".  If this
    /// is difficult to guard against then the `fuse` adapter can be used to
    /// ensure that `poll_next` always returns `Ready(None)` in subsequent calls.
    fn poll(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error>;
}

impl<'a, S: ?Sized + Stream> Stream for &'a mut S {
    type Item = S::Item;
    type Error = S::Error;

    fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
        (**self).poll_next(cx)
    }
}

if_std! {
    impl<S: ?Sized + Stream> Stream for ::std::boxed::Box<S> {
        type Item = S::Item;
        type Error = S::Error;

        fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
            (**self).poll_next(cx)
        }
    }

    impl<S: Stream> Stream for ::std::panic::AssertUnwindSafe<S> {
        type Item = S::Item;
        type Error = S::Error;

        fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<S::Item>, S::Error> {
            self.0.poll_next(cx)
        }
    }
}
<commit_msg>Fixes for poll_next<commit_after>//! Asynchronous streams
//!
//! See [Asynchronous Programming in Rust](https://aturon.github.io/apr/) for an
//! overview.

use Poll;
use task;

/// A stream of values produced asynchronously.
///
/// If `Future` is an asynchronous version of `Result`, then `Stream` is an
/// asynchronous version of `Iterator`. A stream represents a sequence of
/// value-producing events that occur asynchronously to the caller.
///
/// The trait is modeled after `Future`, but allows `poll_next` to be called
/// even after a value has been produced, yielding `None` once the stream has
/// been fully exhausted.
///
/// # Errors
///
/// Streams, like futures, also bake in errors through an associated `Error`
/// type. An error on a stream **does not terminate the stream**. That is,
/// after one error is received, another value may be received from the same
/// stream (it's valid to keep polling). Thus a stream is somewhat like an
/// `Iterator<Item = Result<T, E>>`, and is always terminated by returning
/// `None`.
pub trait Stream {
    /// Values yielded by the stream.
    type Item;

    /// Errors yielded by the stream.
    type Error;

    /// Attempt to pull out the next value of this stream, returning `None` if
    /// the stream is finished.
    ///
    /// This method, like [`Future::poll`](::future::Future::poll), makes
    /// progress on producing the next value in the stream, but does not block
    /// if one is not available yet; it instead queues the current task to be
    /// woken up when more progress is possible.
    ///
    /// # Return value
    ///
    /// There are several possible return values, each indicating a distinct
    /// stream state:
    ///
    /// - [`Ok(Pending)`](::Async) means that this stream's next value is not
    /// ready yet. Implementations will ensure that the current task will be
    /// notified when the next value may be ready.
    ///
    /// - [`Ok(Ready(Some(val)))`](::Async) means that the stream has
    /// successfully produced a value, `val`, and may produce further values
    /// on subsequent `poll_next` calls.
    ///
    /// - [`Ok(Ready(None))`](::Async) means that the stream has terminated, and
    /// `poll_next` should not be invoked again.
    ///
    /// - `Err(err)` means that the stream encountered an error while trying to
    /// `poll_next`. Subsequent calls to `poll_next` *are* allowed, and may
    /// return further values or errors.
    ///
    /// # Panics
    ///
    /// Once a stream is finished, i.e. `Ready(None)` has been returned, further
    /// calls to `poll_next` may result in a panic or other "bad behavior".  If this
    /// is difficult to guard against then the `fuse` adapter can be used to
    /// ensure that `poll_next` always returns `Ready(None)` in subsequent calls.
    fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error>;
}

impl<'a, S: ?Sized + Stream> Stream for &'a mut S {
    type Item = S::Item;
    type Error = S::Error;

    fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
        (**self).poll_next(cx)
    }
}

if_std! {
    impl<S: ?Sized + Stream> Stream for ::std::boxed::Box<S> {
        type Item = S::Item;
        type Error = S::Error;

        fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error> {
            (**self).poll_next(cx)
        }
    }

    impl<S: Stream> Stream for ::std::panic::AssertUnwindSafe<S> {
        type Item = S::Item;
        type Error = S::Error;

        fn poll_next(&mut self, cx: &mut task::Context) -> Poll<Option<S::Item>, S::Error> {
            self.0.poll_next(cx)
        }
    }
}
<|endoftext|>


<commit_before>#![feature(old_io)]
#![allow(unused_must_use)]

fn main() {
    writeln!(&mut std::old_io::stdio::stderr(), "Hello stderr");
}
<commit_msg>fix stderr example for rust<commit_after>#![feature(old_io)]
#![allow(unused_must_use)]
#![allow(deprecated)]
use std::old_io as io;

// Rust is currently unstable. The core team is
// working a lot on I/O module.
//
// Therefore this example may fail after rebuilding
// the rust image using lastest nightly.

fn main() {
    writeln!(&mut io::stderr(), "Hello stderr");
}
<|endoftext|>


<commit_before>extern crate suppositions;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::ops::Add;
use suppositions::*;
use suppositions::generators::*;

// Hutton's razor as an example.
// Demonstrates recursive generators.

#[derive(Debug, Clone)]
pub enum Expr {
    Lit(u8),
    Add(Box<Expr>, Box<Expr>),
}

impl Add<Expr> for Expr {
    type Output = Expr;
    fn add(self, other: Expr) -> Expr {
        Expr::Add(Box::new(self), Box::new(other))
    }
}

impl Expr {
    fn eval(&self) -> u64 {
        match self {
            &Expr::Lit(n) => n as u64,
            &Expr::Add(ref a, ref b) => a.eval() + b.eval(),
        }
    }
}

fn expr_gen() -> Box<GeneratorObject<Item=Expr>> {
    let lit = u8s().map(Expr::Lit);
    let add = (lazy(expr_gen), lazy(expr_gen)).map(|(a, b)| Expr::Add(Box::new(a), Box::new(b)));

    // In lieu of having weighted choice
    one_of(lit).or(lit).or(add).boxed()
}

#[test]
fn add_adds() {
    env_logger::init().expect("env_logger::init");
    property((expr_gen(), expr_gen()))
        .check(|(a, b)| {
            debug!("Testing: {:?} + {:?}", a,b);
            assert_eq!(a.eval() + b.eval(), (a + b).eval())
        });

}<commit_msg>Try again.<commit_after>extern crate suppositions;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::ops::Add;
use suppositions::*;
use suppositions::generators::*;

// Hutton's razor as an example.
// Demonstrates recursive generators.

#[derive(Debug, Clone)]
pub enum Expr {
    Lit(u8),
    Add(Box<Expr>, Box<Expr>),
}

impl Add<Expr> for Expr {
    type Output = Expr;
    fn add(self, other: Expr) -> Expr {
        Expr::Add(Box::new(self), Box::new(other))
    }
}

impl Expr {
    fn eval(&self) -> u64 {
        match self {
            &Expr::Lit(n) => n as u64,
            &Expr::Add(ref a, ref b) => a.eval() + b.eval(),
        }
    }
}

fn expr_gen() -> Box<GeneratorObject<Item=Expr>> {
    let lit = u8s().map(Expr::Lit);
    let lit2 = u8s().map(Expr::Lit);
    let add = (lazy(expr_gen), lazy(expr_gen)).map(|(a, b)| Expr::Add(Box::new(a), Box::new(b)));

    // In lieu of having weighted choice
    one_of(lit).or(lit2).or(add).boxed()
}

#[test]
fn add_adds() {
    env_logger::init().expect("env_logger::init");
    property((expr_gen(), expr_gen()))
        .check(|(a, b)| {
            debug!("Testing: {:?} + {:?}", a,b);
            assert_eq!(a.eval() + b.eval(), (a + b).eval())
        });

}<|endoftext|>


<commit_before>//! Random number generation

export Rng, rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:copy>(values: ~[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose some(item) randomly, returning none if values is empty
    fn choose_option<T:copy>(values: ~[T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: copy>(v : ~[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:copy>(v: ~[Weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return none;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return some(item.item);
            }
        }
        unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:copy>(v: ~[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        r
    }

    /// Shuffle a vec
    fn shuffle<T:copy>(values: ~[T]) -> ~[T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        return vec::from_mut(m);
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(&&values: ~[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    let c: *rctx;
    new(c: *rctx) { self.c = c; }
    drop { rustrt::rand_free(self.c); }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose(~[1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option(~[]) == none::<int>;
        assert r.choose_option(~[1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option(~[]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Camel case the option type<commit_after>//! Random number generation

export Rng, rng, seed, seeded_rng, Weighted, extensions;
export xorshift, seeded_xorshift;

#[allow(non_camel_case_types)] // runtime type
enum rctx {}

#[abi = "cdecl"]
extern mod rustrt {
    fn rand_seed() -> ~[u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: ~[u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

/// A random number generator
trait Rng {
    /// Return the next random integer
    fn next() -> u32;
}

/// A value with a particular weight compared to other values
type Weighted<T> = { weight: uint, item: T };

/// Extension methods for random number generators
impl Rng {

    /// Return a random int
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    /**
     * Return an int randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    /// Return a random i8
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    /// Return a random i16
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    /// Return a random i32
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    /// Return a random i64
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    /// Return a random uint
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    /**
     * Return a uint randomly chosen from the range [start, end),
     * failing if start >= end
     */
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    /// Return a random u8
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    /// Return a random u16
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    /// Return a random u32
    fn gen_u32() -> u32 {
        self.next()
    }

    /// Return a random u64
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    /// Return a random float in the interval [0,1]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    /// Return a random f32 in the interval [0,1]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    /// Return a random f64 in the interval [0,1]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        const scale : f64 = (u32::max_value as f64) + 1.0f64;
        return ((u1 / scale + u2) / scale + u3) / scale;
    }

    /// Return a random char
    fn gen_char() -> char {
        self.next() as char
    }

    /**
     * Return a char randomly chosen from chars, failing if chars is empty
     */
    fn gen_char_from(chars: ~str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    /// Return a random bool
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    /// Return a bool with a 1 in n chance of true
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    /**
     * Return a random string of the specified length composed of A-Z,a-z,0-9
     */
    fn gen_str(len: uint) -> ~str {
        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                       abcdefghijklmnopqrstuvwxyz\
                       0123456789";
        let mut s = ~"";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    /// Return a random byte string of the specified length
    fn gen_bytes(len: uint) -> ~[u8] {
        do vec::from_fn(len) |_i| {
            self.gen_u8()
        }
    }

    /// Choose an item randomly, failing if values is empty
    fn choose<T:copy>(values: ~[T]) -> T {
        self.choose_option(values).get()
    }

    /// Choose Some(item) randomly, returning None if values is empty
    fn choose_option<T:copy>(values: ~[T]) -> Option<T> {
        if values.is_empty() {
            None
        } else {
            Some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    /**
     * Choose an item respecting the relative weights, failing if the sum of
     * the weights is 0
     */
    fn choose_weighted<T: copy>(v : ~[Weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    /**
     * Choose Some(item) respecting the relative weights, returning none if
     * the sum of the weights is 0
     */
    fn choose_weighted_option<T:copy>(v: ~[Weighted<T>]) -> Option<T> {
        let mut total = 0u;
        for v.each |item| {
            total += item.weight;
        }
        if total == 0u {
            return None;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each |item| {
            so_far += item.weight;
            if so_far > chosen {
                return Some(item.item);
            }
        }
        unreachable();
    }

    /**
     * Return a vec containing copies of the items, in order, where
     * the weight of the item determines how many copies there are
     */
    fn weighted_vec<T:copy>(v: ~[Weighted<T>]) -> ~[T] {
        let mut r = ~[];
        for v.each |item| {
            for uint::range(0u, item.weight) |_i| {
                vec::push(r, item.item);
            }
        }
        r
    }

    /// Shuffle a vec
    fn shuffle<T:copy>(values: ~[T]) -> ~[T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        return vec::from_mut(m);
    }

    /// Shuffle a mutable vec in place
    fn shuffle_mut<T>(&&values: ~[mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

struct RandRes {
    let c: *rctx;
    new(c: *rctx) { self.c = c; }
    drop { rustrt::rand_free(self.c); }
}

impl @RandRes: Rng {
    fn next() -> u32 { return rustrt::rand_next((*self).c); }
}

/// Create a new random seed for seeded_rng
fn seed() -> ~[u8] {
    rustrt::rand_seed()
}

/// Create a random number generator with a system specified seed
fn rng() -> Rng {
    @RandRes(rustrt::rand_new()) as Rng
}

/**
 * Create a random number generator using the specified seed. A generator
 * constructed with a given seed will generate the same sequence of values as
 * all other generators constructed with the same seed. The seed may be any
 * length.
 */
fn seeded_rng(seed: ~[u8]) -> Rng {
    @RandRes(rustrt::rand_new_seeded(seed)) as Rng
}

type XorShiftState = {
    mut x: u32,
    mut y: u32,
    mut z: u32,
    mut w: u32
};

impl XorShiftState: Rng {
    fn next() -> u32 {
        let x = self.x;
        let mut t = x ^ (x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        let w = self.w;
        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
        self.w
    }
}

fn xorshift() -> Rng {
    // constants taken from http://en.wikipedia.org/wiki/Xorshift
    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
}

fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
    {mut x: x, mut y: y, mut z: z, mut w: w} as Rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed2() {
        let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        // Regression test that isaac is actually using the above vector
        let r = ra.next();
        error!("%?", r);
        assert r == 890007737u32 // on x86_64
            || r == 2935188040u32; // on x86
    }

    #[test]
    fn gen_int_range() {
        let r = rand::rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn gen_uint_range_fail() {
        rand::rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose(~[1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option(~[]) == None::<int>;
        assert r.choose_option(~[1, 1, 1]) == Some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
               Some(42);
        assert r.choose_weighted_option(~[
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == Some(43);
        assert r.choose_weighted_option(~[]) == None::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.weighted_vec(~[]) == empty;
        assert r.weighted_vec(~[
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == ~[2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: ~[int] = ~[];
        assert r.shuffle(~[]) == empty;
        assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;
extern crate byteorder;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpStream;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
use std::time::Duration;
use std::option::Option;
//use std::io::Read;
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
//use futures::Future;
use std::sync::{Arc, Mutex};
use std::io::{Error, ErrorKind};
use std::str;
use std::io::Cursor;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

mod userchannel;
mod messaging;
use messaging::*;

fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8>
where R: Read,
{
    let mut buf = vec![];
    let mut chunk = reader.take(bytes_to_read);
    let status = chunk.read_to_end(&mut buf);
    match status {
        Ok(n) => assert_eq!(bytes_to_read as usize, n),
            _ => return vec![]
    }
    buf
 }

fn read_hdr_type(hdr: &[u8]) -> u32 {
    let mut buf = Cursor::new(&hdr[..]);
    let num = buf.read_u32::<BigEndian>().unwrap();
    num >> 24
}

fn read_hdr_len(hdr: &[u8]) -> usize {
    let mut buf = Cursor::new(&hdr[..]);
    let num = buf.read_u32::<BigEndian>().unwrap();
    (num & 0xfff) as usize
}

fn write_hdr(len: usize) -> Vec<u8> {
    let hdr = (('M' as u32) << 24) | len as u32;
    let mut msgv = vec![];
    msgv.write_u32::<BigEndian>(hdr).unwrap();
    msgv
}

fn main() {
    let address = "0.0.0.0:8081";
    let listener = TcpListener::bind(&address).unwrap();
    let mut spawned = HashMap::new();
    let option: Option<Duration> = Some(Duration::from_millis(50));
    let mut cnt = 0;

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();

    for socket in listener.incoming() {
        /* 1. Read incoming msg channel
         * 2. If it does not exist, spawn new thread
         * 3. Send socket to thread
         */
        let mut socket = socket.unwrap();
        let mut stream = socket.try_clone().unwrap();
        let buf = read_n(&stream, 4);
        if read_hdr_type(buf.as_slice()) != 'M' as u32 {
            println!("Incorrect payload type");
            continue;
        }

        println!("Payload len {}", read_hdr_len(buf.as_slice()));
        let buf = read_n(&stream, read_hdr_len(buf.as_slice()) as u64);
        let decoded_msg = messaging::message_decode(buf.as_slice());
        if 0 == decoded_msg.message.len() {
            continue;
        }
        socket.set_nodelay(true);
        socket.set_read_timeout(option);
        if !spawned.contains_key(&decoded_msg.message[1]) {
            let tx = tx.clone();
            //let user = String::from_utf8_lossy(decoded_msg.message[0].clone().as_slice()).into_owned().as_str();
            //println!("Got {}", user);
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: New channel created!");
                let mut users = HashMap::new();
                let mut messages: Vec<Vec<u8>> = Vec::new();
                tx.send(thr_tx.clone()).unwrap();
                loop {
                    let mut removals = Vec::new();
                    match thr_rx.try_recv() {
                        Ok(val) => {
                            let mut thr: TcpStream = val;
                            cnt += 1;
                            println!("Adding {}", cnt);
                            users.insert(cnt, thr.try_clone().unwrap());

                            /* If a new user, all push messages to her */
                            for buf in &messages {
                                println!("Historial msg is {:?}", buf);
                                thr.write(buf.as_slice()).unwrap();
                            }
                        },
                        Err(_) => {}
                    }
                    for (user, thr_socket) in &users {
                        let stream = thr_socket.try_clone().unwrap();
                        let mut buf = read_n(&stream, 4);
                        if 0 == buf.len() {
                            continue;
                        }
                        println!("Got buf len {}", buf.len());
                        if read_hdr_type(buf.as_slice()) != 'M' as u32 {
                            continue;
                        }
                        println!("Ok hdr type");
                        let hdr_len = read_hdr_len(buf.as_slice()) as u64;
                        println!("Hdr_len {}", hdr_len);
                        if 0 == hdr_len {
                            continue;
                        }
                        let payload = read_n(&stream, hdr_len);
                        println!("Payload len {}", payload.len());
                        if payload.len() != (hdr_len as usize) {
                            continue;
                        }
                        buf.extend(payload);
                        for (another_user, mut thr_sock) in &users {
                            if user != another_user {
                                println!("Msg is {:?}", buf);
                                thr_sock.write(buf.as_slice()).unwrap();
                            }
                        }
                        /* Add to local db */
                        messages.push(buf);
                    }
                    for removal in &removals {
                        users.remove(removal);
                    }
                    if cnt > 0 && users.is_empty() {
                        break;
                    }
                }
            });
            let thr_feed = rx.recv().unwrap();
            println!("Channel {}", String::from_utf8_lossy(decoded_msg.message[1].as_slice()).into_owned().as_str());
            spawned.insert(decoded_msg.message[1].clone(), thr_feed);
        }
        let thr_socket = spawned.get_mut(&decoded_msg.message[1]).unwrap();
        thr_socket.send(socket).unwrap();
    }
}
<commit_msg>User and channel removal support.<commit_after>#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;
extern crate byteorder;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpStream;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
use std::time::Duration;
use std::option::Option;
//use std::io::Read;
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
//use futures::Future;
use std::sync::{Arc, Mutex};
use std::io::{Error, ErrorKind};
use std::str;
use std::io::Cursor;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

mod userchannel;
mod messaging;
use messaging::*;

fn read_n<R>(reader: R, bytes_to_read: u64) -> (Result<usize, Error>, Vec<u8>)
where R: Read,
{
    let mut buf = vec![];
    let mut chunk = reader.take(bytes_to_read);
    let status = chunk.read_to_end(&mut buf);
    /*
    match status {
        Ok(n) => assert_eq!(bytes_to_read as usize, n),
        Ok(0) => ,
        Err(_) => return vec![]
    }*/
    (status, buf)
 }

fn read_hdr_type(hdr: &[u8]) -> u32 {
    let mut buf = Cursor::new(&hdr[..]);
    let num = buf.read_u32::<BigEndian>().unwrap();
    num >> 24
}

fn read_hdr_len(hdr: &[u8]) -> usize {
    let mut buf = Cursor::new(&hdr[..]);
    let num = buf.read_u32::<BigEndian>().unwrap();
    (num & 0xfff) as usize
}

fn write_hdr(len: usize) -> Vec<u8> {
    let hdr = (('M' as u32) << 24) | len as u32;
    let mut msgv = vec![];
    msgv.write_u32::<BigEndian>(hdr).unwrap();
    msgv
}

fn main() {
    let address = "0.0.0.0:8081";
    let listener = TcpListener::bind(&address).unwrap();
    let mut spawned = HashMap::new();
    let option: Option<Duration> = Some(Duration::from_millis(50));
    let mut cnt = 0;

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();
    let (removedtx, removedrx) = channel();

    for socket in listener.incoming() {
        /* Check first has anybody removed channels */
        match removedrx.try_recv() {
            Ok(val) => {
                let removed_channel: Vec<u8> = val;
                println!("Removing unused channel {}", String::from_utf8_lossy(removed_channel.as_slice()).into_owned().as_str());
                spawned.remove(&removed_channel);
            },
            Err(_) => {}
        }
        /* 1. Read incoming msg channel
         * 2. If it does not exist, spawn new thread
         * 3. Send socket to thread
         */
        let mut socket = socket.unwrap();
        let mut stream = socket.try_clone().unwrap();
        let tuple = read_n(&stream, 4);
        let status = tuple.0;
        match status {
            Ok(0) => {
               continue;
            },
            Ok(n) => {},
            _ => {
               continue;
            },
        }
        let buf = tuple.1;
        if 0 == buf.len() {
            continue;
        }
        if read_hdr_type(buf.as_slice()) != 'M' as u32 {
            println!("Incorrect payload type");
            continue;
        }
        println!("Payload len {}", read_hdr_len(buf.as_slice()));
        let tuple = read_n(&stream, read_hdr_len(buf.as_slice()) as u64);
        let status = tuple.0;
        match status {
            Ok(0) => {
               continue;
            },
            Ok(n) => {},
            _ => {
               continue;
            },
        }
        let buf = tuple.1;
        let decoded_msg = messaging::message_decode(buf.as_slice());
        if 0 == decoded_msg.message.len() {
            continue;
        }
        socket.set_nodelay(true);
        socket.set_read_timeout(option);
        if !spawned.contains_key(&decoded_msg.message[1]) {
            let tx = tx.clone();
            let removedtx = removedtx.clone();
            let this_channel = decoded_msg.message[1].clone();
            //let user = String::from_utf8_lossy(decoded_msg.message[0].clone().as_slice()).into_owned().as_str();
            //println!("Got {}", user);
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: New channel created!");
                let mut users = HashMap::new();
                let mut messages: Vec<Vec<u8>> = Vec::new();
                tx.send(thr_tx.clone()).unwrap();
                loop {
                    let mut removals = Vec::new();
                    match thr_rx.try_recv() {
                        Ok(val) => {
                            let mut thr: TcpStream = val;
                            cnt += 1;
                            println!("Adding {}", cnt);
                            users.insert(cnt, thr.try_clone().unwrap());

                            /* If a new user, all push messages to her */
                            for buf in &messages {
                                println!("Historial msg is {:?}", buf);
                                thr.write(buf.as_slice()).unwrap();
                            }
                        },
                        Err(_) => {}
                    }
                    for (user, thr_socket) in &users {
                        let stream = thr_socket.try_clone().unwrap();
                        let tuple = read_n(&stream, 4);
                        let status = tuple.0;
                        match status {
                            Ok(0) => {
                                removals.push(user.clone());
                            },
                            _ => {}
                        }
                        let mut buf = tuple.1;
                        if 0 == buf.len() {
                            continue;
                        }
                        println!("Got buf len {}", buf.len());
                        if read_hdr_type(buf.as_slice()) != 'M' as u32 {
                            continue;
                        }
                        println!("Ok hdr type");
                        let hdr_len = read_hdr_len(buf.as_slice()) as u64;
                        println!("Hdr_len {}", hdr_len);
                        if 0 == hdr_len {
                            continue;
                        }
                        let tuple = read_n(&stream, hdr_len);
                        let status = tuple.0;
                        match status {
                            Ok(0) => {
                                removals.push(user.clone());
                            },
                            _ => {}
                        }
                        let payload = tuple.1;
                        println!("Payload len {}", payload.len());
                        if payload.len() != (hdr_len as usize) {
                            continue;
                        }
                        buf.extend(payload);
                        for (another_user, mut thr_sock) in &users {
                            if user != another_user {
                                println!("Msg is {:?}", buf);
                                thr_sock.write(buf.as_slice()).unwrap();
                            }
                        }
                        /* Add to local db */
                        messages.push(buf);
                    }
                    for removal in &removals {
                        println!("Removing user {}", removal);
                        users.remove(removal);
                    }
                    if cnt > 0 && users.is_empty() {
                        removedtx.send(this_channel).unwrap();
                        break;
                    }
                }
            });
            let thr_feed = rx.recv().unwrap();
            println!("Channel {}", String::from_utf8_lossy(decoded_msg.message[1].as_slice()).into_owned().as_str());
            spawned.insert(decoded_msg.message[1].clone(), thr_feed);
        }
        let thr_socket = spawned.get_mut(&decoded_msg.message[1]).unwrap();
        thr_socket.send(socket).unwrap();
    }
}
<|endoftext|>