<commit_before>use cargo::core::{Workspace, Source};
use cargo::sources::PathSource;
use syntex_syntax::attr;
use syntex_syntax::visit::{self, Visitor, FnKind};
use syntex_syntax::codemap::{CodeMap, Span, FilePathMapping};
use syntex_syntax::ast::{NodeId, Mac, Attribute, Stmt, StmtKind, FnDecl, Mod,
    StructField, Block, Item, ItemKind};
use syntex_syntax::parse::{self, ParseSess};
use syntex_syntax::errors::Handler;
use syntex_syntax::errors::emitter::ColorConfig;
use std::path::PathBuf;
use std::ffi::OsStr;
use std::rc::Rc;
use std::ops::Deref;
use config::Config;

struct IgnoredLines<'a> {
    lines: Vec<usize>,
    codemap: &'a CodeMap,
    config: &'a Config,
    started: bool,
}

/// Returns a list of files and line numbers to ignore (not indexes!)
pub fn get_lines_to_ignore(project: &Workspace, config: &Config) -> Vec<(PathBuf, usize)> {
    let mut result: Vec<(PathBuf, usize)> = Vec::new();

    let pkg = project.current().unwrap();
    let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), project.config());
    // If this fails we should just iterate over no files. No need to care.
    let _ = src.update();

    let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
    let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
    let parse_session = ParseSess::with_span_handler(handler, codemap.clone());

    for file in src.list_files(&pkg).unwrap().iter() {
        if !(config.ignore_tests && file.starts_with(project.root().join("tests"))) {
            if file.extension() == Some(OsStr::new("rs")) {
                // Rust source file
                let mut parser = parse::new_parser_from_file(&parse_session, &file);
                if let Ok(krate) = parser.parse_crate_mod() {
                    let mut visitor = IgnoredLines::from_session(&parse_session, config);
                    visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
                    result.append(&mut visitor.lines.iter()
                                                    .map(|x| (file.to_path_buf(), *x))
                                                    .collect::<Vec<_>>());
                }
            }
        }
    }
    result
}

impl<'a> IgnoredLines<'a> {
    /// Construct a new ignored lines object for the given project
    fn from_session(session: &'a ParseSess, config: &'a Config) -> IgnoredLines<'a> {
        IgnoredLines {
            lines: vec![],
            codemap: session.codemap(),
            config: config,
            started: false
        }
    }

    /// Add lines to the line ignore list
    fn ignore_lines(&mut self, span: Span) {
        if let Ok(s) = self.codemap.span_to_lines(span) {
            for line in &s.lines {
                // Line number is index+1
                self.lines.push(line.line_index + 1);
            }
        }
    }

    /// Looks for #[cfg(test)] attribute.
    fn contains_cfg_test(&mut self, attrs: &[Attribute]) -> bool {
        attrs.iter()
             .filter(|x| x.path == "cfg")
             .filter_map(|x| x.meta_item_list())
             .flat_map(|x| x)
             .any(|x| {
                 if let Some(w) = x.word() {
                    w.name().as_str() == "test"
                 } else {
                     false
                 }
             })
    }

    /// This function finds ignorable lines within actual coverable code.
    /// As opposed to other functions which find isolated lines that aren't
    /// executed or lines filtered by the user. These lines are things like
    /// close braces that are within coverable code but not coverable.
    fn find_ignorable_lines(&mut self, span: Span) {
        if let Ok(l) = self.codemap.span_to_lines(span) {
            for line in &l.lines {
                if let Some(s) = l.file.get_line(line.line_index) {
                    // Is this one of those pointless {, } or }; only lines?
                    if !s.chars().any(|x| !"{}[];\t ,".contains(x)) {
                        self.lines.push(line.line_index + 1);
                    }
                }
            }
        }
    }
}

impl<'v, 'a> Visitor<'v> for IgnoredLines<'a> {

    fn visit_item(&mut self, i: &'v Item) {
        match i.node {
            ItemKind::ExternCrate(..) => self.ignore_lines(i.span),
            ItemKind::Fn(_, _, _, _, _, ref block) => {
                if attr::contains_name(&i.attrs, "test") && self.config.ignore_tests {
                    self.ignore_lines(i.span);
                    self.ignore_lines(block.deref().span);
                }
            },
            _ => {},
        }
        visit::walk_item(self, i);
    }

    fn visit_mod(&mut self, m: &'v Mod, s: Span, _attrs: &[Attribute], _n: NodeId) {
        // We want to limit ourselves to only this source file.
        // This avoids repeated hits and issues where there are multiple compilation targets
        if self.started == false {
            self.started = true;
            visit::walk_mod(self, m);
        } else {
            // Needs to be more advanced - cope with mod { .. } in file.
            // Also if mod is cfg(test) and --ignore-tests ignore contents!
            if let Ok(fl) = self.codemap.span_to_lines(s) {
                if fl.lines.len() > 1 {
                    if self.config.ignore_tests && self.contains_cfg_test(_attrs) {
                        self.ignore_lines(s);
                    }
                    visit::walk_mod(self, m);
                } else {
                    // one line mod, so either referencing another file or something
                    // not worth covering.
                    self.ignore_lines(s);
                }
            }
        }
    }

    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, s: Span, _: NodeId) {
        visit::walk_fn(self, fk, fd, s);
    }

    fn visit_stmt(&mut self, s: &Stmt) {
        match s.node {
            StmtKind::Mac(_) => visit::walk_stmt(self, s),
            _ => {},
        }
    }

    fn visit_mac(&mut self, mac: &Mac) {
        // Use this to ignore unreachable lines
        let mac_text = &format!("{}", mac.node.path)[..];
        // TODO unimplemented should have extra logic to exclude the
        // function from coverage
        match mac_text {
            "unimplemented" => self.ignore_lines(mac.span),
            "unreachable" => self.ignore_lines(mac.span),
            _ => {},
        }
        visit::walk_mac(self, mac);
    }

    /// Ignores attributes which may get identified as coverable lines.
    fn visit_attribute(&mut self, attr: &Attribute) {
        if attr.check_name("derive") {
            self.ignore_lines(attr.span);
        }
    }

    /// Struct fields are mistakenly identified as instructions and uncoverable.
    fn visit_struct_field(&mut self, s: &'v StructField) {
        self.ignore_lines(s.span);
        visit::walk_struct_field(self, s);
    }

    fn visit_block(&mut self, b: &'v Block) {
        self.find_ignorable_lines(b.span);
        visit::walk_block(self, b);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use syntex_syntax::parse::filemap_to_parser;
    use syntex_syntax::parse::parser::Parser;

    struct TestContext {
        conf: Config,
        codemap: Rc<CodeMap>,
        parse_session: ParseSess
    }

    impl TestContext {
        fn generate_parser(&self, filename: &str, src_string: &str) -> Parser {
            let filemap = self.codemap.new_filemap(filename.to_string(),
                                                   src_string.to_string());
            filemap_to_parser(&self.parse_session, filemap)
        }
    }

    impl Default for TestContext {
        fn default() -> TestContext {
            let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
            let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
            let parse_session = ParseSess::with_span_handler(handler, codemap.clone());
            TestContext {
                conf: Config::default(),
                codemap: codemap,
                parse_session: parse_session
            }
        }
    }

    fn parse_crate(ctx: &TestContext, parser: &mut Parser) -> Vec<usize>  {
        let krate = parser.parse_crate_mod();
        assert!(krate.is_ok());
        let krate = krate.unwrap();
        let mut visitor = IgnoredLines::from_session(&ctx.parse_session, &ctx.conf);
        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
        visitor.lines
    }

    #[test]
    fn filter_struct_members() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("struct_test.rs", "#[derive(Debug)]\npub struct Struct {\npub i: i32,\nj:String,\n}");
        let lines = parse_crate(&ctx, &mut parser);

        assert_eq!(lines.len(), 3);
        assert!(lines.contains(&1));
        assert!(lines.contains(&3));
        assert!(lines.contains(&4));
    }

    #[test]
    fn filter_mods() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "mod foo {\nfn double(x:i32)->i32 {\n x*2\n}\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&3));

        let mut parser = ctx.generate_parser("test.rs", "mod foo{}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&1));
    }

    #[test]
    fn filter_macros() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "\n\nfn unused() {\nunimplemented!();\n}");

        let lines = parse_crate(&ctx, &mut parser);
        // Braces should be ignored so number could be higher
        assert!(lines.len() >= 1);
        assert!(lines.contains(&4));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nunreachable!();\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.len() >= 1);
        assert!(lines.contains(&2));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nprintln!(\"text\");\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
    }

    #[test]
    fn filter_tests() {
        let ctx = TestContext::default();
        let src_string = "#[cfg(test)]\nmod tests {\n fn boo(){\nassert!(true);\n}\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&4));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&4));

        let ctx = TestContext::default();
        let src_string = "#[test]\nfn mytest() { \n assert!(true);\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
        assert!(!lines.contains(&3));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&2));
        assert!(lines.contains(&3));

    }
}
<commit_msg>Switched to parse AST from crate roots.<commit_after>use std::rc::Rc;
use std::ops::Deref;
use std::path::PathBuf;
use std::collections::HashSet;
use cargo::core::Workspace;
use cargo::sources::PathSource;
use syntex_syntax::attr;
use syntex_syntax::visit::{self, Visitor, FnKind};
use syntex_syntax::codemap::{CodeMap, Span, FilePathMapping};
use syntex_syntax::ast::{NodeId, Mac, Attribute, Stmt, StmtKind, FnDecl, Mod,
    StructField, Block, Item, ItemKind};
