<commit_before>use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::fs::File;
use std::io::Write;

extern crate tools;
extern crate ipdl_parser;
extern crate getopts;

use getopts::Options;

use tools::file_format::analysis::{read_analysis, read_target, WithLocation, AnalysisTarget, AnalysisKind};

use ipdl_parser::parser;
use ipdl_parser::ast;

type TargetAnalysis = Vec<WithLocation<Vec<AnalysisTarget>>>;

fn get_options_parser() -> Options {
    let mut opts = Options::new();
    opts.optmulti("I", "include",
                  "Additional directory to search for included protocol specifications",
                  "DIR");
    opts.reqopt("d", "outheaders-dir",
                "Directory into which C++ headers analysis data is location.",
                "HDR_DIR");
    opts.reqopt("b", "base-input-prefix",
                "Base directory where IPDL input files are found.",
                "BASE_DIR");
    opts.reqopt("a", "analysis-prefix",
                "Base directory where analysis output files are found.",
                "ANALYSIS_DIR");
    opts
}

fn header_file_name(outheaders_dir: &str, ns: &ast::Namespace, parent_or_child: &str) -> String {
    format!("{}/{}/{}{}.h",
            outheaders_dir,
            ns.namespaces.clone().join("/"),
            ns.name.id,
            parent_or_child)
}

fn mangle_simple(s: &str) -> String {
    format!("{}{}", s.len(), s)
}

fn mangle_nested_name(ns: &Vec<String>, protocol: &str, name: &str) -> String {
    format!("_ZN{}{}{}E",
            ns.iter().map(|id| mangle_simple(&id)).collect::<Vec<_>>().join(""),
            mangle_simple(protocol),
            mangle_simple(name))
}

fn find_analysis<'a>(analysis: &'a TargetAnalysis, mangled: &str) -> &'a AnalysisTarget
{
    for datum in analysis {
        for piece in &datum.data {
            if piece.kind == AnalysisKind::Decl && piece.sym.contains(mangled) {
                return &piece;
            }
        }
    }

    panic!("No analysis target found for {}", mangled);
}

fn output_data(outputf: &mut File, locstr: &str, datum: &AnalysisTarget) {
    write!(outputf, r#"{{"loc": "{}", "target": 1, "kind": "idl", "pretty": "{}", "sym": "{}"}}"#,
           locstr, datum.pretty, datum.sym).unwrap();
    write!(outputf, "\n").unwrap();
    write!(outputf, r#"{{"loc": "{}", "source": 1, "pretty": "{}", "sym": "{}"}}"#,
           locstr, datum.pretty, datum.sym).unwrap();
    write!(outputf, "\n").unwrap();
}

fn output_send_recv(outputf: &mut File,
                    locstr: &str,
                    protocol: &ast::Namespace,
                    message: &ast::MessageDecl,
                    is_ctor: bool,
                    send_side: &str, send_analysis: &TargetAnalysis,
                    recv_side: &str, recv_analysis: &TargetAnalysis)
{
    let send_prefix = if message.send_semantics == ast::SendSemantics::Intr { "Call" } else { "Send" };
    let recv_prefix = if message.send_semantics == ast::SendSemantics::Intr { "Answer" } else { "Recv" };

    let ctor_suffix = if is_ctor { "Constructor" } else { "" };

    let mangled = mangle_nested_name(&protocol.namespaces,
                                     &format!("{}{}", protocol.name.id, send_side),
                                     &format!("{}{}{}", send_prefix, message.name.id, ctor_suffix));
    let send_datum = find_analysis(send_analysis, &mangled);
    output_data(outputf, &locstr, &send_datum);

    let mangled = mangle_nested_name(&protocol.namespaces,
                                     &format!("{}{}", protocol.name.id, recv_side),
                                     &format!("{}{}{}", recv_prefix, message.name.id, ctor_suffix));
    let recv_datum = find_analysis(recv_analysis, &mangled);
    output_data(outputf, &locstr, &recv_datum);
}

fn main() {
    let args : Vec<String> = env::args().collect();

    let opts = get_options_parser();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) },
    };

    if matches.free.is_empty() {
        panic!("Expected at least one IPDL file to be specified.");
    }

    let mut include_dirs = Vec::new();
    for i in matches.opt_strs("I") {
        include_dirs.push(PathBuf::from(i))
    }

    let outheaders_dir = matches.opt_str("d").unwrap();
    let base_dir = matches.opt_str("b").unwrap();
    let analysis_dir = matches.opt_str("a").unwrap();
    let base_path = Path::new(&base_dir);
    let analysis_path = Path::new(&analysis_dir);

    let mut file_names = Vec::new();
    for f in matches.free {
        file_names.push(PathBuf::from(f));
    }

    let maybe_tus = parser::parse(&include_dirs, file_names);

    if maybe_tus.is_none() {
        println!("Specification could not be parsed.");
        return;
    }

    let tus = maybe_tus.unwrap();

    for (_, tu) in tus {
        println!("Analyzing {:?}", tu.file_name);

        let path = tu.file_name.as_path();
        let relative = path.strip_prefix(base_path).unwrap();
        let absolute = analysis_path.join(relative);
        let mut outputf = File::create(absolute).unwrap();

        if let Some((ns, protocol)) = tu.protocol {
            let parent_fname = header_file_name(&outheaders_dir, &ns, "Parent");
            let parent_analysis = read_analysis(&parent_fname, &read_target);
            let child_fname = header_file_name(&outheaders_dir, &ns, "Child");
            let child_analysis = read_analysis(&child_fname, &read_target);

            let is_toplevel = protocol.managers.len() == 0;

            for message in protocol.messages {
                let loc = &message.name.loc;
                let locstr = format!("{}:{}-{}", loc.lineno, loc.colno, loc.colno + message.name.id.len());

                if is_toplevel && message.name.id == "__delete__" {
                    continue;
                }

                let is_ctor = protocol.manages.iter().any(|e| e.id == message.name.id);

                if message.direction == ast::Direction::ToChild || message.direction == ast::Direction::ToParentOrChild {
                    output_send_recv(&mut outputf, &locstr, &ns, &message, is_ctor,
                                     "Parent", &parent_analysis, "Child", &child_analysis);
                }

                if message.direction == ast::Direction::ToParent || message.direction == ast::Direction::ToParentOrChild {
                    output_send_recv(&mut outputf, &locstr, &ns, &message, is_ctor,
                                     "Child", &child_analysis, "Parent", &parent_analysis);
                }
            }
        }
    }
}
<commit_msg>Fix another IPDL error<commit_after>use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::fs::File;
use std::io::Write;

extern crate tools;
extern crate ipdl_parser;
extern crate getopts;

use getopts::Options;

use tools::file_format::analysis::{read_analysis, read_target, WithLocation, AnalysisTarget, AnalysisKind};

use ipdl_parser::parser;
use ipdl_parser::ast;

type TargetAnalysis = Vec<WithLocation<Vec<AnalysisTarget>>>;

fn get_options_parser() -> Options {
    let mut opts = Options::new();
    opts.optmulti("I", "include",
                  "Additional directory to search for included protocol specifications",
                  "DIR");
    opts.reqopt("d", "outheaders-dir",
                "Directory into which C++ headers analysis data is location.",
                "HDR_DIR");
    opts.reqopt("b", "base-input-prefix",
                "Base directory where IPDL input files are found.",
                "BASE_DIR");
    opts.reqopt("a", "analysis-prefix",
                "Base directory where analysis output files are found.",
                "ANALYSIS_DIR");
    opts
}

fn header_file_name(outheaders_dir: &str, ns: &ast::Namespace, parent_or_child: &str) -> String {
    format!("{}/{}/{}{}.h",
            outheaders_dir,
            ns.namespaces.clone().join("/"),
            ns.name.id,
            parent_or_child)
}

fn mangle_simple(s: &str) -> String {
    format!("{}{}", s.len(), s)
}

fn mangle_nested_name(ns: &Vec<String>, protocol: &str, name: &str) -> String {
    format!("_ZN{}{}{}E",
            ns.iter().map(|id| mangle_simple(&id)).collect::<Vec<_>>().join(""),
            mangle_simple(protocol),
            mangle_simple(name))
}

fn find_analysis<'a>(analysis: &'a TargetAnalysis, mangled: &str) -> &'a AnalysisTarget
{
    for datum in analysis {
        for piece in &datum.data {
            if piece.kind == AnalysisKind::Decl && piece.sym.contains(mangled) {
                return &piece;
            }
        }
    }

    panic!("No analysis target found for {}", mangled);
}

fn output_data(outputf: &mut File, locstr: &str, datum: &AnalysisTarget) {
    write!(outputf, r#"{{"loc": "{}", "target": 1, "kind": "idl", "pretty": "{}", "sym": "{}"}}"#,
           locstr, datum.pretty, datum.sym).unwrap();
    write!(outputf, "\n").unwrap();
    write!(outputf, r#"{{"loc": "{}", "source": 1, "pretty": "{}", "sym": "{}"}}"#,
           locstr, datum.pretty, datum.sym).unwrap();
    write!(outputf, "\n").unwrap();
}

fn output_send_recv(outputf: &mut File,
                    locstr: &str,
                    protocol: &ast::Namespace,
                    message: &ast::MessageDecl,
                    is_ctor: bool,
                    send_side: &str, send_analysis: &TargetAnalysis,
                    recv_side: &str, recv_analysis: &TargetAnalysis)
{
    let send_prefix = if message.send_semantics == ast::SendSemantics::Intr { "Call" } else { "Send" };
    let recv_prefix = if message.send_semantics == ast::SendSemantics::Intr { "Answer" } else { "Recv" };

    let ctor_suffix = if is_ctor { "Constructor" } else { "" };

    let mangled = mangle_nested_name(&protocol.namespaces,
                                     &format!("{}{}", protocol.name.id, send_side),
                                     &format!("{}{}{}", send_prefix, message.name.id, ctor_suffix));
    let send_datum = find_analysis(send_analysis, &mangled);
    output_data(outputf, &locstr, &send_datum);

    let mangled = mangle_nested_name(&protocol.namespaces,
                                     &format!("{}{}", protocol.name.id, recv_side),
                                     &format!("{}{}{}", recv_prefix, message.name.id, ctor_suffix));
    let recv_datum = find_analysis(recv_analysis, &mangled);
    output_data(outputf, &locstr, &recv_datum);
}