use syntex_syntax::parse::{self, ParseSess};
use syntex_syntax::errors::Handler;
use syntex_syntax::errors::emitter::ColorConfig;
use syntex_syntax::ext::expand::MacroExpander;
use config::Config;

struct IgnoredLines<'a> {
    lines: Vec<(PathBuf, usize)>,
    covered: &'a HashSet<PathBuf>,
    codemap: &'a CodeMap,
    config: &'a Config,
}

/// Returns a list of files and line numbers to ignore (not indexes!)
pub fn get_lines_to_ignore(project: &Workspace, config: &Config) -> Vec<(PathBuf, usize)> {
    let mut result: Vec<(PathBuf, usize)> = Vec::new();

    let pkg = project.current().unwrap();
    let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), project.config());
    if let Ok(package) = src.root_package() {

        let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
        let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
        let parse_session = ParseSess::with_span_handler(handler, codemap.clone());

        let mut done_files: HashSet<PathBuf> = HashSet::new();
        for target in package.targets() {
            let file = target.src_path();
            if !(config.ignore_tests && file.starts_with(project.root().join("tests"))) {
                let mut parser = parse::new_parser_from_file(&parse_session, file);
                if let Ok(krate) = parser.parse_crate_mod() {

                    let mut lines = {
                        let mut visitor = IgnoredLines::from_session(&parse_session, &done_files, config);
                        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
                        visitor.lines
                    };

                    for l in &lines {
                        done_files.insert(l.0.clone());
                    }
                    result.append(&mut lines);
                }
            }
        }
    }
    result
}

impl<'a> IgnoredLines<'a> {
    /// Construct a new ignored lines object for the given project
    fn from_session(session: &'a ParseSess,
                    covered: &'a HashSet<PathBuf>,
                    config: &'a Config) -> IgnoredLines<'a> {
        IgnoredLines {
            lines: vec![],
            covered: covered,
            codemap: session.codemap(),
            config: config,
        }
    }

    /// Add lines to the line ignore list
    fn ignore_lines(&mut self, span: Span) {
        if let Ok(s) = self.codemap.span_to_lines(span) {
            for line in &s.lines {
                let pb = PathBuf::from(self.codemap.span_to_filename(span) as String);
                // Line number is index+1
                self.lines.push((pb, line.line_index + 1));
            }
        }
    }

    /// Looks for #[cfg(test)] attribute.
    fn contains_cfg_test(&mut self, attrs: &[Attribute]) -> bool {
        attrs.iter()
             .filter(|x| x.path == "cfg")
             .filter_map(|x| x.meta_item_list())
             .flat_map(|x| x)
             .any(|x| {
                 if let Some(w) = x.word() {
                    w.name().as_str() == "test"
                 } else {
                     false
                 }
             })
    }

    /// This function finds ignorable lines within actual coverable code.
    /// As opposed to other functions which find isolated lines that aren't
    /// executed or lines filtered by the user. These lines are things like
    /// close braces that are within coverable code but not coverable.
    fn find_ignorable_lines(&mut self, span: Span) {
        if let Ok(l) = self.codemap.span_to_lines(span) {
            for line in &l.lines {
                let pb = PathBuf::from(self.codemap.span_to_filename(span) as String);
                if let Some(s) = l.file.get_line(line.line_index) {
                    // Is this one of those pointless {, } or }; only lines?
                    if !s.chars().any(|x| !"{}[];\t ,".contains(x)) {
                        self.lines.push((pb, line.line_index + 1));
                    }
                }
            }
        }
    }
}

impl<'v, 'a> Visitor<'v> for IgnoredLines<'a> {

    fn visit_item(&mut self, i: &'v Item) {
        match i.node {
            ItemKind::ExternCrate(..) => self.ignore_lines(i.span),
            ItemKind::Fn(_, _, _, _, _, ref block) => {
                if attr::contains_name(&i.attrs, "test") && self.config.ignore_tests {
                    self.ignore_lines(i.span);
                    self.ignore_lines(block.deref().span);
                }
            },
            _ => {},
        }
        visit::walk_item(self, i);
    }

    fn visit_mod(&mut self, m: &'v Mod, s: Span, _attrs: &[Attribute], _n: NodeId) {
        // If mod is cfg(test) and --ignore-tests ignore contents!
        if let Ok(fl) = self.codemap.span_to_lines(s) {
            if self.config.ignore_tests && self.contains_cfg_test(_attrs) {
                self.ignore_lines(s);
                if fl.lines.len() == 1 {
                    // Ignore the file
                    self.ignore_lines(m.inner);
                }
            }
            else {
                if fl.lines.len() == 1 {
                    // mod imports show up as coverable. Ignore
                    self.ignore_lines(s);
                }
                let mod_path = PathBuf::from(self.codemap.span_to_filename(m.inner));
                if !self.covered.contains(&mod_path) {
                    visit::walk_mod(self, m);
                }
            }
        }
    }

    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, s: Span, _: NodeId) {
        visit::walk_fn(self, fk, fd, s);
    }

    fn visit_stmt(&mut self, s: &Stmt) {
        match s.node {
            StmtKind::Mac(_) => visit::walk_stmt(self, s),
            _ => {},
        }
    }

    fn visit_mac(&mut self, mac: &Mac) {
        // Use this to ignore unreachable lines
        let mac_text = &format!("{}", mac.node.path)[..];
        // TODO unimplemented should have extra logic to exclude the
        // function from coverage
        match mac_text {
            "unimplemented" => self.ignore_lines(mac.span),
            "unreachable" => self.ignore_lines(mac.span),
            _ => {},
        }
        visit::walk_mac(self, mac);
    }

    /// Ignores attributes which may get identified as coverable lines.
    fn visit_attribute(&mut self, attr: &Attribute) {
        if attr.check_name("derive") {
            self.ignore_lines(attr.span);
        }
    }

    /// Struct fields are mistakenly identified as instructions and uncoverable.
    fn visit_struct_field(&mut self, s: &'v StructField) {
        self.ignore_lines(s.span);
        visit::walk_struct_field(self, s);
    }

    fn visit_block(&mut self, b: &'v Block) {
        self.find_ignorable_lines(b.span);
        visit::walk_block(self, b);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use syntex_syntax::parse::filemap_to_parser;
    use syntex_syntax::parse::parser::Parser;

    struct TestContext {
        conf: Config,
        codemap: Rc<CodeMap>,
        parse_session: ParseSess
    }

    impl TestContext {
        fn generate_parser(&self, filename: &str, src_string: &str) -> Parser {
            let filemap = self.codemap.new_filemap(filename.to_string(),
                                                   src_string.to_string());
            filemap_to_parser(&self.parse_session, filemap)
        }
    }

    impl Default for TestContext {
        fn default() -> TestContext {
            let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
            let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
            let parse_session = ParseSess::with_span_handler(handler, codemap.clone());
            TestContext {
                conf: Config::default(),
                codemap: codemap,
                parse_session: parse_session
            }
        }
    }

    fn parse_crate(ctx: &TestContext, parser: &mut Parser) -> Vec<usize>  {
        let krate = parser.parse_crate_mod();
        assert!(krate.is_ok());
        let krate = krate.unwrap();
        let unused: HashSet<PathBuf> = HashSet::new();
        let mut visitor = IgnoredLines::from_session(&ctx.parse_session, &unused, &ctx.conf);
        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
        visitor.lines.iter().map(|x| x.1).collect::<Vec<_>>()
    }

    #[test]
    fn filter_struct_members() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("struct_test.rs", "#[derive(Debug)]\npub struct Struct {\npub i: i32,\nj:String,\n}");
        let lines = parse_crate(&ctx, &mut parser);

        assert_eq!(lines.len(), 3);
        assert!(lines.contains(&1));
        assert!(lines.contains(&3));
        assert!(lines.contains(&4));
    }

    #[test]
    fn filter_mods() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "mod foo {\nfn double(x:i32)->i32 {\n x*2\n}\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&3));

        let mut parser = ctx.generate_parser("test.rs", "mod foo{}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&1));
    }

    #[test]
    fn filter_macros() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "\n\nfn unused() {\nunimplemented!();\n}");

        let lines = parse_crate(&ctx, &mut parser);
        // Braces should be ignored so number could be higher
        assert!(lines.len() >= 1);
        assert!(lines.contains(&4));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nunreachable!();\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.len() >= 1);
        assert!(lines.contains(&2));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nprintln!(\"text\");\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
    }

    #[test]
    fn filter_tests() {
        let ctx = TestContext::default();
        let src_string = "#[cfg(test)]\nmod tests {\n fn boo(){\nassert!(true);\n}\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&4));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&4));

        let ctx = TestContext::default();
        let src_string = "#[test]\nfn mytest() { \n assert!(true);\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
        assert!(!lines.contains(&3));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&2));
        assert!(lines.contains(&3));

    }
}
<|endoftext|>


<commit_before>use super::selector::SockState;
use super::InternalState;
use super::{new_socket, socket_addr};
use crate::poll;
use crate::sys::windows::init;
use crate::{event, Interests, Registry, Token};