fn main() {
    let args : Vec<String> = env::args().collect();

    let opts = get_options_parser();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) },
    };

    let mut include_dirs = Vec::new();
    for i in matches.opt_strs("I") {
        include_dirs.push(PathBuf::from(i))
    }

    let outheaders_dir = matches.opt_str("d").unwrap();
    let base_dir = matches.opt_str("b").unwrap();
    let analysis_dir = matches.opt_str("a").unwrap();
    let base_path = Path::new(&base_dir);
    let analysis_path = Path::new(&analysis_dir);

    let mut file_names = Vec::new();
    for f in matches.free {
        file_names.push(PathBuf::from(f));
    }

    let maybe_tus = parser::parse(&include_dirs, file_names);

    if maybe_tus.is_none() {
        println!("Specification could not be parsed.");
        return;
    }

    let tus = maybe_tus.unwrap();

    for (_, tu) in tus {
        println!("Analyzing {:?}", tu.file_name);

        let path = tu.file_name.as_path();
        let relative = path.strip_prefix(base_path).unwrap();
        let absolute = analysis_path.join(relative);
        let mut outputf = File::create(absolute).unwrap();

        if let Some((ns, protocol)) = tu.protocol {
            let parent_fname = header_file_name(&outheaders_dir, &ns, "Parent");
            let parent_analysis = read_analysis(&parent_fname, &read_target);
            let child_fname = header_file_name(&outheaders_dir, &ns, "Child");
            let child_analysis = read_analysis(&child_fname, &read_target);

            let is_toplevel = protocol.managers.len() == 0;

            for message in protocol.messages {
                let loc = &message.name.loc;
                let locstr = format!("{}:{}-{}", loc.lineno, loc.colno, loc.colno + message.name.id.len());

                if is_toplevel && message.name.id == "__delete__" {
                    continue;
                }

                let is_ctor = protocol.manages.iter().any(|e| e.id == message.name.id);

                if message.direction == ast::Direction::ToChild || message.direction == ast::Direction::ToParentOrChild {
                    output_send_recv(&mut outputf, &locstr, &ns, &message, is_ctor,
                                     "Parent", &parent_analysis, "Child", &child_analysis);
                }

                if message.direction == ast::Direction::ToParent || message.direction == ast::Direction::ToParentOrChild {
                    output_send_recv(&mut outputf, &locstr, &ns, &message, is_ctor,
                                     "Child", &child_analysis, "Parent", &parent_analysis);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>generate_error_module!(
    generate_error_types!(ListError, ListErrorKind,
        IOError        => "IO Error",
        FormatError    => "FormatError",
        EntryError     => "EntryError",
        IterationError => "IterationError",
        CLIError       => "No CLI subcommand for listing entries"
    );
);

pub use self::error::ListError;
pub use self::error::ListErrorKind;

<commit_msg>Export MapErrInto trait here as well<commit_after>generate_error_module!(
    generate_error_types!(ListError, ListErrorKind,
        IOError        => "IO Error",
        FormatError    => "FormatError",
        EntryError     => "EntryError",
        IterationError => "IterationError",
        CLIError       => "No CLI subcommand for listing entries"
    );
);

pub use self::error::ListError;
pub use self::error::ListErrorKind;
pub use self::error::MapErrInto;

<|endoftext|>


<commit_before>generate_error_imports!();

generate_error_types!(ViewError, ViewErrorKind,
    Unknown => "Unknown view error"
);

<commit_msg>libimagentryview: use generate_error_module!() macro and reexport generated types<commit_after>generate_error_module!(
    generate_error_types!(ViewError, ViewErrorKind,
        Unknown => "Unknown view error"
    );
);

pub use self::error::ViewError;
pub use self::error::ViewErrorKind;

<|endoftext|>


<commit_before>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Into<$name> for $kindname {

            fn into(self) -> $name {
                $name::new(self, None)
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_result_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.map_err(Box::new).map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(e))
        /// // or:
        /// foo.map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(Box::new(e)))
        /// ```
        ///
        /// with much nicer
        ///
        /// ```ignore
        /// foo.map_err_into(SomeType::SomeErrorKind)
        /// ```
        ///
        pub trait MapErrInto<T> {
            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name>;
        }

        impl<T, E: Error + 'static> MapErrInto<T> for Result<T, E> {

            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name> {
                self.map_err(Box::new)
                    .map_err(|e| error_kind.into_error_with_cause(e))
            }

        }
    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
        pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {}
        generate_custom_error_types!($name, $kindname,
                                     SomeNotExistingTypeWithATypeNameNoOneWillEverChoose,
                                     $($kind => $string),*);

        generate_result_helper!($name, $kindname);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
    pub struct CustomData {
        pub test: i32,
        pub othr: i64,
    }

    generate_error_imports!();

    generate_custom_error_types!(CustomTestError, CustomTestErrorKind,
        CustomData,
        CustomErrorKindA => "customerrorkind a",
        CustomErrorKindB => "customerrorkind B");

    impl CustomTestError {
        pub fn test(&self) -> i32 {
            match self.custom_data {
                Some(t) => t.test,
                None => 0,
            }
        }

        pub fn bar(&self) -> i64 {
            match self.custom_data {
                Some(t) => t.othr,
                None => 0,
            }
        }
    }

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }
}
<commit_msg>Add Option helper<commit_after>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Into<$name> for $kindname {

            fn into(self) -> $name {
                $name::new(self, None)
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_result_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.map_err(Box::new).map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(e))
        /// // or:
        /// foo.map_err(|e| SomeType::SomeErrorKind.into_error_with_cause(Box::new(e)))
        /// ```
        ///
        /// with much nicer
        ///
        /// ```ignore
        /// foo.map_err_into(SomeType::SomeErrorKind)
        /// ```
        ///
        pub trait MapErrInto<T> {
            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name>;
        }

        impl<T, E: Error + 'static> MapErrInto<T> for Result<T, E> {

            fn map_err_into(self, error_kind: $kindname) -> Result<T, $name> {
                self.map_err(Box::new)
                    .map_err(|e| error_kind.into_error_with_cause(e))
            }

        }
    }
}

#[macro_export]
macro_rules! generate_option_helper {
    (
        $name: ident,
        $kindname: ident
    ) => {
        /// Trait to replace
        ///
        /// ```ignore
        /// foo.ok_or(SomeType::SomeErrorKind.into_error())
        /// ```
        ///
        /// with
        ///
        /// ```ignore
        /// foo.ok_or_errkind(SomeType::SomeErrorKind)
        /// ```
        pub trait OkOrErr<T> {
            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name>;
        }

        impl<T> OkOrErr<T> for Option<T> {

            fn ok_or_errkind(self, kind: $kindname) -> Result<T, $name> {
                self.ok_or(kind.into_error())
            }

        }
    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
        pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {}
        generate_custom_error_types!($name, $kindname,
                                     SomeNotExistingTypeWithATypeNameNoOneWillEverChoose,
                                     $($kind => $string),*);

        generate_result_helper!($name, $kindname);
        generate_option_helper!($name, $kindname);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
    pub struct CustomData {
        pub test: i32,
        pub othr: i64,
    }

    generate_error_imports!();

    generate_custom_error_types!(CustomTestError, CustomTestErrorKind,
        CustomData,
        CustomErrorKindA => "customerrorkind a",
        CustomErrorKindB => "customerrorkind B");

    impl CustomTestError {
        pub fn test(&self) -> i32 {
            match self.custom_data {
                Some(t) => t.test,
                None => 0,
            }
        }

        pub fn bar(&self) -> i64 {
            match self.custom_data {
                Some(t) => t.othr,
                None => 0,
            }
        }
    }

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::convert;
use crate::ops::{self, ControlFlow};
use crate::result::Result;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Changes the ready value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map<U, F>(self, f: F) -> Poll<U>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if this is `Poll::Ready`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if this is `Poll::Pending`
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Changes the success value of this `Poll` with the closure provided.
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Changes the error value of this `Poll` with the closure provided.
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    /// Convert to a `Ready` variant.
    ///
    /// # Example
    ///
    /// ```
    /// # use core::task::Poll;
    /// assert_eq!(Poll::from(true), Poll::Ready(true));
    /// ```
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
    type Output = Poll<T>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(Ok)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
            Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Err(From::from(e))),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
    type Output = Poll<Option<T>>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(|x| x.map(Ok))
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
            Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
    for Poll<Option<Result<T, F>>>
{
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Some(Err(From::from(e)))),
        }
    }
}
<commit_msg>Auto merge of #86598 - yoshuawuyts:poll-method-docs, r=JohnTitor<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::convert;
use crate::ops::{self, ControlFlow};
use crate::result::Result;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
    ///
    /// # Examples
    ///
    /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original:
    ///
    /// [`String`]: ../../std/string/struct.String.html
    /// ```
    /// # use core::task::Poll;
    /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
    /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
    /// let poll_some_len = poll_some_string.map(|s| s.len());
    ///
    /// assert_eq!(poll_some_len, Poll::Ready(13));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map<U, F>(self, f: F) -> Poll<U>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if the poll is a [`Poll::Ready`] value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_ready(), true);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_ready(), false);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if the poll is a [`Pending`] value.
    ///
    /// [`Pending`]: Poll::Pending
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_pending(), false);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_pending(), true);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
    /// function to a contained `Poll::Ready(Ok)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Ok(144)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
    /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Err(0)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
    /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
    /// leaving all other variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
    /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
    /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
    /// untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Some(Err(0))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    /// Convert to a `Ready` variant.
    ///
    /// # Example
    ///
    /// ```
    /// # use core::task::Poll;
    /// assert_eq!(Poll::from(true), Poll::Ready(true));
    /// ```
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
    type Output = Poll<T>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(Ok)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
            Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Err(From::from(e))),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
    type Output = Poll<Option<T>>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(|x| x.map(Ok))
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
            Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
    for Poll<Option<Result<T, F>>>
{
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Some(Err(From::from(e)))),
        }
    }
}
<|endoftext|>


<commit_before>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "none")]
pub type c_size_t = usize;

/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "none")]
pub type c_ssize_t = isize;
<commit_msg>Reference tracking issue<commit_after>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;

/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ssize_t = isize;
<|endoftext|>


<commit_before>use drop_bomb::DropBomb;