use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use std::sync::{Arc, Mutex};
use std::{fmt, io};
use winapi::um::winsock2::{bind, closesocket, SOCKET_ERROR, SOCK_DGRAM};

pub struct UdpSocket {
    internal: Arc<Mutex<Option<InternalState>>>,
    inner: net::UdpSocket,
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
        init();
        new_socket(addr, SOCK_DGRAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| UdpSocket {
                internal: Arc::new(Mutex::new(None)),
                inner: unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<UdpSocket> {
        self.inner.try_clone().map(|inner| UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            inner,
        })
    }

    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
        try_io!(self, send_to, buf, target)
    }

    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        try_io!(self, recv_from, buf)
    }

    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        try_io!(self, peek_from, buf)
    }

    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, send, buf)
    }

    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, recv, buf)
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, peek, buf)
    }

    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
        self.inner.connect(addr)
    }

    pub fn broadcast(&self) -> io::Result<bool> {
        self.inner.broadcast()
    }

    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
        self.inner.set_broadcast(on)
    }

    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
        self.inner.multicast_loop_v4()
    }

    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
        self.inner.set_multicast_loop_v4(on)
    }

    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
        self.inner.multicast_ttl_v4()
    }

    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_multicast_ttl_v4(ttl)
    }

    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
        self.inner.multicast_loop_v6()
    }

    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
        self.inner.set_multicast_loop_v6(on)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.inner.join_multicast_v4(&multiaddr, &interface)
    }

    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.inner.join_multicast_v6(multiaddr, interface)
    }

    pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.inner.leave_multicast_v4(&multiaddr, &interface)
    }

    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.inner.leave_multicast_v6(multiaddr, interface)
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for UdpSocket {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for UdpSocket {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

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

impl FromRawSocket for UdpSocket {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> UdpSocket {
        UdpSocket {
            internal: Arc::new(Mutex::new(None)),
            inner: net::UdpSocket::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for UdpSocket {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for UdpSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}
<commit_msg>Remove Arc from UdpSocket internal state<commit_after>use super::selector::SockState;
use super::InternalState;
use super::{new_socket, socket_addr};
use crate::poll;
use crate::sys::windows::init;
use crate::{event, Interests, Registry, Token};

use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::os::windows::raw::SOCKET as StdSocket; // winapi uses usize, stdlib uses u32/u64.
use std::sync::{Arc, Mutex};
use std::{fmt, io};
use winapi::um::winsock2::{bind, closesocket, SOCKET_ERROR, SOCK_DGRAM};

pub struct UdpSocket {
    internal: Mutex<Option<InternalState>>,
    inner: net::UdpSocket,
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> io::Result<UdpSocket> {
        init();
        new_socket(addr, SOCK_DGRAM).and_then(|socket| {
            let (raw_addr, raw_addr_length) = socket_addr(&addr);
            syscall!(
                bind(socket, raw_addr, raw_addr_length,),
                PartialEq::eq,
                SOCKET_ERROR
            )
            .map_err(|err| {
                // Close the socket if we hit an error, ignoring the error
                // from closing since we can't pass back two errors.
                let _ = unsafe { closesocket(socket) };
                err
            })
            .map(|_| UdpSocket {
                internal: Mutex::new(None),
                inner: unsafe { net::UdpSocket::from_raw_socket(socket as StdSocket) },
            })
        })
    }

    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    pub fn try_clone(&self) -> io::Result<UdpSocket> {
        self.inner.try_clone().map(|inner| UdpSocket {
            internal: Mutex::new(None),
            inner,
        })
    }

    pub fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result<usize> {
        try_io!(self, send_to, buf, target)
    }

    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        try_io!(self, recv_from, buf)
    }

    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
        try_io!(self, peek_from, buf)
    }

    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
        try_io!(self, send, buf)
    }

    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, recv, buf)
    }

    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
        try_io!(self, peek, buf)
    }

    pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
        self.inner.connect(addr)
    }

    pub fn broadcast(&self) -> io::Result<bool> {
        self.inner.broadcast()
    }

    pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
        self.inner.set_broadcast(on)
    }

    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
        self.inner.multicast_loop_v4()
    }

    pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
        self.inner.set_multicast_loop_v4(on)
    }

    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
        self.inner.multicast_ttl_v4()
    }

    pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_multicast_ttl_v4(ttl)
    }

    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
        self.inner.multicast_loop_v6()
    }

    pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
        self.inner.set_multicast_loop_v6(on)
    }

    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.inner.join_multicast_v4(&multiaddr, &interface)
    }

    pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.inner.join_multicast_v6(multiaddr, interface)
    }

    pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
        self.inner.leave_multicast_v4(&multiaddr, &interface)
    }

    pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
        self.inner.leave_multicast_v6(multiaddr, interface)
    }

    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    // Used by `try_io` to register after an I/O operation blocked.
    fn io_blocked_reregister(&self) -> io::Result<()> {
        let internal = self.internal.lock().unwrap();
        if internal.is_some() {
            let selector = internal.as_ref().unwrap().selector.clone();
            let token = internal.as_ref().unwrap().token;
            let interests = internal.as_ref().unwrap().interests;
            drop(internal);
            selector.reregister(self, token, interests)
        } else {
            Ok(())
        }
    }
}

impl super::SocketState for UdpSocket {
    fn get_sock_state(&self) -> Option<Arc<Mutex<SockState>>> {
        let internal = self.internal.lock().unwrap();
        match &*internal {
            Some(internal) => match &internal.sock_state {
                Some(arc) => Some(arc.clone()),
                None => None,
            },
            None => None,
        }
    }
    fn set_sock_state(&self, sock_state: Option<Arc<Mutex<SockState>>>) {
        let mut internal = self.internal.lock().unwrap();
        match &mut *internal {
            Some(internal) => {
                internal.sock_state = sock_state;
            }
            None => {}
        };
    }
}

impl event::Source for UdpSocket {
    fn register(&self, registry: &Registry, token: Token, interests: Interests) -> io::Result<()> {
        {
            let mut internal = self.internal.lock().unwrap();
            if internal.is_none() {
                *internal = Some(InternalState::new(
                    poll::selector(registry).clone_inner(),
                    token,
                    interests,
                ));
            }
        }
        let result = poll::selector(registry).register(self, token, interests);
        match result {
            Ok(_) => {}
            Err(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
        }
        result
    }

    fn reregister(
        &self,
        registry: &Registry,
        token: Token,
        interests: Interests,
    ) -> io::Result<()> {
        let result = poll::selector(registry).reregister(self, token, interests);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                internal.as_mut().unwrap().token = token;
                internal.as_mut().unwrap().interests = interests;
            }
            Err(_) => {}
        };
        result
    }

    fn deregister(&self, registry: &Registry) -> io::Result<()> {
        let result = poll::selector(registry).deregister(self);
        match result {
            Ok(_) => {
                let mut internal = self.internal.lock().unwrap();
                *internal = None;
            }
            Err(_) => {}
        };
        result
    }
}

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

impl FromRawSocket for UdpSocket {
    unsafe fn from_raw_socket(rawsocket: RawSocket) -> UdpSocket {
        UdpSocket {
            internal: Mutex::new(None),
            inner: net::UdpSocket::from_raw_socket(rawsocket),
        }
    }
}

impl IntoRawSocket for UdpSocket {
    fn into_raw_socket(self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}

impl AsRawSocket for UdpSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.inner.as_raw_socket()
    }
}
<|endoftext|>


<commit_before>//! EGL context related structs
use std::os::raw::c_int;
use std::sync::atomic::Ordering;

use super::{ffi, wrap_egl_call, Error, MakeCurrentError};
use crate::backend::egl::display::{EGLDisplay, PixelFormat};
use crate::backend::egl::EGLSurface;

/// EGL context for rendering
#[derive(Debug)]
pub struct EGLContext {
    context: ffi::egl::types::EGLContext,
    pub(crate) display: EGLDisplay,
    config_id: ffi::egl::types::EGLConfig,
    pixel_format: Option<PixelFormat>,
}
// EGLContexts can be moved between threads safely
unsafe impl Send for EGLContext {}
unsafe impl Sync for EGLContext {}

impl EGLContext {
    /// Creates a new configless `EGLContext` from a given `EGLDisplay`
    pub fn new<L>(display: &EGLDisplay, log: L) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, None, None, log)
    }

    /// Create a new [`EGLContext`] from a given `EGLDisplay` and configuration requirements
    pub fn new_with_config<L>(
        display: &EGLDisplay,
        attributes: GlAttributes,
        reqs: PixelFormatRequirements,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, None, Some((attributes, reqs)), log)
    }

    /// Create a new configless `EGLContext` from a given `EGLDisplay` sharing resources with another context
    pub fn new_shared<L>(display: &EGLDisplay, share: &EGLContext, log: L) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, Some(share), None, log)
    }

    /// Create a new `EGLContext` from a given `EGLDisplay` and configuration requirements sharing resources with another context
    pub fn new_shared_with_config<L>(
        display: &EGLDisplay,
        share: &EGLContext,
        attributes: GlAttributes,
        reqs: PixelFormatRequirements,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, Some(share), Some((attributes, reqs)), log)
    }

    fn new_internal<L>(
        display: &EGLDisplay,
        shared: Option<&EGLContext>,
        config: Option<(GlAttributes, PixelFormatRequirements)>,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_fallback(log.into()).new(o!("smithay_module" => "backend_egl"));

        let (pixel_format, config_id) = match config {
            Some((attributes, reqs)) => {
                let (format, config_id) = display.choose_config(attributes, reqs)?;
                (Some(format), config_id)
            }
            None => {
                if !display
                    .extensions
                    .iter()
                    .any(|x| x == "EGL_KHR_no_config_context")
                    && !display
                        .extensions
                        .iter()
                        .any(|x| x == "EGL_MESA_configless_context")
                    && !display
                        .extensions
                        .iter()
                        .any(|x| x == "EGL_KHR_surfaceless_context")
                {
                    return Err(Error::EglExtensionNotSupported(&[
                        "EGL_KHR_no_config_context",
                        "EGL_MESA_configless_context",
                        "EGL_KHR_surfaceless_context",
                    ]));
                }
                (None, ffi::egl::NO_CONFIG_KHR)
            }
        };

        let mut context_attributes = Vec::with_capacity(10);

        if let Some((attributes, _)) = config {
            let version = attributes.version;

            if display.egl_version >= (1, 5)
                || display.extensions.iter().any(|s| s == "EGL_KHR_create_context")
            {
                trace!(log, "Setting CONTEXT_MAJOR_VERSION to {}", version.0);
                context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
                context_attributes.push(version.0 as i32);
                trace!(log, "Setting CONTEXT_MINOR_VERSION to {}", version.1);
                context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
                context_attributes.push(version.1 as i32);

                if attributes.debug && display.egl_version >= (1, 5) {
                    trace!(log, "Setting CONTEXT_OPENGL_DEBUG to TRUE");
                    context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
                    context_attributes.push(ffi::egl::TRUE as i32);
                }

                context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32);
                context_attributes.push(0);
            } else if display.egl_version >= (1, 3) {
                trace!(log, "Setting CONTEXT_CLIENT_VERSION to {}", version.0);
                context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
                context_attributes.push(version.0 as i32);
            }
        } else {
            trace!(log, "Setting CONTEXT_CLIENT_VERSION to 2");
            context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
            context_attributes.push(2);
        }

        context_attributes.push(ffi::egl::NONE as i32);

        trace!(log, "Creating EGL context...");
        let context = wrap_egl_call(|| unsafe {
            ffi::egl::CreateContext(
                **display.display,
                config_id,
                shared
                    .map(|context| context.context)
                    .unwrap_or(ffi::egl::NO_CONTEXT),
                context_attributes.as_ptr(),
            )
        })
        .map_err(Error::CreationFailed)?;

        info!(log, "EGL context created");

        Ok(EGLContext {
            context,
            display: display.clone(),
            config_id,
            pixel_format,
        })
    }

    /// Makes the OpenGL context the current context in the current thread with a surface to
    /// read/write to.
    ///
    /// # Safety
    ///
    /// This function is marked unsafe, because the context cannot be made current
    /// on multiple threads.
    pub unsafe fn make_current_with_surface(&self, surface: &EGLSurface) -> Result<(), MakeCurrentError> {
        let surface_ptr = surface.surface.load(Ordering::SeqCst);
        wrap_egl_call(|| {
            ffi::egl::MakeCurrent(**self.display.display, surface_ptr, surface_ptr, self.context)
        })
        .map(|_| ())
        .map_err(Into::into)
    }

    /// Makes the OpenGL context the current context in the current thread with no surface bound.
    ///
    /// # Safety
    ///
    /// This function is marked unsafe, because the context cannot be made current
    /// on multiple threads without being unbound again (see `unbind`)
    pub unsafe fn make_current(&self) -> Result<(), MakeCurrentError> {
        wrap_egl_call(|| {
            ffi::egl::MakeCurrent(
                **self.display.display,
                ffi::egl::NO_SURFACE,
                ffi::egl::NO_SURFACE,
                self.context,
            )
        })
        .map(|_| ())
        .map_err(Into::into)
    }

    /// Returns true if the OpenGL context is the current one in the thread.
    pub fn is_current(&self) -> bool {
        unsafe { ffi::egl::GetCurrentContext() == self.context as *const _ }
    }

    /// Returns the egl config for this context
    pub fn config_id(&self) -> ffi::egl::types::EGLConfig {
        self.config_id
    }

    /// Returns the pixel format of the main framebuffer of the context.
    pub fn pixel_format(&self) -> Option<PixelFormat> {
        self.pixel_format
    }

    /// Unbinds this context from the current thread, if set.
    ///
    /// This does nothing if this context is not the current context
    pub fn unbind(&self) -> Result<(), MakeCurrentError> {
        if self.is_current() {
            wrap_egl_call(|| unsafe {
                ffi::egl::MakeCurrent(
                    **self.display.display,
                    ffi::egl::NO_SURFACE,
                    ffi::egl::NO_SURFACE,
                    ffi::egl::NO_CONTEXT,
                )
            })?;
        }
        Ok(())
    }
}

impl Drop for EGLContext {
    fn drop(&mut self) {
        unsafe {
            // We need to ensure the context is unbound, otherwise it egl stalls the destroy call
            // ignore failures at this point
            let _ = self.unbind();
            ffi::egl::DestroyContext(**self.display.display, self.context);
        }
    }
}

/// Attributes to use when creating an OpenGL context.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GlAttributes {
    /// Describes the OpenGL API and version that are being requested when a context is created.
    ///
    /// `(3, 0)` will request a OpenGL ES 3.0 context for example.
    /// `(2, 0)` is the minimum.
    pub version: (u8, u8),
    /// OpenGL profile to use
    pub profile: Option<GlProfile>,
    /// Whether to enable the debug flag of the context.
    ///
    /// Debug contexts are usually slower but give better error reporting.
    pub debug: bool,
    /// Whether to use vsync. If vsync is enabled, calling `swap_buffers` will block until the screen refreshes.
    /// This is typically used to prevent screen tearing.
    pub vsync: bool,
}

/// Describes the requested OpenGL context profiles.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GlProfile {
    /// Include all the immediate more functions and definitions.
    Compatibility,
    /// Include all the future-compatible functions and definitions.
    Core,
}

/// Describes how the backend should choose a pixel format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PixelFormatRequirements {
    /// If `true`, only hardware-accelerated formats will be considered. If `false`, only software renderers.
    /// `None` means "don't care". Default is `None`.
    pub hardware_accelerated: Option<bool>,
    /// Minimum number of bits for the color buffer, excluding alpha. `None` means "don't care". The default is `None`.
    pub color_bits: Option<u8>,
    /// If `true`, the color buffer must be in a floating point format. Default is `false`.
    ///
    /// Using floating points allows you to write values outside of the `[0.0, 1.0]` range.
    pub float_color_buffer: bool,
    /// Minimum number of bits for the alpha in the color buffer. `None` means "don't care". The default is `None`.
    pub alpha_bits: Option<u8>,
    /// Minimum number of bits for the depth buffer. `None` means "don't care". The default value is `None`.
    pub depth_bits: Option<u8>,
    /// Minimum number of bits for the depth buffer. `None` means "don't care". The default value is `None`.
    pub stencil_bits: Option<u8>,
    /// If `true`, only double-buffered formats will be considered. If `false`, only single-buffer formats.
    /// `None` means "don't care". The default is `None`.
    pub double_buffer: Option<bool>,
    /// Contains the minimum number of samples per pixel in the color, depth and stencil buffers.
    /// `None` means "don't care". Default is `None`. A value of `Some(0)` indicates that multisampling must not be enabled.
    pub multisampling: Option<u16>,
}

impl Default for PixelFormatRequirements {
    fn default() -> Self {
        PixelFormatRequirements {
            hardware_accelerated: Some(true),
            color_bits: Some(24),
            float_color_buffer: false,
            alpha_bits: Some(8),
            depth_bits: Some(24),
            stencil_bits: Some(8),
            double_buffer: Some(true),
            multisampling: None,
        }
    }
}

impl PixelFormatRequirements {
    /// Append the  requirements to the given attribute list
    pub fn create_attributes(&self, out: &mut Vec<c_int>, logger: &slog::Logger) {
        if let Some(hardware_accelerated) = self.hardware_accelerated {
            out.push(ffi::egl::CONFIG_CAVEAT as c_int);
            out.push(if hardware_accelerated {
                trace!(logger, "Setting CONFIG_CAVEAT to NONE");
                ffi::egl::NONE as c_int
            } else {
                trace!(logger, "Setting CONFIG_CAVEAT to SLOW_CONFIG");
                ffi::egl::SLOW_CONFIG as c_int
            });
        }

        if let Some(color) = self.color_bits {
            trace!(logger, "Setting RED_SIZE to {}", color / 3);
            out.push(ffi::egl::RED_SIZE as c_int);
            out.push((color / 3) as c_int);
            trace!(
                logger,
                "Setting GREEN_SIZE to {}",
                color / 3 + if color % 3 != 0 { 1 } else { 0 }
            );
            out.push(ffi::egl::GREEN_SIZE as c_int);
            out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
            trace!(
                logger,
                "Setting BLUE_SIZE to {}",
                color / 3 + if color % 3 == 2 { 1 } else { 0 }
            );
            out.push(ffi::egl::BLUE_SIZE as c_int);
            out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
        }

        if let Some(alpha) = self.alpha_bits {
            trace!(logger, "Setting ALPHA_SIZE to {}", alpha);
            out.push(ffi::egl::ALPHA_SIZE as c_int);
            out.push(alpha as c_int);
        }

        if let Some(depth) = self.depth_bits {
            trace!(logger, "Setting DEPTH_SIZE to {}", depth);
            out.push(ffi::egl::DEPTH_SIZE as c_int);
            out.push(depth as c_int);
        }

        if let Some(stencil) = self.stencil_bits {
            trace!(logger, "Setting STENCIL_SIZE to {}", stencil);
            out.push(ffi::egl::STENCIL_SIZE as c_int);
            out.push(stencil as c_int);
        }

        if let Some(multisampling) = self.multisampling {
            trace!(logger, "Setting SAMPLES to {}", multisampling);
            out.push(ffi::egl::SAMPLES as c_int);
            out.push(multisampling as c_int);
        }
    }
}
<commit_msg>egl: expose supported dmabuf formats<commit_after>//! EGL context related structs
use std::collections::HashSet;
use std::os::raw::c_int;
use std::sync::atomic::Ordering;