use crate::ast;
use crate::ast::SyntaxKind;
use crate::grammar;
use crate::lexer::tokenize;
use crate::parser::builder::SyntaxTreeBuilder;
use crate::parser::event::{Event, EventSink};
use crate::parser::input::ParserInput;
use crate::parser::input::SyntaxKindBase;
use crate::parser::input::TokenBase;
use crate::token::Token;
use crate::token::TokenType;
use rowan::WalkEvent;
use std::marker::PhantomData;

mod builder;
mod event;
mod input;

// TODO: This is largely inspired by the rust parser in rust-analyzer's ra_syntax crate.
//       Could the common code be extracted out into a generic parser, similar to IntelliJ's
//       PsiParser interface?

/// A recursive-descent parser that emits output as parse events denoting where syntax tree nodes
/// begin, allowing the parser and construction of the AST structure to evolve separately.
///
/// This parser is not aware of trivia tokens (e.g. doc comments, whitespace) and instead deals
/// solely with module structure. For details on reconciling whitespace and documentation with
/// AST nodes see the [EventProcessor] in the [:event] module.
pub struct Parser<'a, K: SyntaxKindBase, T: TokenBase<K>> {
    events: Vec<Event<K>>,
    input: ParserInput<'a, K, T>,
    pos: usize,
}

impl<'a, K: SyntaxKindBase, T: TokenBase<K>> Parser<'a, K, T> {
    pub fn new(input: ParserInput<'a, K, T>) -> Self {
        Parser {
            events: vec![],
            input,
            pos: 0,
        }
    }

    /// Check if the parser is currently positioned at the [expected] type.
    pub fn at<E>(&self, expected: E) -> bool
    where
        E: Into<K>,
    {
        self.current() == expected.into()
    }

    /// Check if the parser is currently positioned at the expected node with
    /// matching text.
    pub fn at_text<S>(&self, text: S) -> bool
    where
        S: AsRef<str>,
    {
        self.current_text() == text.as_ref()
    }

    /// Advance the position of the parser within the token stream and produce an event
    /// for the current leaf.
    pub fn bump(&mut self) {
        self.events.push(Event::Leaf(self.current()));
        self.pos += 1;
    }

    /// Advance the position of the parser within the token stream and produce and event
    /// for the current leaf, but remap it to the given [kind].
    pub fn bump_as<F>(&mut self, kind: F)
    where
        F: Into<K>,
    {
        self.events.push(Event::Leaf(kind.into()));
        self.pos += 1;
    }

    /// Get the type of token the parser is currently at.
    pub fn current(&self) -> K {
        self.nth(0)
    }

    /// Get the text of the token the parser is currently at.
    pub fn current_text(&self) -> &'a str {
        self.nth_text(0)
    }

    /// Check if the parser is currently positioned at the [expected] type and consume the token,
    /// advancing the parsers position.
    pub fn eat<E>(&mut self, expected: E) -> bool
    where
        E: Into<K>,
    {
        if self.at(expected) {
            self.bump();
            return true;
        }

        return false;
    }

    /// Notify the parser that an error occurred at the given position with [text] as the error
    /// message.
    pub fn error<S>(&mut self, text: S)
    where
        S: AsRef<str>,
    {
    }

    /// Check if the parser is currently positioned at the [expected] type, consuming it and
    /// emitting an error if the current token doesn't match what is expected.
    pub fn expect<E>(&mut self, expected: E)
    where
        E: Into<K>,
    {
        let kind = expected.into();

        if !self.eat(kind) {
            self.error(format!("expected {:#?}", kind));
        }
    }

    /// Check if the parser is currently positioned at a token type that matches
    /// any of the expected [items], consuming the token and emitting an
    /// error if the current token doesn't match any of the inputs.
    pub fn expect_one_of<E>(&mut self, items: Vec<E>)
    where
        E: Into<K>,
    {
        let current_kind = self.current();
        let kinds: Vec<K> = items.into_iter().map(|item| item.into()).collect();

        if kinds.iter().any(|k| *k == current_kind) {
            self.bump();
        } else {
            self.error(format!("expected one of (todo)"));
        }
    }

    /// Check if the parser is currently positioned at a token has text matching
    /// any of the expected [items], consuming the token and emitting an error
    /// if the current token text doesn't match any of the inputs.
    pub fn expect_one_of_str<S: Into<String>>(&mut self, items: Vec<S>) {
        let current_text = self.current_text();
        let strs: Vec<String> = items.into_iter().map(|item| item.into()).collect();

        if strs.iter().any(|str| *str == current_text) {
            self.bump();
        } else {
            self.error(format!("expected one of (todo)"));
        }
    }

    /// Create a new empty marker at the parsers current position.
    pub fn mark(&mut self) -> Marker<K, T> {
        self.events.push(Event::BeginMarker);
        Marker::new(self.events.len() - 1)
    }

    /// Get the `nth` lookahead token type, offset from the parsers current position.
    pub fn nth(&self, offset: usize) -> K {
        self.input.kind(self.pos + offset)
    }

    /// Get the `nth` lookahead token text, offset from the parsers current position.
    pub fn nth_text(&self, offset: usize) -> &'a str {
        self.input.text(self.pos + offset)
    }
}

pub struct Marker<K: SyntaxKindBase, T: TokenBase<K>> {
    pos: usize,
    bomb: DropBomb,
    _phantom_kind: PhantomData<K>,
    _phantom_token: PhantomData<T>,
}

impl<K: SyntaxKindBase, T: TokenBase<K>> Marker<K, T> {
    pub fn new(pos: usize) -> Self {
        Marker {
            pos,
            bomb: DropBomb::new(
                "A marker must be completed or abandoned before it goes out of scope",
            ),
            _phantom_kind: PhantomData,
            _phantom_token: PhantomData,
        }
    }

    pub fn abandon(mut self, parser: &mut Parser<K, T>) {
        match &mut parser.events[self.pos] {
            evt @ Event::BeginMarker => *evt = Event::Tombstone,
            e => unreachable!("trying to abandon a {:#?} marker", e)
        };

        if self.pos == parser.events.len() - 1 {
            parser.events.pop();
        }

        self.bomb.defuse()
    }

    pub fn complete(mut self, parser: &mut Parser<K, T>, kind: K) -> CompletedMarker<K, T> {
        match parser.events[self.pos] {
            ref mut evt @ Event::BeginMarker => *evt = Event::Begin(kind, None),
            _ => unreachable!(),
        };

        parser.events.push(Event::End);
        self.bomb.defuse();

        CompletedMarker::new(kind, self.pos)
    }
}

pub struct CompletedMarker<K: SyntaxKindBase, T: TokenBase<K>> {
    kind: K,
    pos: usize,
    _phantom_token: PhantomData<T>,
}

impl<K: SyntaxKindBase, T: TokenBase<K>> CompletedMarker<K, T> {
    pub fn new(kind: K, pos: usize) -> Self {
        CompletedMarker {
            kind,
            pos,
            _phantom_token: PhantomData,
        }
    }

    pub fn precede(self, p: &mut Parser<K, T>) -> Marker<K, T> {
        let m = p.mark();

        match p.events[self.pos] {
            Event::Begin(_, ref mut forward_parent) => {
                *forward_parent = Some(m.pos - self.pos);
            }
            _ => unreachable!(),
        }

        m
    }
}

pub fn parse_file(text: &str) -> ast::SourceFileNode {
    let (node, errors) = parse(text, builder::SyntaxTreeBuilder::new(), grammar::root);
    let root = ast::SyntaxNode::new(node, errors);

    assert_eq!(root.kind(), ast::SyntaxKind::SourceFile);

    ast::SourceFileNode { syntax: root }
}

pub fn parse<S: EventSink<SyntaxKind>>(
    text: &str,
    sink: S,
    parser: fn(&mut Parser<SyntaxKind, Token>),
) -> S::Output {
    let tokens = tokenize(text);
    let input = ParserInput::new(text, &tokens);
    let mut parser_api = Parser::new(input);
    parser(&mut parser_api);

    event::EventProcessor::new(text, &tokens, sink, &mut parser_api.events).process()
}

pub type CspParser<'a> = Parser<'a, SyntaxKind, Token>;

impl<'a> CspParser<'a> {
    pub fn at_kw(&self) -> bool {
        self.at(TokenType::Name) || self.at(TokenType::IfKw) || self.at(TokenType::ElseKw)
    }
}
<commit_msg>Fix crashes resulting from the parser hitting EOF<commit_after>use drop_bomb::DropBomb;

use crate::ast;
use crate::ast::SyntaxKind;
use crate::grammar;
use crate::lexer::tokenize;
use crate::parser::builder::SyntaxTreeBuilder;
use crate::parser::event::{Event, EventSink};
use crate::parser::input::ParserInput;
use crate::parser::input::SyntaxKindBase;
use crate::parser::input::TokenBase;
use crate::token::Token;
use crate::token::TokenType;
use rowan::WalkEvent;
use std::marker::PhantomData;

mod builder;
mod event;
mod input;

// TODO: This is largely inspired by the rust parser in rust-analyzer's ra_syntax crate.
//       Could the common code be extracted out into a generic parser, similar to IntelliJ's
//       PsiParser interface?

/// A recursive-descent parser that emits output as parse events denoting where syntax tree nodes
/// begin, allowing the parser and construction of the AST structure to evolve separately.
///
/// This parser is not aware of trivia tokens (e.g. doc comments, whitespace) and instead deals
/// solely with module structure. For details on reconciling whitespace and documentation with
/// AST nodes see the [EventProcessor] in the [:event] module.
pub struct Parser<'a, K: SyntaxKindBase, T: TokenBase<K>> {
    events: Vec<Event<K>>,
    input: ParserInput<'a, K, T>,
    pos: usize,
}

impl<'a, K: SyntaxKindBase, T: TokenBase<K>> Parser<'a, K, T> {
    pub fn new(input: ParserInput<'a, K, T>) -> Self {
        Parser {
            events: vec![],
            input,
            pos: 0,
        }
    }

    /// Check if the parser is currently positioned at the [expected] type.
    pub fn at<E>(&self, expected: E) -> bool
    where
        E: Into<K>,
    {
        self.current() == expected.into()
    }

    /// Check if the parser is currently positioned at the expected node with
    /// matching text.
    pub fn at_text<S>(&self, text: S) -> bool
    where
        S: AsRef<str>,
    {
        self.current_text() == text.as_ref()
    }