use super::{ffi, wrap_egl_call, Error, MakeCurrentError};
use crate::backend::allocator::Format as DrmFormat;
use crate::backend::egl::display::{EGLDisplay, PixelFormat};
use crate::backend::egl::EGLSurface;

/// EGL context for rendering
#[derive(Debug)]
pub struct EGLContext {
    context: ffi::egl::types::EGLContext,
    pub(crate) display: EGLDisplay,
    config_id: ffi::egl::types::EGLConfig,
    pixel_format: Option<PixelFormat>,
}
// EGLContexts can be moved between threads safely
unsafe impl Send for EGLContext {}
unsafe impl Sync for EGLContext {}

impl EGLContext {
    /// Creates a new configless `EGLContext` from a given `EGLDisplay`
    pub fn new<L>(display: &EGLDisplay, log: L) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, None, None, log)
    }

    /// Create a new [`EGLContext`] from a given `EGLDisplay` and configuration requirements
    pub fn new_with_config<L>(
        display: &EGLDisplay,
        attributes: GlAttributes,
        reqs: PixelFormatRequirements,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, None, Some((attributes, reqs)), log)
    }

    /// Create a new configless `EGLContext` from a given `EGLDisplay` sharing resources with another context
    pub fn new_shared<L>(display: &EGLDisplay, share: &EGLContext, log: L) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, Some(share), None, log)
    }

    /// Create a new `EGLContext` from a given `EGLDisplay` and configuration requirements sharing resources with another context
    pub fn new_shared_with_config<L>(
        display: &EGLDisplay,
        share: &EGLContext,
        attributes: GlAttributes,
        reqs: PixelFormatRequirements,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        Self::new_internal(display, Some(share), Some((attributes, reqs)), log)
    }

    fn new_internal<L>(
        display: &EGLDisplay,
        shared: Option<&EGLContext>,
        config: Option<(GlAttributes, PixelFormatRequirements)>,
        log: L,
    ) -> Result<EGLContext, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_fallback(log.into()).new(o!("smithay_module" => "backend_egl"));

        let (pixel_format, config_id) = match config {
            Some((attributes, reqs)) => {
                let (format, config_id) = display.choose_config(attributes, reqs)?;
                (Some(format), config_id)
            }
            None => {
                if !display
                    .extensions
                    .iter()
                    .any(|x| x == "EGL_KHR_no_config_context")
                    && !display
                        .extensions
                        .iter()
                        .any(|x| x == "EGL_MESA_configless_context")
                    && !display
                        .extensions
                        .iter()
                        .any(|x| x == "EGL_KHR_surfaceless_context")
                {
                    return Err(Error::EglExtensionNotSupported(&[
                        "EGL_KHR_no_config_context",
                        "EGL_MESA_configless_context",
                        "EGL_KHR_surfaceless_context",
                    ]));
                }
                (None, ffi::egl::NO_CONFIG_KHR)
            }
        };

        let mut context_attributes = Vec::with_capacity(10);

        if let Some((attributes, _)) = config {
            let version = attributes.version;

            if display.egl_version >= (1, 5)
                || display.extensions.iter().any(|s| s == "EGL_KHR_create_context")
            {
                trace!(log, "Setting CONTEXT_MAJOR_VERSION to {}", version.0);
                context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
                context_attributes.push(version.0 as i32);
                trace!(log, "Setting CONTEXT_MINOR_VERSION to {}", version.1);
                context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
                context_attributes.push(version.1 as i32);

                if attributes.debug && display.egl_version >= (1, 5) {
                    trace!(log, "Setting CONTEXT_OPENGL_DEBUG to TRUE");
                    context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
                    context_attributes.push(ffi::egl::TRUE as i32);
                }

                context_attributes.push(ffi::egl::CONTEXT_FLAGS_KHR as i32);
                context_attributes.push(0);
            } else if display.egl_version >= (1, 3) {
                trace!(log, "Setting CONTEXT_CLIENT_VERSION to {}", version.0);
                context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
                context_attributes.push(version.0 as i32);
            }
        } else {
            trace!(log, "Setting CONTEXT_CLIENT_VERSION to 2");
            context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
            context_attributes.push(2);
        }

        context_attributes.push(ffi::egl::NONE as i32);

        trace!(log, "Creating EGL context...");
        let context = wrap_egl_call(|| unsafe {
            ffi::egl::CreateContext(
                **display.display,
                config_id,
                shared
                    .map(|context| context.context)
                    .unwrap_or(ffi::egl::NO_CONTEXT),
                context_attributes.as_ptr(),
            )
        })
        .map_err(Error::CreationFailed)?;

        info!(log, "EGL context created");

        Ok(EGLContext {
            context,
            display: display.clone(),
            config_id,
            pixel_format,
        })
    }

    /// Makes the OpenGL context the current context in the current thread with a surface to
    /// read/write to.
    ///
    /// # Safety
    ///
    /// This function is marked unsafe, because the context cannot be made current
    /// on multiple threads.
    pub unsafe fn make_current_with_surface(&self, surface: &EGLSurface) -> Result<(), MakeCurrentError> {
        let surface_ptr = surface.surface.load(Ordering::SeqCst);
        wrap_egl_call(|| {
            ffi::egl::MakeCurrent(**self.display.display, surface_ptr, surface_ptr, self.context)
        })
        .map(|_| ())
        .map_err(Into::into)
    }

    /// Makes the OpenGL context the current context in the current thread with no surface bound.
    ///
    /// # Safety
    ///
    /// This function is marked unsafe, because the context cannot be made current
    /// on multiple threads without being unbound again (see `unbind`)
    pub unsafe fn make_current(&self) -> Result<(), MakeCurrentError> {
        wrap_egl_call(|| {
            ffi::egl::MakeCurrent(
                **self.display.display,
                ffi::egl::NO_SURFACE,
                ffi::egl::NO_SURFACE,
                self.context,
            )
        })
        .map(|_| ())
        .map_err(Into::into)
    }

    /// Returns true if the OpenGL context is the current one in the thread.
    pub fn is_current(&self) -> bool {
        unsafe { ffi::egl::GetCurrentContext() == self.context as *const _ }
    }

    /// Returns the egl config for this context
    pub fn config_id(&self) -> ffi::egl::types::EGLConfig {
        self.config_id
    }

    /// Returns the pixel format of the main framebuffer of the context.
    pub fn pixel_format(&self) -> Option<PixelFormat> {
        self.pixel_format
    }

    /// Unbinds this context from the current thread, if set.
    ///
    /// This does nothing if this context is not the current context
    pub fn unbind(&self) -> Result<(), MakeCurrentError> {
        if self.is_current() {
            wrap_egl_call(|| unsafe {
                ffi::egl::MakeCurrent(
                    **self.display.display,
                    ffi::egl::NO_SURFACE,
                    ffi::egl::NO_SURFACE,
                    ffi::egl::NO_CONTEXT,
                )
            })?;
        }
        Ok(())
    }

    /// Returns a list of formats for dmabufs that can be rendered to
    pub fn dmabuf_render_formats(&self) -> &HashSet<DrmFormat> {
        &self.display.dmabuf_render_formats
    }

    /// Returns a list of formats for dmabufs that can be used as textures
    pub fn dmabuf_texture_formats(&self) -> &HashSet<DrmFormat> {
        &self.display.dmabuf_import_formats
    }
}

impl Drop for EGLContext {
    fn drop(&mut self) {
        unsafe {
            // We need to ensure the context is unbound, otherwise it egl stalls the destroy call
            // ignore failures at this point
            let _ = self.unbind();
            ffi::egl::DestroyContext(**self.display.display, self.context);
        }
    }
}

/// Attributes to use when creating an OpenGL context.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GlAttributes {
    /// Describes the OpenGL API and version that are being requested when a context is created.
    ///
    /// `(3, 0)` will request a OpenGL ES 3.0 context for example.
    /// `(2, 0)` is the minimum.
    pub version: (u8, u8),
    /// OpenGL profile to use
    pub profile: Option<GlProfile>,
    /// Whether to enable the debug flag of the context.
    ///
    /// Debug contexts are usually slower but give better error reporting.
    pub debug: bool,
    /// Whether to use vsync. If vsync is enabled, calling `swap_buffers` will block until the screen refreshes.
    /// This is typically used to prevent screen tearing.
    pub vsync: bool,
}