    /// Advance the position of the parser within the token stream and produce an event
    /// for the current leaf.
    pub fn bump(&mut self) {
        if self.current() == K::eof() {
            return;
        }

        self.events.push(Event::Leaf(self.current()));
        self.pos += 1;
    }

    /// Advance the position of the parser within the token stream and produce and event
    /// for the current leaf, but remap it to the given [kind].
    pub fn bump_as<F>(&mut self, kind: F)
    where
        F: Into<K>,
    {
        self.events.push(Event::Leaf(kind.into()));
        self.pos += 1;
    }

    /// Get the type of token the parser is currently at.
    pub fn current(&self) -> K {
        self.nth(0)
    }

    /// Get the text of the token the parser is currently at.
    pub fn current_text(&self) -> &'a str {
        self.nth_text(0)
    }

    /// Check if the parser is currently positioned at the [expected] type and consume the token,
    /// advancing the parsers position.
    pub fn eat<E>(&mut self, expected: E) -> bool
    where
        E: Into<K>,
    {
        if self.at(expected) {
            self.bump();
            return true;
        }

        return false;
    }

    /// Notify the parser that an error occurred at the given position with [text] as the error
    /// message.
    pub fn error<S>(&mut self, text: S)
    where
        S: AsRef<str>,
    {
    }

    /// Check if the parser is currently positioned at the [expected] type, consuming it and
    /// emitting an error if the current token doesn't match what is expected.
    pub fn expect<E>(&mut self, expected: E)
    where
        E: Into<K>,
    {
        let kind = expected.into();

        if !self.eat(kind) {
            self.error(format!("expected {:#?}", kind));
        }
    }

    /// Check if the parser is currently positioned at a token type that matches
    /// any of the expected [items], consuming the token and emitting an
    /// error if the current token doesn't match any of the inputs.
    pub fn expect_one_of<E>(&mut self, items: Vec<E>)
    where
        E: Into<K>,
    {
        let current_kind = self.current();
        let kinds: Vec<K> = items.into_iter().map(|item| item.into()).collect();

        if kinds.iter().any(|k| *k == current_kind) {
            self.bump();
        } else {
            self.error(format!("expected one of (todo)"));
        }
    }

    /// Check if the parser is currently positioned at a token has text matching
    /// any of the expected [items], consuming the token and emitting an error
    /// if the current token text doesn't match any of the inputs.
    pub fn expect_one_of_str<S: Into<String>>(&mut self, items: Vec<S>) {
        let current_text = self.current_text();
        let strs: Vec<String> = items.into_iter().map(|item| item.into()).collect();

        if strs.iter().any(|str| *str == current_text) {
            self.bump();
        } else {
            self.error(format!("expected one of (todo)"));
        }
    }

    /// Create a new empty marker at the parsers current position.
    pub fn mark(&mut self) -> Marker<K, T> {
        self.events.push(Event::BeginMarker);
        Marker::new(self.events.len() - 1)
    }

    /// Get the `nth` lookahead token type, offset from the parsers current position.
    pub fn nth(&self, offset: usize) -> K {
        self.input.kind(self.pos + offset)
    }

    /// Get the `nth` lookahead token text, offset from the parsers current position.
    pub fn nth_text(&self, offset: usize) -> &'a str {
        self.input.text(self.pos + offset)
    }
}

pub struct Marker<K: SyntaxKindBase, T: TokenBase<K>> {
    pos: usize,
    bomb: DropBomb,
    _phantom_kind: PhantomData<K>,
    _phantom_token: PhantomData<T>,
}

impl<K: SyntaxKindBase, T: TokenBase<K>> Marker<K, T> {
    pub fn new(pos: usize) -> Self {
        Marker {
            pos,
            bomb: DropBomb::new(
                "A marker must be completed or abandoned before it goes out of scope",
            ),
            _phantom_kind: PhantomData,
            _phantom_token: PhantomData,
        }
    }

    pub fn abandon(mut self, parser: &mut Parser<K, T>) {
        match &mut parser.events[self.pos] {
            evt @ Event::BeginMarker => *evt = Event::Tombstone,
            e => unreachable!("trying to abandon a {:#?} marker", e)
        };

        if self.pos == parser.events.len() - 1 {
            parser.events.pop();
        }

        self.bomb.defuse()
    }

    pub fn complete(mut self, parser: &mut Parser<K, T>, kind: K) -> CompletedMarker<K, T> {
        match parser.events[self.pos] {
            ref mut evt @ Event::BeginMarker => *evt = Event::Begin(kind, None),
            _ => unreachable!(),
        };

        parser.events.push(Event::End);
        self.bomb.defuse();

        CompletedMarker::new(kind, self.pos)
    }
}

pub struct CompletedMarker<K: SyntaxKindBase, T: TokenBase<K>> {
    kind: K,
    pos: usize,
    _phantom_token: PhantomData<T>,
}

impl<K: SyntaxKindBase, T: TokenBase<K>> CompletedMarker<K, T> {
    pub fn new(kind: K, pos: usize) -> Self {
        CompletedMarker {
            kind,
            pos,
            _phantom_token: PhantomData,
        }
    }