/// Describes the requested OpenGL context profiles.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GlProfile {
    /// Include all the immediate more functions and definitions.
    Compatibility,
    /// Include all the future-compatible functions and definitions.
    Core,
}

/// Describes how the backend should choose a pixel format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PixelFormatRequirements {
    /// If `true`, only hardware-accelerated formats will be considered. If `false`, only software renderers.
    /// `None` means "don't care". Default is `None`.
    pub hardware_accelerated: Option<bool>,
    /// Minimum number of bits for the color buffer, excluding alpha. `None` means "don't care". The default is `None`.
    pub color_bits: Option<u8>,
    /// If `true`, the color buffer must be in a floating point format. Default is `false`.
    ///
    /// Using floating points allows you to write values outside of the `[0.0, 1.0]` range.
    pub float_color_buffer: bool,
    /// Minimum number of bits for the alpha in the color buffer. `None` means "don't care". The default is `None`.
    pub alpha_bits: Option<u8>,
    /// Minimum number of bits for the depth buffer. `None` means "don't care". The default value is `None`.
    pub depth_bits: Option<u8>,
    /// Minimum number of bits for the depth buffer. `None` means "don't care". The default value is `None`.
    pub stencil_bits: Option<u8>,
    /// If `true`, only double-buffered formats will be considered. If `false`, only single-buffer formats.
    /// `None` means "don't care". The default is `None`.
    pub double_buffer: Option<bool>,
    /// Contains the minimum number of samples per pixel in the color, depth and stencil buffers.
    /// `None` means "don't care". Default is `None`. A value of `Some(0)` indicates that multisampling must not be enabled.
    pub multisampling: Option<u16>,
}

impl Default for PixelFormatRequirements {
    fn default() -> Self {
        PixelFormatRequirements {
            hardware_accelerated: Some(true),
            color_bits: Some(24),
            float_color_buffer: false,
            alpha_bits: Some(8),
            depth_bits: Some(24),
            stencil_bits: Some(8),
            double_buffer: Some(true),
            multisampling: None,
        }
    }
}

impl PixelFormatRequirements {
    /// Append the  requirements to the given attribute list
    pub fn create_attributes(&self, out: &mut Vec<c_int>, logger: &slog::Logger) {
        if let Some(hardware_accelerated) = self.hardware_accelerated {
            out.push(ffi::egl::CONFIG_CAVEAT as c_int);
            out.push(if hardware_accelerated {
                trace!(logger, "Setting CONFIG_CAVEAT to NONE");
                ffi::egl::NONE as c_int
            } else {
                trace!(logger, "Setting CONFIG_CAVEAT to SLOW_CONFIG");
                ffi::egl::SLOW_CONFIG as c_int
            });
        }

        if let Some(color) = self.color_bits {
            trace!(logger, "Setting RED_SIZE to {}", color / 3);
            out.push(ffi::egl::RED_SIZE as c_int);
            out.push((color / 3) as c_int);
            trace!(
                logger,
                "Setting GREEN_SIZE to {}",
                color / 3 + if color % 3 != 0 { 1 } else { 0 }
            );
            out.push(ffi::egl::GREEN_SIZE as c_int);
            out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
            trace!(
                logger,
                "Setting BLUE_SIZE to {}",
                color / 3 + if color % 3 == 2 { 1 } else { 0 }
            );
            out.push(ffi::egl::BLUE_SIZE as c_int);
            out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
        }

        if let Some(alpha) = self.alpha_bits {
            trace!(logger, "Setting ALPHA_SIZE to {}", alpha);
            out.push(ffi::egl::ALPHA_SIZE as c_int);
            out.push(alpha as c_int);
        }

        if let Some(depth) = self.depth_bits {
            trace!(logger, "Setting DEPTH_SIZE to {}", depth);
            out.push(ffi::egl::DEPTH_SIZE as c_int);
            out.push(depth as c_int);
        }

        if let Some(stencil) = self.stencil_bits {
            trace!(logger, "Setting STENCIL_SIZE to {}", stencil);
            out.push(ffi::egl::STENCIL_SIZE as c_int);
            out.push(stencil as c_int);
        }

        if let Some(multisampling) = self.multisampling {
            trace!(logger, "Setting SAMPLES to {}", multisampling);
            out.push(ffi::egl::SAMPLES as c_int);
            out.push(multisampling as c_int);
        }
    }
}
<|endoftext|>


<commit_before>//! Bounding volumes.

// Types and traits
#[doc(inline)]
pub use bounding_volume::bounding_volume::{HasBoundingVolume, BoundingVolume, LooseBoundingVolume};
#[doc(inline)]
pub use bounding_volume::aabb::{HasAABB, AABB, WithAABB};
pub use bounding_volume::bounding_sphere::{HasBoundingSphere, BoundingSphere};
pub use bounding_volume::spacialized_cone::SpacializedCone;

// // functions
pub use bounding_volume::aabb_utils::{implicit_shape_aabb, point_cloud_aabb};
pub use bounding_volume::aabb_ball::ball_aabb;
pub use bounding_volume::bounding_sphere_utils::{point_cloud_bounding_sphere_with_center, point_cloud_bounding_sphere};
//
// modules
#[doc(hidden)]
pub mod aabb;
#[doc(hidden)]
pub mod bounding_volume;

mod aabb_box;
mod aabb_cone;
mod aabb_ball;
mod aabb_cylinder;
mod aabb_capsule;
mod aabb_plane;
mod aabb_convex;
mod aabb_compound;
mod aabb_triangle;
mod aabb_segment;
mod aabb_mesh;
mod aabb_bezier_surface;
mod aabb_utils;

mod bounding_sphere;
mod bounding_sphere_box;
mod bounding_sphere_cone;
mod bounding_sphere_ball;
mod bounding_sphere_cylinder;
mod bounding_sphere_capsule;
mod bounding_sphere_plane;
mod bounding_sphere_convex;
mod bounding_sphere_compound;
mod bounding_sphere_triangle;
mod bounding_sphere_segment;
mod bounding_sphere_mesh;
mod bounding_sphere_bezier_surface;
mod bounding_sphere_utils;

mod spacialized_cone;
<commit_msg>make bounding_sphere mod public and allow missing doc.<commit_after>//! Bounding volumes.

// Types and traits
#[doc(inline)]
pub use bounding_volume::bounding_volume::{HasBoundingVolume, BoundingVolume, LooseBoundingVolume};
#[doc(inline)]
pub use bounding_volume::aabb::{HasAABB, AABB, WithAABB};
pub use bounding_volume::bounding_sphere::{HasBoundingSphere, BoundingSphere};
pub use bounding_volume::spacialized_cone::SpacializedCone;

// // functions
pub use bounding_volume::aabb_utils::{implicit_shape_aabb, point_cloud_aabb};
pub use bounding_volume::aabb_ball::ball_aabb;
pub use bounding_volume::bounding_sphere_utils::{point_cloud_bounding_sphere_with_center, point_cloud_bounding_sphere};
//
// modules
#[doc(hidden)]
pub mod aabb;
#[doc(hidden)]
pub mod bounding_volume;

mod aabb_box;
mod aabb_cone;
mod aabb_ball;
mod aabb_cylinder;
mod aabb_capsule;
mod aabb_plane;
mod aabb_convex;
mod aabb_compound;
mod aabb_triangle;
mod aabb_segment;
mod aabb_mesh;
mod aabb_bezier_surface;
mod aabb_utils;

#[allow(missing_doc)]
pub mod bounding_sphere;
mod bounding_sphere_box;
mod bounding_sphere_cone;
mod bounding_sphere_ball;
mod bounding_sphere_cylinder;
mod bounding_sphere_capsule;
mod bounding_sphere_plane;
mod bounding_sphere_convex;
mod bounding_sphere_compound;
mod bounding_sphere_triangle;
mod bounding_sphere_segment;
mod bounding_sphere_mesh;
mod bounding_sphere_bezier_surface;
mod bounding_sphere_utils;

mod spacialized_cone;
<|endoftext|>


<commit_before>use core::mem;
use core::cell::Cell;
use core::ops::{Index, IndexMut};
use hil;

use common::take_cell::TakeCell;

use peripheral_registers::{GPIO_BASE, GPIO};

#[allow(non_snake_case)]
fn GPIO() -> &'static GPIO {
    unsafe { mem::transmute(GPIO_BASE as usize) }
}

pub struct GPIOPin {
    pin: u8,
    client_data: Cell<usize>,
    client: TakeCell<&'static hil::gpio::Client>,
}

impl GPIOPin {
    const fn new(pin: u8) -> GPIOPin {
        GPIOPin {
            pin: pin,
            client_data: Cell::new(0),
            client: TakeCell::empty(),
        }
    }

    pub fn set_client<C: hil::gpio::Client>(&self, client: &'static C) {
        self.client.replace(client);
    }

}

impl hil::gpio::GPIOPin for GPIOPin {
    fn enable_output(&self) {
        GPIO().pin_cnf[self.pin as usize].set((1 << 0) | (1 << 1) | (0 << 2) | (0 << 8) | (0 << 16));
    }

    fn enable_input(&self, _mode: hil::gpio::InputMode) {
        unimplemented!();
    }

    fn disable(&self) {
        unimplemented!();
    }

    fn set(&self) {
        GPIO().outset.set(1 << self.pin);
    }

    fn clear(&self) {
        GPIO().outclr.set(1 << self.pin);
    }

    fn toggle(&self) {
        unimplemented!();
    }

    fn read(&self) -> bool {
        unimplemented!();
    }

    fn enable_interrupt(&self, client_data: usize, mode: hil::gpio::InterruptMode) {
        unimplemented!();
    }

    fn disable_interrupt(&self) {
        unimplemented!();
    }
}

pub struct Port {
    pins: [GPIOPin; 32]
}

impl Index<usize> for Port {
    type Output = GPIOPin;

    fn index(&self, index: usize) -> &GPIOPin {
        &self.pins[index]
    }
}

impl IndexMut<usize> for Port {
    fn index_mut(&mut self, index: usize) -> &mut GPIOPin {
        &mut self.pins[index]
    }
}

pub static mut PA : Port = Port {
    pins: [
        GPIOPin::new(0), GPIOPin::new(1), GPIOPin::new(2), GPIOPin::new(3),
        GPIOPin::new(4), GPIOPin::new(5), GPIOPin::new(6), GPIOPin::new(7),
        GPIOPin::new(8), GPIOPin::new(9), GPIOPin::new(10), GPIOPin::new(11),
        GPIOPin::new(12), GPIOPin::new(13), GPIOPin::new(14), GPIOPin::new(15),
        GPIOPin::new(16), GPIOPin::new(17), GPIOPin::new(18), GPIOPin::new(19),
        GPIOPin::new(20), GPIOPin::new(21), GPIOPin::new(22), GPIOPin::new(23),
        GPIOPin::new(24), GPIOPin::new(25), GPIOPin::new(26), GPIOPin::new(27),
        GPIOPin::new(28), GPIOPin::new(29), GPIOPin::new(30), GPIOPin::new(31),
    ],
};
<commit_msg>nRF51822: Remove unused code from gpio.rs<commit_after>use core::mem;
use core::ops::{Index, IndexMut};
use hil;

use common::take_cell::TakeCell;

use peripheral_registers::{GPIO_BASE, GPIO};

#[allow(non_snake_case)]
fn GPIO() -> &'static GPIO {
    unsafe { mem::transmute(GPIO_BASE as usize) }
}

pub struct GPIOPin {
    pin: u8,
    client: TakeCell<&'static hil::gpio::Client>,
}

impl GPIOPin {
    const fn new(pin: u8) -> GPIOPin {
        GPIOPin {
            pin: pin,
            client: TakeCell::empty(),
        }
    }

    pub fn set_client<C: hil::gpio::Client>(&self, client: &'static C) {
        self.client.replace(client);
    }

}

impl hil::gpio::GPIOPin for GPIOPin {
    fn enable_output(&self) {
        GPIO().pin_cnf[self.pin as usize].set((1 << 0) | (1 << 1) | (0 << 2) | (0 << 8) | (0 << 16));
    }

    fn enable_input(&self, _mode: hil::gpio::InputMode) {
        unimplemented!();
    }

    fn disable(&self) {
        unimplemented!();
    }

    fn set(&self) {
        GPIO().outset.set(1 << self.pin);
    }

    fn clear(&self) {
        GPIO().outclr.set(1 << self.pin);
    }

    fn toggle(&self) {
        unimplemented!();
    }

    fn read(&self) -> bool {
        unimplemented!();
    }

    fn enable_interrupt(&self, _client_data: usize, _mode: hil::gpio::InterruptMode) {
        unimplemented!();
    }

    fn disable_interrupt(&self) {
        unimplemented!();
    }
}

pub struct Port {
    pins: [GPIOPin; 32]
}

impl Index<usize> for Port {
    type Output = GPIOPin;

    fn index(&self, index: usize) -> &GPIOPin {
        &self.pins[index]
    }
}

impl IndexMut<usize> for Port {
    fn index_mut(&mut self, index: usize) -> &mut GPIOPin {
        &mut self.pins[index]
    }
}

pub static mut PA : Port = Port {
    pins: [
        GPIOPin::new(0), GPIOPin::new(1), GPIOPin::new(2), GPIOPin::new(3),
        GPIOPin::new(4), GPIOPin::new(5), GPIOPin::new(6), GPIOPin::new(7),
        GPIOPin::new(8), GPIOPin::new(9), GPIOPin::new(10), GPIOPin::new(11),
        GPIOPin::new(12), GPIOPin::new(13), GPIOPin::new(14), GPIOPin::new(15),
        GPIOPin::new(16), GPIOPin::new(17), GPIOPin::new(18), GPIOPin::new(19),
        GPIOPin::new(20), GPIOPin::new(21), GPIOPin::new(22), GPIOPin::new(23),
        GPIOPin::new(24), GPIOPin::new(25), GPIOPin::new(26), GPIOPin::new(27),
        GPIOPin::new(28), GPIOPin::new(29), GPIOPin::new(30), GPIOPin::new(31),
    ],
};
<|endoftext|>


<commit_before>/// This module takes a (parsed) defenition of `macro_rules` invocation, a
/// `tt::TokenTree` representing an argument of macro invocation, and produces a
/// `tt::TokenTree` for the result of the expansion.
use rustc_hash::FxHashMap;
use ra_syntax::SmolStr;

use crate::tt_cursor::TtCursor;