    pub fn precede(self, p: &mut Parser<K, T>) -> Marker<K, T> {
        let m = p.mark();

        match p.events[self.pos] {
            Event::Begin(_, ref mut forward_parent) => {
                *forward_parent = Some(m.pos - self.pos);
            }
            _ => unreachable!(),
        }

        m
    }
}

pub fn parse_file(text: &str) -> ast::SourceFileNode {
    let (node, errors) = parse(text, builder::SyntaxTreeBuilder::new(), grammar::root);
    let root = ast::SyntaxNode::new(node, errors);

    assert_eq!(root.kind(), ast::SyntaxKind::SourceFile);

    ast::SourceFileNode { syntax: root }
}

pub fn parse<S: EventSink<SyntaxKind>>(
    text: &str,
    sink: S,
    parser: fn(&mut Parser<SyntaxKind, Token>),
) -> S::Output {
    let tokens = tokenize(text);
    let input = ParserInput::new(text, &tokens);
    let mut parser_api = Parser::new(input);
    parser(&mut parser_api);

    event::EventProcessor::new(text, &tokens, sink, &mut parser_api.events).process()
}

pub type CspParser<'a> = Parser<'a, SyntaxKind, Token>;

impl<'a> CspParser<'a> {
    pub fn at_kw(&self) -> bool {
        self.at(TokenType::Name) || self.at(TokenType::IfKw) || self.at(TokenType::ElseKw)
    }
}
<|endoftext|>


<commit_before>use std::time::{SystemTime, UNIX_EPOCH, Duration, Instant};
use tokio::timer::Interval;
use tokio::prelude::*;
use std::str::FromStr;
use std::sync::Arc;

use blockchain::*;
use constants;
use crypto::*;
use asset::*;
use tx::*;

pub struct Producer {
    chain: Arc<Blockchain>,
    minter: KeyPair,
    staker: PublicKey
}

impl Producer {

    pub fn new(chain: Arc<Blockchain>,
                minter: KeyPair,
                staker: PublicKey) -> Producer {
        Producer {
            chain,
            minter,
            staker
        }
    }

    pub fn start_timer(self) {
        let dur = Duration::from_millis(constants::BLOCK_PROD_TIME);
        let at = Instant::now() + dur;
        ::tokio::spawn(Interval::new(at, dur).take_while(|_| {
            Ok(true)
        }).for_each(move |_| {
            Producer::produce(&self);
            Ok(())
        }).map_err(|err| {
            error!("Unknown error in producer: {:?}", err);
        }));
    }

    fn produce(&self) {
        let blockchain = &*self.chain;

        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as u32;
        let transactions = vec![
            TxVariant::RewardTx(RewardTx {
                base: Tx {
                    tx_type: TxType::REWARD,
                    fee: Asset::from_str("0 GOLD").unwrap(),
                    timestamp,
                    signature_pairs: Vec::new()
                },
                to: self.staker.clone(),
                rewards: vec![
                    Asset::from_str("1 GOLD").unwrap(),
                    Asset::from_str("100 SILVER").unwrap()
                ]
            })
        ];

        let head = blockchain.get_chain_head();
        let block = head.new_child(transactions).sign(&self.minter);

        let height = block.height;
        let tx_len = block.transactions.len();

        blockchain.insert_block(block).unwrap();
        info!("Produced block at height {} with {} txs", height, tx_len);
    }
}
<commit_msg>Cleanup producer<commit_after>use std::time::{SystemTime, UNIX_EPOCH, Duration, Instant};
use tokio::timer::Interval;
use tokio::prelude::*;
use std::str::FromStr;
use std::sync::Arc;

use blockchain::*;
use constants;
use crypto::*;
use asset::*;
use tx::*;

pub struct Producer {
    chain: Arc<Blockchain>,
    minter: KeyPair,
    staker: PublicKey
}

impl Producer {

    pub fn new(chain: Arc<Blockchain>,
                minter: KeyPair,
                staker: PublicKey) -> Producer {
        Producer {
            chain,
            minter,
            staker
        }
    }

    pub fn start_timer(self) {
        let dur = Duration::from_millis(constants::BLOCK_PROD_TIME);
        let at = Instant::now() + dur;
        ::tokio::spawn(Interval::new(at, dur).for_each(move |_| {
            self.produce();
            Ok(())
        }).map_err(|err| {
            error!("Timer error in producer: {:?}", err);
        }));
    }

    fn produce(&self) {
        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as u32;
        let transactions = vec![
            TxVariant::RewardTx(RewardTx {
                base: Tx {
                    tx_type: TxType::REWARD,
                    fee: Asset::from_str("0 GOLD").unwrap(),
                    timestamp,
                    signature_pairs: Vec::new()
                },
                to: self.staker.clone(),
                rewards: vec![
                    Asset::from_str("1 GOLD").unwrap(),
                    Asset::from_str("100 SILVER").unwrap()
                ]
            })
        ];

        let head = self.chain.get_chain_head();
        let block = head.new_child(transactions).sign(&self.minter);

        let height = block.height;
        let tx_len = block.transactions.len();

        self.chain.insert_block(block).unwrap();
        info!("Produced block at height {} with {} txs", height, tx_len);
    }
}
<|endoftext|>