pub(crate) fn exapnd(rules: &crate::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> {
    rules.rules.iter().find_map(|it| expand_rule(it, input))
}

fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Option<tt::Subtree> {
    let mut input = TtCursor::new(input);
    let bindings = match_lhs(&rule.lhs, &mut input)?;
    if !input.is_eof() {
        return None;
    }
    expand_subtree(&rule.rhs, &bindings, &mut Vec::new())
}

/// The actual algorithm for expansion is not too hard, but is pretty tricky.
/// `Bindings` structure is the key to understanding what we are doing here.
///
/// On the high level, it stores mapping from meta variables to the bits of
/// syntax it should be substituted with. For example, if `$e:expr` is matched
/// with `1 + 1` by macro_rules, the `Binding` will store `$e -> 1 + 1`.
///
/// The tricky bit is dealing with repetitions (`$()*`). Consider this example:
///
/// ```ignore
/// macro_rules! foo {
///     ($($ i:ident $($ e:expr),*);*) => {
///         $(fn $ i() { $($ e);*; })*
///     }
/// }
/// foo! { foo 1,2,3; bar 4,5,6 }
/// ```
///
/// Here, the `$i` meta variable is matched first with `foo` and then with
/// `bar`, and `$e` is matched in turn with `1`, `2`, `3`, `4`, `5`, `6`.
///
/// To represent such "multi-mappings", we use a recursive structures: we map
/// variables not to values, but to *lists* of values or other lists (that is,
/// to the trees).
///
/// For the above example, the bindings would store
///
/// ```ignore
/// i -> [foo, bar]
/// e -> [[1, 2, 3], [4, 5, 6]]
/// ```
///
/// We construct `Bindings` in the `match_lhs`. The interesting case is
/// `TokenTree::Repeat`, where we use `push_nested` to create the desired
/// nesting structure.
///
/// The other side of the puzzle is `expand_subtree`, where we use the bindings
/// to substitute meta variables in the output template. When expanding, we
/// maintain a `nesteing` stack of indicies whihc tells us which occurence from
/// the `Bindings` we should take. We push to the stack when we enter a
/// repetition.
///
/// In other words, `Bindings` is a *multi* mapping from `SmolStr` to
/// `tt::TokenTree`, where the index to select a particular `TokenTree` among
/// many is not a plain `usize`, but an `&[usize]`.
#[derive(Debug, Default)]
struct Bindings {
    inner: FxHashMap<SmolStr, Binding>,
}

#[derive(Debug)]
enum Binding {
    Simple(tt::TokenTree),
    Nested(Vec<Binding>),
}

impl Bindings {
    fn get(&self, name: &SmolStr, nesting: &[usize]) -> Option<&tt::TokenTree> {
        let mut b = self.inner.get(name)?;
        for &idx in nesting.iter() {
            b = match b {
                Binding::Simple(_) => break,
                Binding::Nested(bs) => bs.get(idx)?,
            };
        }
        match b {
            Binding::Simple(it) => Some(it),
            Binding::Nested(_) => None,
        }
    }
    fn push_nested(&mut self, nested: Bindings) -> Option<()> {
        for (key, value) in nested.inner {
            if !self.inner.contains_key(&key) {
                self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
            }
            match self.inner.get_mut(&key) {
                Some(Binding::Nested(it)) => it.push(value),
                _ => return None,
            }
        }
        Some(())
    }
}

fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Option<Bindings> {
    let mut res = Bindings::default();
    for pat in pattern.token_trees.iter() {
        match pat {
            crate::TokenTree::Leaf(leaf) => match leaf {
                crate::Leaf::Var(crate::Var { text, kind }) => {
                    let kind = kind.clone()?;
                    match kind.as_str() {
                        "ident" => {
                            let ident = input.eat_ident()?.clone();
                            res.inner.insert(
                                text.clone(),
                                Binding::Simple(tt::Leaf::from(ident).into()),
                            );
                        }
                        _ => return None,
                    }
                }
                crate::Leaf::Punct(punct) => {
                    if input.eat_punct()? != punct {
                        return None;
                    }
                }
                crate::Leaf::Ident(ident) => {
                    if input.eat_ident()?.text != ident.text {
                        return None;
                    }
                }
                _ => return None,
            },
            crate::TokenTree::Repeat(crate::Repeat {
                subtree,
                kind: _,
                separator,
            }) => {
                while let Some(nested) = match_lhs(subtree, input) {
                    res.push_nested(nested)?;
                    if let Some(separator) = *separator {
                        if !input.is_eof() {
                            if input.eat_punct()?.char != separator {
                                return None;
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }
    Some(res)
}

fn expand_subtree(
    template: &crate::Subtree,
    bindings: &Bindings,
    nesting: &mut Vec<usize>,
) -> Option<tt::Subtree> {
    let token_trees = template
        .token_trees
        .iter()
        .map(|it| expand_tt(it, bindings, nesting))
        .collect::<Option<Vec<_>>>()?;

    Some(tt::Subtree {
        token_trees,
        delimiter: template.delimiter,
    })
}

fn expand_tt(
    template: &crate::TokenTree,
    bindings: &Bindings,
    nesting: &mut Vec<usize>,
) -> Option<tt::TokenTree> {
    let res: tt::TokenTree = match template {
        crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(),
        crate::TokenTree::Repeat(repeat) => {
            let mut token_trees = Vec::new();
            nesting.push(0);
            while let Some(t) = expand_subtree(&repeat.subtree, bindings, nesting) {
                let idx = nesting.pop().unwrap();
                nesting.push(idx + 1);
                token_trees.push(t.into())
            }
            nesting.pop().unwrap();
            tt::Subtree {
                token_trees,
                delimiter: tt::Delimiter::None,
            }
            .into()
        }
        crate::TokenTree::Leaf(leaf) => match leaf {
            crate::Leaf::Ident(ident) => tt::Leaf::from(tt::Ident {
                text: ident.text.clone(),
            })
            .into(),
            crate::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(),
            crate::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(),
            crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal {
                text: l.text.clone(),
            })
            .into(),
        },
    };
    Some(res)
}
<commit_msg>avoid 'ignored' in test output<commit_after>/// This module takes a (parsed) defenition of `macro_rules` invocation, a
/// `tt::TokenTree` representing an argument of macro invocation, and produces a
/// `tt::TokenTree` for the result of the expansion.
use rustc_hash::FxHashMap;
use ra_syntax::SmolStr;

use crate::tt_cursor::TtCursor;

pub(crate) fn exapnd(rules: &crate::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> {
    rules.rules.iter().find_map(|it| expand_rule(it, input))
}

fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Option<tt::Subtree> {
    let mut input = TtCursor::new(input);
    let bindings = match_lhs(&rule.lhs, &mut input)?;
    if !input.is_eof() {
        return None;
    }
    expand_subtree(&rule.rhs, &bindings, &mut Vec::new())
}

/// The actual algorithm for expansion is not too hard, but is pretty tricky.
/// `Bindings` structure is the key to understanding what we are doing here.
///
/// On the high level, it stores mapping from meta variables to the bits of
/// syntax it should be substituted with. For example, if `$e:expr` is matched
/// with `1 + 1` by macro_rules, the `Binding` will store `$e -> 1 + 1`.
///
/// The tricky bit is dealing with repetitions (`$()*`). Consider this example:
///
/// ```not_rust
/// macro_rules! foo {
///     ($($ i:ident $($ e:expr),*);*) => {
///         $(fn $ i() { $($ e);*; })*
///     }
/// }
/// foo! { foo 1,2,3; bar 4,5,6 }
/// ```
///
/// Here, the `$i` meta variable is matched first with `foo` and then with
/// `bar`, and `$e` is matched in turn with `1`, `2`, `3`, `4`, `5`, `6`.
///
/// To represent such "multi-mappings", we use a recursive structures: we map
/// variables not to values, but to *lists* of values or other lists (that is,
/// to the trees).
///
/// For the above example, the bindings would store
///
/// ```not_rust
/// i -> [foo, bar]
/// e -> [[1, 2, 3], [4, 5, 6]]
/// ```
///
/// We construct `Bindings` in the `match_lhs`. The interesting case is
/// `TokenTree::Repeat`, where we use `push_nested` to create the desired
/// nesting structure.
///
/// The other side of the puzzle is `expand_subtree`, where we use the bindings
/// to substitute meta variables in the output template. When expanding, we
/// maintain a `nesteing` stack of indicies whihc tells us which occurence from
/// the `Bindings` we should take. We push to the stack when we enter a
/// repetition.
///
/// In other words, `Bindings` is a *multi* mapping from `SmolStr` to
/// `tt::TokenTree`, where the index to select a particular `TokenTree` among
/// many is not a plain `usize`, but an `&[usize]`.
#[derive(Debug, Default)]
struct Bindings {
    inner: FxHashMap<SmolStr, Binding>,
}

#[derive(Debug)]
enum Binding {
    Simple(tt::TokenTree),
    Nested(Vec<Binding>),
}

impl Bindings {
    fn get(&self, name: &SmolStr, nesting: &[usize]) -> Option<&tt::TokenTree> {
        let mut b = self.inner.get(name)?;
        for &idx in nesting.iter() {
            b = match b {
                Binding::Simple(_) => break,
                Binding::Nested(bs) => bs.get(idx)?,
            };
        }
        match b {
            Binding::Simple(it) => Some(it),
            Binding::Nested(_) => None,
        }
    }
    fn push_nested(&mut self, nested: Bindings) -> Option<()> {
        for (key, value) in nested.inner {
            if !self.inner.contains_key(&key) {
                self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
            }
            match self.inner.get_mut(&key) {
                Some(Binding::Nested(it)) => it.push(value),
                _ => return None,
            }
        }
        Some(())
    }
}

fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Option<Bindings> {
    let mut res = Bindings::default();
    for pat in pattern.token_trees.iter() {
        match pat {
            crate::TokenTree::Leaf(leaf) => match leaf {
                crate::Leaf::Var(crate::Var { text, kind }) => {
                    let kind = kind.clone()?;
                    match kind.as_str() {
                        "ident" => {
                            let ident = input.eat_ident()?.clone();
                            res.inner.insert(
                                text.clone(),
                                Binding::Simple(tt::Leaf::from(ident).into()),
                            );
                        }
                        _ => return None,
                    }
                }
                crate::Leaf::Punct(punct) => {
                    if input.eat_punct()? != punct {
                        return None;
                    }
                }
                crate::Leaf::Ident(ident) => {
                    if input.eat_ident()?.text != ident.text {
                        return None;
                    }
                }
                _ => return None,
            },
            crate::TokenTree::Repeat(crate::Repeat {
                subtree,
                kind: _,
                separator,
            }) => {
                while let Some(nested) = match_lhs(subtree, input) {
                    res.push_nested(nested)?;
                    if let Some(separator) = *separator {
                        if !input.is_eof() {
                            if input.eat_punct()?.char != separator {
                                return None;
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }
    Some(res)
}

fn expand_subtree(
    template: &crate::Subtree,
    bindings: &Bindings,
    nesting: &mut Vec<usize>,
) -> Option<tt::Subtree> {
    let token_trees = template
        .token_trees
        .iter()
        .map(|it| expand_tt(it, bindings, nesting))
        .collect::<Option<Vec<_>>>()?;

    Some(tt::Subtree {
        token_trees,
        delimiter: template.delimiter,
    })
}

fn expand_tt(
    template: &crate::TokenTree,
    bindings: &Bindings,
    nesting: &mut Vec<usize>,
) -> Option<tt::TokenTree> {
    let res: tt::TokenTree = match template {
        crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, bindings, nesting)?.into(),
        crate::TokenTree::Repeat(repeat) => {
            let mut token_trees = Vec::new();
            nesting.push(0);
            while let Some(t) = expand_subtree(&repeat.subtree, bindings, nesting) {
                let idx = nesting.pop().unwrap();
                nesting.push(idx + 1);
                token_trees.push(t.into())
            }
            nesting.pop().unwrap();
            tt::Subtree {
                token_trees,
                delimiter: tt::Delimiter::None,
            }
            .into()
        }
        crate::TokenTree::Leaf(leaf) => match leaf {
            crate::Leaf::Ident(ident) => tt::Leaf::from(tt::Ident {
                text: ident.text.clone(),
            })
            .into(),
            crate::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(),
            crate::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(),
            crate::Leaf::Literal(l) => tt::Leaf::from(tt::Literal {
                text: l.text.clone(),
            })
            .into(),
        },
    };
    Some(res)
}
<|endoftext|>


<commit_before>pub struct Document;

impl Document {
    pub fn new(path: &Path) {
        println!("Creating Document from path {}", path.as_str().unwrap());
    }
}
<commit_msg>Implemented Document::new which returns a new document with attributes of type Vec<(String, String)> and content of type String<commit_after>pub struct Document {
    attributes: Vec<(String, String)>,
    content: String,
}

impl Document {
    pub fn new(attributes: Vec<(String, String)>, content: String) -> Document {
        Document {
            attributes: attributes,
            content: content,
        }
    }
}
<|endoftext|>