<commit_before>use std::char;
use std::collections::BTreeSet;
use std::iter::FromIterator;

use fst::Map;

const BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/unicode/name_fst.bin"));
include!(concat!(env!("OUT_DIR"), "/unicode/names.rs"));

fn query_fst(word: &str) -> Vec<char> {
    lazy_static! {
        static ref FST: Map = Map::from_bytes(BYTES.to_owned()).unwrap();
    }

    let mut chars: Vec<char> = vec![];
    if let Some(cp) = FST.get(word) {
        if cp & (0xff << 32) != 0 {
            let index: usize = (cp as u32) as usize;
            for ch in AMBIGUOUS_CHARS[index].chars() {
                chars.push(ch);
            }
        } else if let Some(ch) = char::from_u32(cp as u32) {
            chars.push(ch)
        }
    }
    chars
}

pub fn lookup_by_query(query: &str) -> Vec<char> {
    let query = query.to_lowercase();
    // try the original query first:
    let original_results = query_fst(query.as_str());
    if !original_results.is_empty() {
        return original_results;
    }

    let mut candidates = BTreeSet::new();
    if query.contains(char::is_whitespace) {
        // Split multiple-word queries, AND them together:
        let mut words = query.split_whitespace();
        if let Some(word) = words.next() {
            for ch in query_fst(word) {
                candidates.insert(ch);
            }
        }
        for word in words {
            let mut merge_candidates = BTreeSet::new();
            for ch in query_fst(word) {
                merge_candidates.insert(ch);
            }
            candidates = BTreeSet::from_iter(candidates.intersection(&merge_candidates).cloned());
            if candidates.is_empty() {
                return vec![];
            }
        }
    }
    candidates.into_iter().collect()
}
<commit_msg>Adjust the type signature / constructor to use for fst::Map<commit_after>use std::char;
use std::collections::BTreeSet;
use std::iter::FromIterator;

use fst::Map;

const BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/unicode/name_fst.bin"));
include!(concat!(env!("OUT_DIR"), "/unicode/names.rs"));

fn query_fst(word: &str) -> Vec<char> {
    lazy_static! {
        static ref FST: Map<Vec<u8>> = Map::new(BYTES.to_owned()).unwrap();
    }

    let mut chars: Vec<char> = vec![];
    if let Some(cp) = FST.get(word) {
        if cp & (0xff << 32) != 0 {
            let index: usize = (cp as u32) as usize;
            for ch in AMBIGUOUS_CHARS[index].chars() {
                chars.push(ch);
            }
        } else if let Some(ch) = char::from_u32(cp as u32) {
            chars.push(ch)
        }
    }
    chars
}

pub fn lookup_by_query(query: &str) -> Vec<char> {
    let query = query.to_lowercase();
    // try the original query first:
    let original_results = query_fst(query.as_str());
    if !original_results.is_empty() {
        return original_results;
    }

    let mut candidates = BTreeSet::new();
    if query.contains(char::is_whitespace) {
        // Split multiple-word queries, AND them together:
        let mut words = query.split_whitespace();
        if let Some(word) = words.next() {
            for ch in query_fst(word) {
                candidates.insert(ch);
            }
        }
        for word in words {
            let mut merge_candidates = BTreeSet::new();
            for ch in query_fst(word) {
                merge_candidates.insert(ch);
            }
            candidates = BTreeSet::from_iter(candidates.intersection(&merge_candidates).cloned());
            if candidates.is_empty() {
                return vec![];
            }
        }
    }
    candidates.into_iter().collect()
}
<|endoftext|>


<commit_before>extern crate futures;

use actix_web::{http, App, AsyncResponder, Error, HttpRequest, HttpResponse};
use chrono::naive::serde::ts_seconds;
use chrono::prelude::*;
use serde_json::Value;

use self::futures::Future;
use actix_state::State;
use build_info;
use data::TypeIdentifiable;
use data::*;
use repo_actor::*;

pub fn mount(app: App<State>) -> App<State> {
    app.route("/api/data", http::Method::GET, get_data).route(
        "/version",
        http::Method::GET,
        |_: HttpRequest<State>| build_info::build_version(),
    )
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct DataResponse {
    #[serde(with = "ts_seconds")]
    revision: NaiveDateTime,
    deletions: Vec<Resource>,
    changes: Vec<DataChange>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct DataChange {
    resource: Resource,
    data: Value,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct Resource {
    id: i32,

    #[serde(rename = "type")]
    _type: String,
}

fn get_data(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
    let now = Utc::now().naive_utc();

    let db = &req.state().db;

    let req_1 = db.send(GetNoteBooksMessage {
        since_revision: now,
    });
    let req_2 = db.send(GetNotesMessage {
        since_revision: now,
    });
    let req_3 = db.send(GetContentBlocksMessage {
        since_revision: now,
    });
    let req_4 = db.send(GetDeletionsMessage {
        since_revision: now,
    });

    req_1
        .join4(req_2, req_3, req_4)
        .from_err()
        .and_then(move |res| match res {
            (Ok(notebooks), Ok(notes), Ok(content_blocks), Ok(deleted_records)) => {
                let data_response =
                    build_response(notebooks, notes, content_blocks, deleted_records);
                Ok(HttpResponse::Ok().json(data_response))
            }
            _ => Ok(HttpResponse::InternalServerError().into()),
        })
        .responder()
}

fn build_response(
    notebooks: Vec<Notebook>,
    notes: Vec<Note>,
    content_blocks: Vec<ContentBlock>,
    deleted_records: Vec<Deletion>,
) -> DataResponse {
    // FIXME
    let now = Utc::now().naive_utc();

    let notebook_changes: Vec<DataChange> = notebooks
        .iter()
        .map(|n| DataChange {
            data: json!(n),
            resource: Resource {
                id: n.id,
                _type: n.type_name().into(),
            },
        })
        .collect();

    let mut note_changes: Vec<DataChange> = notes
        .iter()
        .map(|n| DataChange {
            data: json!(n),
            resource: Resource {
                id: n.id,
                _type: n.type_name().into(),
            },
        })
        .collect();

    let mut content_changes: Vec<DataChange> = content_blocks
        .iter()
        .map(|c| DataChange {
            data: json!(c),
            resource: Resource {
                id: c.id,
                _type: c.type_name().into(),
            },
        })
        .collect();

    let mut changes = notebook_changes;
    changes.append(&mut note_changes);
    changes.append(&mut content_changes);

    let deletions: Vec<Resource> = deleted_records
        .iter()
        .map(|d| Resource {
            id: d.id,
            _type: d._type.clone(),
        })
        .collect();

    DataResponse {
        revision: now,
        deletions: deletions,
        changes: changes,
    }
}
<commit_msg>Improve formatting of API routes<commit_after>extern crate futures;

use actix_web::http::Method;
use actix_web::{App, AsyncResponder, Error, HttpRequest, HttpResponse};
use chrono::naive::serde::ts_seconds;
use chrono::prelude::*;
use serde_json::Value;

use self::futures::Future;
use actix_state::State;
use build_info;
use data::TypeIdentifiable;
use data::*;
use repo_actor::*;

pub fn mount(app: App<State>) -> App<State> {
    #[cfg_attr(rustfmt, rustfmt_skip)]
    app.route("/api/data", Method::GET, get_data)
       .route("/version", Method::GET, |_: HttpRequest<State>|
           build_info::build_version()
       )
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct DataResponse {
    #[serde(with = "ts_seconds")]
    revision: NaiveDateTime,
    deletions: Vec<Resource>,
    changes: Vec<DataChange>,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct DataChange {
    resource: Resource,
    data: Value,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct Resource {
    id: i32,

    #[serde(rename = "type")]
    _type: String,
}

fn get_data(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
    let now = Utc::now().naive_utc();

    let db = &req.state().db;

    let req_1 = db.send(GetNoteBooksMessage {
        since_revision: now,
    });
    let req_2 = db.send(GetNotesMessage {
        since_revision: now,
    });
    let req_3 = db.send(GetContentBlocksMessage {
        since_revision: now,
    });
    let req_4 = db.send(GetDeletionsMessage {
        since_revision: now,
    });

    req_1
        .join4(req_2, req_3, req_4)
        .from_err()
        .and_then(move |res| match res {
            (Ok(notebooks), Ok(notes), Ok(content_blocks), Ok(deleted_records)) => {
                let data_response =
                    build_response(notebooks, notes, content_blocks, deleted_records);
                Ok(HttpResponse::Ok().json(data_response))
            }
            _ => Ok(HttpResponse::InternalServerError().into()),
        })
        .responder()
}

fn build_response(
    notebooks: Vec<Notebook>,
    notes: Vec<Note>,
    content_blocks: Vec<ContentBlock>,
    deleted_records: Vec<Deletion>,
) -> DataResponse {
    let notebook_changes: Vec<DataChange> = notebooks
        .iter()
        .map(|n| DataChange {
            data: json!(n),
            resource: Resource {
                id: n.id,
                _type: n.type_name().into(),
            },
        })
        .collect();

    let mut note_changes: Vec<DataChange> = notes
        .iter()
        .map(|n| DataChange {
            data: json!(n),
            resource: Resource {
                id: n.id,
                _type: n.type_name().into(),
            },
        })
        .collect();

    let mut content_changes: Vec<DataChange> = content_blocks
        .iter()
        .map(|c| DataChange {
            data: json!(c),
            resource: Resource {
                id: c.id,
                _type: c.type_name().into(),
            },
        })
        .collect();

    let mut changes = notebook_changes;
    changes.append(&mut note_changes);
    changes.append(&mut content_changes);

    let deletions: Vec<Resource> = deleted_records
        .iter()
        .map(|d| Resource {
            id: d.id,
            _type: d._type.clone(),
        })
        .collect();

    // FIXME
    let revision = Utc::now().naive_utc();

    DataResponse {
        revision: revision,
        deletions: deletions,
        changes: changes,
    }
}
<|endoftext|>


<commit_before>fn main() {
    let s = "Hello, <TYPO descr="Typo: In word 'Wodlr'">W\u{6F}dlr</TYPO>!";
    let s = "Hello, <TYPO descr="Typo: In word 'Wodlr'">W\x6Fdlr</TYPO>!";
}
<commit_msg>(T): fix spellcheck test for the next EAP.<commit_after>fn main() {
    let s = "Hello, <TYPO>W\u{6F}dlr</TYPO>!";
    let s = "Hello, <TYPO>W\x6Fdlr</TYPO>!";
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fmt::{self, Display};
use std::io;
use std::result;

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(&self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        io::Error::from_raw_os_error(self.0).fmt(f)
    }
}

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}

/// Sets errno to given error code.
/// Only defined when we compile tests as normal code does not
/// normally need set errno.
#[cfg(test)]
pub fn set_errno(e: i32) {
    unsafe {
        *__errno_location() = e;
    }
}
<commit_msg>sys_util: errno: Make clippy clean<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fmt::{self, Display};
use std::io;
use std::result;

use libc::__errno_location;

/// An error number, retrieved from errno (man 3 errno), set by a libc
/// function that returned an error.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Error(i32);
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Constructs a new error with the given errno.
    pub fn new(e: i32) -> Error {
        Error(e)
    }

    /// Constructs an error from the current errno.
    ///
    /// The result of this only has any meaning just after a libc call that returned a value
    /// indicating errno was set.
    pub fn last() -> Error {
        Error(unsafe { *__errno_location() })
    }

    /// Gets the errno for this error
    pub fn errno(self) -> i32 {
        self.0
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        io::Error::from_raw_os_error(self.0).fmt(f)
    }
}

/// Returns the last errno as a Result that is always an error.
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}

/// Sets errno to given error code.
/// Only defined when we compile tests as normal code does not
/// normally need set errno.
#[cfg(test)]
pub fn set_errno(e: i32) {
    unsafe {
        *__errno_location() = e;
    }
}
<|endoftext|>


<commit_before>

use protocol::*;
use std::io::Read;

use xml::EventReader;
use xml::attribute::OwnedAttribute;
use xml::reader::Events;
use xml::reader::ParserConfig;
use xml::reader::XmlEvent;

macro_rules! extract_from(
    ($it: expr => $pattern: pat => $result: expr) => (
        match $it.next() {
            Some(Ok($pattern)) => { $result },
            e => panic!("Ill-formed protocol file: {:?}", e)
        }
    )
);

macro_rules! extract_end_tag(
    ($it: expr => $tag: expr) => (
        extract_from!($it => XmlEvent::EndElement { name } => {
            assert!(name.local_name == $tag, "Ill-formed protocol file");
        });
    )
);

pub fn parse_stream<S: Read>(stream: S) -> Protocol {
    let reader = EventReader::new_with_config(stream, ParserConfig::new().trim_whitespace(true));
    let mut iter = reader.into_iter();
    iter.next(); // StartDocument
    let mut protocol = parse_protocol(iter);

    // yay, hardcoding things
    if protocol.name == "wayland" {
        // wl_callback has actually a destructor *event*, but the wayland specification
        // format does not handle this.
        // Luckily, wayland-scanner does, so we inject it
        for interface in &mut protocol.interfaces {
            if interface.name == "wl_callback" {
                let done_event = &mut interface.events[0];
                assert!(done_event.name == "done");
                done_event.typ = Some(Type::Destructor);
            }
        }
    }

    protocol
}

fn parse_protocol<'a, S: Read + 'a>(mut iter: Events<S>) -> Protocol {
    let mut protocol =
        extract_from!(
        iter => XmlEvent::StartElement { name, attributes, .. } => {
            assert!(name.local_name == "protocol", "Missing protocol toplevel tag");
            assert!(attributes[0].name.local_name == "name", "Protocol must have a name");
            Protocol::new(attributes[0].value.clone())
        }
    );

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "copyright" => {
                        // parse the copyright
                        let copyright = extract_from!(iter => XmlEvent::Characters(copyright) => copyright);
                        extract_end_tag!(iter => "copyright");
                        protocol.copyright = Some(copyright);
                    }
                    "interface" => {
                        protocol.interfaces.push(
                            parse_interface(&mut iter, attributes),
                        );
                    }
                    "description" => {
                        protocol.description = Some(parse_description(&mut iter, attributes));
                    }
                    _ => {
                        panic!(
                            "Ill-formed protocol file: unexpected token `{}` in protocol {}",
                            name.local_name,
                            protocol.name
                        )
                    }
                }
            }
            Some(Ok(XmlEvent::EndElement { name })) => {
                assert!(
                    name.local_name == "protocol",
                    "Unexpected closing token `{}`",
                    name.local_name
                );
                break;
            }
            e => panic!("Ill-formed protocol file: {:?}", e),
        }
    }

    protocol
}

fn parse_interface<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Interface {
    let mut interface = Interface::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => interface.name = attr.value,
            "version" => interface.version = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => interface.description = Some(parse_description(iter, attributes)),
                    "request" => interface.requests.push(parse_request(iter, attributes)),
                    "event" => interface.events.push(parse_event(iter, attributes)),
                    "enum" => interface.enums.push(parse_enum(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "interface" => break,
            _ => {}
        }
    }

    interface
}

fn parse_description<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> (String, String) {
    let mut summary = String::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "summary" => summary = attr.value,
            _ => {}
        }
    }

    let description = match iter.next() {
        Some(Ok(XmlEvent::Characters(txt))) => {
            extract_end_tag!(iter => "description");
            txt
        }
        Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "description" => String::new(),
        e => panic!("Ill-formed protocol file: {:?}", e),
    };

    (summary, description)
}

fn parse_request<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Message {
    let mut request = Message::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => request.name = attr.value,
            "type" => request.typ = Some(parse_type(&attr.value)),
            "since" => request.since = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => request.description = Some(parse_description(iter, attributes)),
                    "arg" => request.args.push(parse_arg(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "request" => break,
            _ => {}
        }
    }

    request
}

fn parse_enum<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Enum {
    let mut enu = Enum::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => enu.name = attr.value,
            "since" => enu.since = attr.value.parse().unwrap(),
            "bitfield" => {
                if &attr.value[..] == "true" {
                    enu.bitfield = true
                }
            }
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => enu.description = Some(parse_description(iter, attributes)),
                    "entry" => enu.entries.push(parse_entry(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "enum" => break,
            _ => {}
        }
    }

    enu
}

fn parse_event<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Message {
    let mut event = Message::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => event.name = attr.value,
            "since" => event.since = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => event.description = Some(parse_description(iter, attributes)),
                    "arg" => event.args.push(parse_arg(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "event" => break,
            _ => {}
        }
    }

    event
}

fn parse_arg<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Arg {
    let mut arg = Arg::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => arg.name = attr.value,
            "type" => arg.typ = parse_type(&attr.value),
            "summary" => arg.summary = Some(attr.value),
            "interface" => arg.interface = Some(attr.value),
            "allow-null" => {
                if attr.value == "true" {
                    arg.allow_null = true
                }
            }
            "enum" => arg.enum_ = Some(attr.value),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => arg.description = Some(parse_description(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "arg" => break,
            _ => {}
        }
    }

    arg
}

fn parse_type(txt: &str) -> Type {
    match txt {
        "int" => Type::Int,
        "uint" => Type::Uint,
        "fixed" => Type::Fixed,
        "string" => Type::String,
        "object" => Type::Object,
        "new_id" => Type::NewId,
        "array" => Type::Array,
        "fd" => Type::Fd,
        "destructor" => Type::Destructor,
        e => panic!("Unexpected type: {}", e),
    }
}

fn parse_entry<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Entry {
    let mut entry = Entry::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => entry.name = attr.value,
            "value" => entry.value = attr.value,
            "since" => entry.since = attr.value.parse().unwrap(),
            "summary" => entry.summary = Some(attr.value),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => entry.description = Some(parse_description(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "entry" => break,
            _ => {}
        }
    }

    entry
}
<commit_msg>scanner: normalize whitespaces in doc summary<commit_after>

use protocol::*;
use std::io::Read;

use xml::EventReader;
use xml::attribute::OwnedAttribute;
use xml::reader::Events;
use xml::reader::ParserConfig;
use xml::reader::XmlEvent;

macro_rules! extract_from(
    ($it: expr => $pattern: pat => $result: expr) => (
        match $it.next() {
            Some(Ok($pattern)) => { $result },
            e => panic!("Ill-formed protocol file: {:?}", e)
        }
    )
);

macro_rules! extract_end_tag(
    ($it: expr => $tag: expr) => (
        extract_from!($it => XmlEvent::EndElement { name } => {
            assert!(name.local_name == $tag, "Ill-formed protocol file");
        });
    )
);

pub fn parse_stream<S: Read>(stream: S) -> Protocol {
    let reader = EventReader::new_with_config(stream, ParserConfig::new().trim_whitespace(true));
    let mut iter = reader.into_iter();
    iter.next(); // StartDocument
    let mut protocol = parse_protocol(iter);

    // yay, hardcoding things
    if protocol.name == "wayland" {
        // wl_callback has actually a destructor *event*, but the wayland specification
        // format does not handle this.
        // Luckily, wayland-scanner does, so we inject it
        for interface in &mut protocol.interfaces {
            if interface.name == "wl_callback" {
                let done_event = &mut interface.events[0];
                assert!(done_event.name == "done");
                done_event.typ = Some(Type::Destructor);
            }
        }
    }

    protocol
}

fn parse_protocol<'a, S: Read + 'a>(mut iter: Events<S>) -> Protocol {
    let mut protocol =
        extract_from!(
        iter => XmlEvent::StartElement { name, attributes, .. } => {
            assert!(name.local_name == "protocol", "Missing protocol toplevel tag");
            assert!(attributes[0].name.local_name == "name", "Protocol must have a name");
            Protocol::new(attributes[0].value.clone())
        }
    );

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "copyright" => {
                        // parse the copyright
                        let copyright = extract_from!(iter => XmlEvent::Characters(copyright) => copyright);
                        extract_end_tag!(iter => "copyright");
                        protocol.copyright = Some(copyright);
                    }
                    "interface" => {
                        protocol.interfaces.push(
                            parse_interface(&mut iter, attributes),
                        );
                    }
                    "description" => {
                        protocol.description = Some(parse_description(&mut iter, attributes));
                    }
                    _ => {
                        panic!(
                            "Ill-formed protocol file: unexpected token `{}` in protocol {}",
                            name.local_name,
                            protocol.name
                        )
                    }
                }
            }
            Some(Ok(XmlEvent::EndElement { name })) => {
                assert!(
                    name.local_name == "protocol",
                    "Unexpected closing token `{}`",
                    name.local_name
                );
                break;
            }
            e => panic!("Ill-formed protocol file: {:?}", e),
        }
    }

    protocol
}

fn parse_interface<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Interface {
    let mut interface = Interface::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => interface.name = attr.value,
            "version" => interface.version = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => interface.description = Some(parse_description(iter, attributes)),
                    "request" => interface.requests.push(parse_request(iter, attributes)),
                    "event" => interface.events.push(parse_event(iter, attributes)),
                    "enum" => interface.enums.push(parse_enum(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "interface" => break,
            _ => {}
        }
    }

    interface
}

fn parse_description<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> (String, String) {
    let mut summary = String::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "summary" => summary = attr.value.split_whitespace().collect::<Vec<_>>().join(" "),
            _ => {}
        }
    }

    let description = match iter.next() {
        Some(Ok(XmlEvent::Characters(txt))) => {
            extract_end_tag!(iter => "description");
            txt
        }
        Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "description" => String::new(),
        e => panic!("Ill-formed protocol file: {:?}", e),
    };

    (summary, description)
}

fn parse_request<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Message {
    let mut request = Message::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => request.name = attr.value,
            "type" => request.typ = Some(parse_type(&attr.value)),
            "since" => request.since = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => request.description = Some(parse_description(iter, attributes)),
                    "arg" => request.args.push(parse_arg(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "request" => break,
            _ => {}
        }
    }

    request
}

fn parse_enum<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Enum {
    let mut enu = Enum::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => enu.name = attr.value,
            "since" => enu.since = attr.value.parse().unwrap(),
            "bitfield" => {
                if &attr.value[..] == "true" {
                    enu.bitfield = true
                }
            }
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => enu.description = Some(parse_description(iter, attributes)),
                    "entry" => enu.entries.push(parse_entry(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "enum" => break,
            _ => {}
        }
    }

    enu
}

fn parse_event<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Message {
    let mut event = Message::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => event.name = attr.value,
            "since" => event.since = attr.value.parse().unwrap(),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => event.description = Some(parse_description(iter, attributes)),
                    "arg" => event.args.push(parse_arg(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "event" => break,
            _ => {}
        }
    }

    event
}

fn parse_arg<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Arg {
    let mut arg = Arg::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => arg.name = attr.value,
            "type" => arg.typ = parse_type(&attr.value),
            "summary" => arg.summary = Some(attr.value),
            "interface" => arg.interface = Some(attr.value),
            "allow-null" => {
                if attr.value == "true" {
                    arg.allow_null = true
                }
            }
            "enum" => arg.enum_ = Some(attr.value),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => arg.description = Some(parse_description(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "arg" => break,
            _ => {}
        }
    }

    arg
}

fn parse_type(txt: &str) -> Type {
    match txt {
        "int" => Type::Int,
        "uint" => Type::Uint,
        "fixed" => Type::Fixed,
        "string" => Type::String,
        "object" => Type::Object,
        "new_id" => Type::NewId,
        "array" => Type::Array,
        "fd" => Type::Fd,
        "destructor" => Type::Destructor,
        e => panic!("Unexpected type: {}", e),
    }
}

fn parse_entry<'a, S: Read + 'a>(iter: &mut Events<S>, attrs: Vec<OwnedAttribute>) -> Entry {
    let mut entry = Entry::new();
    for attr in attrs {
        match &attr.name.local_name[..] {
            "name" => entry.name = attr.value,
            "value" => entry.value = attr.value,
            "since" => entry.since = attr.value.parse().unwrap(),
            "summary" => entry.summary = Some(attr.value),
            _ => {}
        }
    }

    loop {
        match iter.next() {
            Some(Ok(XmlEvent::StartElement { name, attributes, .. })) => {
                match &name.local_name[..] {
                    "description" => entry.description = Some(parse_description(iter, attributes)),
                    _ => panic!("Unexpected tocken: `{}`", name.local_name),
                }
            }
            Some(Ok(XmlEvent::EndElement { ref name })) if name.local_name == "entry" => break,
            _ => {}
        }
    }

    entry
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms, clippy::all)]

use futures::{try_ready, Async, Future, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "runtime")]
use tokio_postgres::tls::MakeTlsConnect;
use tokio_postgres::tls::{ChannelBinding, TlsConnect};
use tokio_tls::{Connect, TlsStream};

#[cfg(test)]
mod test;

#[cfg(feature = "runtime")]
#[derive(Clone)]
pub struct MakeTlsConnector(native_tls::TlsConnector);

#[cfg(feature = "runtime")]
impl MakeTlsConnector {
    pub fn new(connector: native_tls::TlsConnector) -> MakeTlsConnector {
        MakeTlsConnector(connector)
    }
}

#[cfg(feature = "runtime")]
impl<S> MakeTlsConnect<S> for MakeTlsConnector
where
    S: AsyncRead + AsyncWrite,
{
    type Stream = TlsStream<S>;
    type TlsConnect = TlsConnector;
    type Error = native_tls::Error;

    fn make_tls_connect(&mut self, domain: &str) -> Result<TlsConnector, native_tls::Error> {
        Ok(TlsConnector::new(self.0.clone(), domain))
    }
}

pub struct TlsConnector {
    connector: tokio_tls::TlsConnector,
    domain: String,
}

impl TlsConnector {
    pub fn new(connector: native_tls::TlsConnector, domain: &str) -> TlsConnector {
        TlsConnector {
            connector: tokio_tls::TlsConnector::from(connector),
            domain: domain.to_string(),
        }
    }
}

impl<S> TlsConnect<S> for TlsConnector
where
    S: AsyncRead + AsyncWrite,
{
    type Stream = TlsStream<S>;
    type Error = native_tls::Error;
    type Future = TlsConnectFuture<S>;

    fn connect(self, stream: S) -> TlsConnectFuture<S> {
        TlsConnectFuture(self.connector.connect(&self.domain, stream))
    }
}

pub struct TlsConnectFuture<S>(Connect<S>);

impl<S> Future for TlsConnectFuture<S>
where
    S: AsyncRead + AsyncWrite,
{
    type Item = (TlsStream<S>, ChannelBinding);
    type Error = native_tls::Error;

    fn poll(&mut self) -> Poll<(TlsStream<S>, ChannelBinding), native_tls::Error> {
        let stream = try_ready!(self.0.poll());

        let channel_binding = match stream.get_ref().tls_server_end_point().unwrap_or(None) {
            Some(buf) => ChannelBinding::tls_server_end_point(buf),
            None => ChannelBinding::none(),
        };

        Ok(Async::Ready((stream, channel_binding)))
    }
}
<commit_msg>Document tokio-postgres-native-tls<commit_after>//! TLS support for `tokio-postgres` via `native-tls.
//!
//! # Example
//!
//! ```no_run
//! use native_tls::{Certificate, TlsConnector};
//! use tokio_postgres_native_tls::MakeTlsConnector;
//! use std::fs;
//!
//! let cert = fs::read("database_cert.pem").unwrap();
//! let cert = Certificate::from_pem(&cert).unwrap();
//! let connector = TlsConnector::builder()
//!     .add_root_certificate(cert)
//!     .build()
//!     .unwrap();
//! let connector = MakeTlsConnector::new(connector);
//!
//! let connect_future = tokio_postgres::connect(
//!     "host=localhost user=postgres sslmode=require",
//!     connector,
//! );
//!
//! // ...
//! ```

#![warn(rust_2018_idioms, clippy::all, missing_docs)]

use futures::{try_ready, Async, Future, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "runtime")]
use tokio_postgres::tls::MakeTlsConnect;
use tokio_postgres::tls::{ChannelBinding, TlsConnect};
use tokio_tls::{Connect, TlsStream};

#[cfg(test)]
mod test;

/// A `MakeTlsConnect` implementation using the `native-tls` crate.
///
/// Requires the `runtime` Cargo feature (enabled by default).
#[cfg(feature = "runtime")]
#[derive(Clone)]
pub struct MakeTlsConnector(native_tls::TlsConnector);

#[cfg(feature = "runtime")]
impl MakeTlsConnector {
    /// Creates a new connector.
    pub fn new(connector: native_tls::TlsConnector) -> MakeTlsConnector {
        MakeTlsConnector(connector)
    }
}

#[cfg(feature = "runtime")]
impl<S> MakeTlsConnect<S> for MakeTlsConnector
where
    S: AsyncRead + AsyncWrite,
{
    type Stream = TlsStream<S>;
    type TlsConnect = TlsConnector;
    type Error = native_tls::Error;

    fn make_tls_connect(&mut self, domain: &str) -> Result<TlsConnector, native_tls::Error> {
        Ok(TlsConnector::new(self.0.clone(), domain))
    }
}

/// A `TlsConnect` implementation using the `native-tls` crate.
pub struct TlsConnector {
    connector: tokio_tls::TlsConnector,
    domain: String,
}

impl TlsConnector {
    /// Creates a new connector configured to connect to the specified domain.
    pub fn new(connector: native_tls::TlsConnector, domain: &str) -> TlsConnector {
        TlsConnector {
            connector: tokio_tls::TlsConnector::from(connector),
            domain: domain.to_string(),
        }
    }
}

impl<S> TlsConnect<S> for TlsConnector
where
    S: AsyncRead + AsyncWrite,
{
    type Stream = TlsStream<S>;
    type Error = native_tls::Error;
    type Future = TlsConnectFuture<S>;

    fn connect(self, stream: S) -> TlsConnectFuture<S> {
        TlsConnectFuture(self.connector.connect(&self.domain, stream))
    }
}

/// The future returned by `TlsConnector`.
pub struct TlsConnectFuture<S>(Connect<S>);

impl<S> Future for TlsConnectFuture<S>
where
    S: AsyncRead + AsyncWrite,
{
    type Item = (TlsStream<S>, ChannelBinding);
    type Error = native_tls::Error;

    fn poll(&mut self) -> Poll<(TlsStream<S>, ChannelBinding), native_tls::Error> {
        let stream = try_ready!(self.0.poll());

        let channel_binding = match stream.get_ref().tls_server_end_point().unwrap_or(None) {
            Some(buf) => ChannelBinding::tls_server_end_point(buf),
            None => ChannelBinding::none(),
        };

        Ok(Async::Ready((stream, channel_binding)))
    }
}
<|endoftext|>


<commit_before>//! This module implements import-resolution/macro expansion algorithm.
//!
//! The result of this module is `CrateDefMap`: a data structure which contains:
//!
//!   * a tree of modules for the crate
//!   * for each module, a set of items visible in the module (directly declared
//!     or imported)
//!
//! Note that `CrateDefMap` contains fully macro expanded code.
//!
//! Computing `CrateDefMap` can be partitioned into several logically
//! independent "phases". The phases are mutually recursive though, there's no
//! strict ordering.
//!
//! ## Collecting RawItems
//!
//! This happens in the `raw` module, which parses a single source file into a
//! set of top-level items. Nested imports are desugared to flat imports in this
//! phase. Macro calls are represented as a triple of (Path, Option<Name>,
//! TokenTree).
//!
//! ## Collecting Modules
//!
//! This happens in the `collector` module. In this phase, we recursively walk
//! tree of modules, collect raw items from submodules, populate module scopes
//! with defined items (so, we assign item ids in this phase) and record the set
//! of unresolved imports and macros.
//!
//! While we walk tree of modules, we also record macro_rules definitions and
//! expand calls to macro_rules defined macros.
//!
//! ## Resolving Imports
//!
//! We maintain a list of currently unresolved imports. On every iteration, we
//! try to resolve some imports from this list. If the import is resolved, we
//! record it, by adding an item to current module scope and, if necessary, by
//! recursively populating glob imports.
//!
//! ## Resolving Macros
//!
//! macro_rules from the same crate use a global mutable namespace. We expand
//! them immediately, when we collect modules.
//!
//! Macros from other crates (including proc-macros) can be used with
//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
//! unexpanded macros. On every iteration, we try to resolve each macro call
//! path and, upon success, we run macro expansion and "collect module" phase on
//! the result

pub(crate) mod raw;
mod collector;
mod mod_resolution;
mod path_resolution;

#[cfg(test)]
mod tests;

use std::sync::Arc;

use hir_expand::{
    ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, InFile,
    MacroDefId,
};
use once_cell::sync::Lazy;
use ra_arena::Arena;
use ra_db::{CrateId, Edition, FileId};
use ra_prof::profile;
use ra_syntax::ast;
use rustc_hash::FxHashMap;

use crate::{
    builtin_type::BuiltinType,
    db::DefDatabase,
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::Path,
    per_ns::PerNs,
    AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
};

/// Contains all top-level defs from a macro-expanded crate
#[derive(Debug, PartialEq, Eq)]
pub struct CrateDefMap {
    pub root: LocalModuleId,
    pub modules: Arena<LocalModuleId, ModuleData>,
    pub(crate) krate: CrateId,
    /// The prelude module for this crate. This either comes from an import
    /// marked with the `prelude_import` attribute, or (in the normal case) from
    /// a dependency (`std` or `core`).
    pub(crate) prelude: Option<ModuleId>,
    pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,

    edition: Edition,
    diagnostics: Vec<DefDiagnostic>,
}

impl std::ops::Index<LocalModuleId> for CrateDefMap {
    type Output = ModuleData;
    fn index(&self, id: LocalModuleId) -> &ModuleData {
        &self.modules[id]
    }
}

#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleData {
    pub parent: Option<LocalModuleId>,
    pub children: FxHashMap<Name, LocalModuleId>,
    pub scope: ModuleScope,

    //  FIXME: these can't be both null, we need a three-state enum here.
    /// None for root
    pub declaration: Option<AstId<ast::Module>>,
    /// None for inline modules.
    ///
    /// Note that non-inline modules, by definition, live inside non-macro file.
    pub definition: Option<FileId>,

    pub impls: Vec<ImplId>,
}

#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct Declarations {
    fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ModuleScope {
    items: FxHashMap<Name, Resolution>,
    /// Macros visable in current module in legacy textual scope
    ///
    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| {
            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
        })
        .collect()
});

/// Shadow mode for builtin type
/// Builtin type can be shadowed by same name mode
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BuiltinShadowMode {
    // Prefer Module
    Module,
    // Prefer Other Types
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
        //FIXME: shadowing
        self.items.iter().chain(BUILTIN_SCOPE.iter())
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.entries()
            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
            .flat_map(|per_ns| {
                per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
            })
    }

    /// Iterate over all module scoped macros
    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.items
            .iter()
            .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visable at the end of the module
    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
        match shadow {
            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
            BuiltinShadowMode::Other => {
                let item = self.items.get(name);
                if let Some(res) = item {
                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
                        return BUILTIN_SCOPE.get(name).or(item);
                    }
                }

                item.or_else(|| BUILTIN_SCOPE.get(name))
            }
        }
    }

    pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.items.values().filter_map(|r| match r.def.take_types() {
            Some(ModuleDefId::TraitId(t)) => Some(t),
            _ => None,
        })
    }

    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Resolution {
    /// None for unresolved
    pub def: PerNs,
    /// ident by which this is imported into local scope.
    pub import: Option<LocalImportId>,
}

impl CrateDefMap {
    pub(crate) fn crate_def_map_query(
        // Note that this doesn't have `+ AstDatabase`!
        // This gurantess that `CrateDefMap` is stable across reparses.
        db: &impl DefDatabase,
        krate: CrateId,
    ) -> Arc<CrateDefMap> {
        let _p = profile("crate_def_map_query");
        let def_map = {
            let crate_graph = db.crate_graph();
            let edition = crate_graph.edition(krate);
            let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
            let root = modules.alloc(ModuleData::default());
            CrateDefMap {
                krate,
                edition,
                extern_prelude: FxHashMap::default(),
                prelude: None,
                root,
                modules,
                diagnostics: Vec::new(),
            }
        };
        let def_map = collector::collect_defs(db, def_map);
        Arc::new(def_map)
    }

    pub fn add_diagnostics(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        sink: &mut DiagnosticSink,
    ) {
        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
    }

    pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
        self.modules
            .iter()
            .filter(move |(_id, data)| data.definition == Some(file_id))
            .map(|(id, _data)| id)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl DefDatabase,
        original_module: LocalModuleId,
        path: &Path,
        shadow: BuiltinShadowMode,
    ) -> (PerNs, Option<usize>) {
        let res =
            self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
        (res.resolved_def, res.segment_index)
    }
}

impl ModuleData {
    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
    pub fn definition_source(
        &self,
        db: &impl DefDatabase,
    ) -> InFile<Either<ast::SourceFile, ast::Module>> {
        if let Some(file_id) = self.definition {
            let sf = db.parse(file_id).tree();
            return InFile::new(file_id.into(), Either::A(sf));
        }
        let decl = self.declaration.unwrap();
        InFile::new(decl.file_id, Either::B(decl.to_node(db)))
    }

    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
    /// `None` for the crate root.
    pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
        let decl = self.declaration?;
        let value = decl.to_node(db);
        Some(InFile { file_id: decl.file_id, value })
    }
}

mod diagnostics {
    use hir_expand::diagnostics::DiagnosticSink;
    use ra_db::RelativePathBuf;
    use ra_syntax::{ast, AstPtr};

    use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};

    #[derive(Debug, PartialEq, Eq)]
    pub(super) enum DefDiagnostic {
        UnresolvedModule {
            module: LocalModuleId,
            declaration: AstId<ast::Module>,
            candidate: RelativePathBuf,
        },
    }

    impl DefDiagnostic {
        pub(super) fn add_to(
            &self,
            db: &impl DefDatabase,
            target_module: LocalModuleId,
            sink: &mut DiagnosticSink,
        ) {
            match self {
                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
                    if *module != target_module {
                        return;
                    }
                    let decl = declaration.to_node(db);
                    sink.push(UnresolvedModule {
                        file: declaration.file_id,
                        decl: AstPtr::new(&decl),
                        candidate: candidate.clone(),
                    })
                }
            }
        }
    }
}
<commit_msg>Fix comment<commit_after>//! This module implements import-resolution/macro expansion algorithm.
//!
//! The result of this module is `CrateDefMap`: a data structure which contains:
//!
//!   * a tree of modules for the crate
//!   * for each module, a set of items visible in the module (directly declared
//!     or imported)
//!
//! Note that `CrateDefMap` contains fully macro expanded code.
//!
//! Computing `CrateDefMap` can be partitioned into several logically
//! independent "phases". The phases are mutually recursive though, there's no
//! strict ordering.
//!
//! ## Collecting RawItems
//!
//! This happens in the `raw` module, which parses a single source file into a
//! set of top-level items. Nested imports are desugared to flat imports in this
//! phase. Macro calls are represented as a triple of (Path, Option<Name>,
//! TokenTree).
//!
//! ## Collecting Modules
//!
//! This happens in the `collector` module. In this phase, we recursively walk
//! tree of modules, collect raw items from submodules, populate module scopes
//! with defined items (so, we assign item ids in this phase) and record the set
//! of unresolved imports and macros.
//!
//! While we walk tree of modules, we also record macro_rules definitions and
//! expand calls to macro_rules defined macros.
//!
//! ## Resolving Imports
//!
//! We maintain a list of currently unresolved imports. On every iteration, we
//! try to resolve some imports from this list. If the import is resolved, we
//! record it, by adding an item to current module scope and, if necessary, by
//! recursively populating glob imports.
//!
//! ## Resolving Macros
//!
//! macro_rules from the same crate use a global mutable namespace. We expand
//! them immediately, when we collect modules.
//!
//! Macros from other crates (including proc-macros) can be used with
//! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
//! unexpanded macros. On every iteration, we try to resolve each macro call
//! path and, upon success, we run macro expansion and "collect module" phase on
//! the result

pub(crate) mod raw;
mod collector;
mod mod_resolution;
mod path_resolution;

#[cfg(test)]
mod tests;

use std::sync::Arc;

use hir_expand::{
    ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, InFile,
    MacroDefId,
};
use once_cell::sync::Lazy;
use ra_arena::Arena;
use ra_db::{CrateId, Edition, FileId};
use ra_prof::profile;
use ra_syntax::ast;
use rustc_hash::FxHashMap;

use crate::{
    builtin_type::BuiltinType,
    db::DefDatabase,
    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
    path::Path,
    per_ns::PerNs,
    AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
};

/// Contains all top-level defs from a macro-expanded crate
#[derive(Debug, PartialEq, Eq)]
pub struct CrateDefMap {
    pub root: LocalModuleId,
    pub modules: Arena<LocalModuleId, ModuleData>,
    pub(crate) krate: CrateId,
    /// The prelude module for this crate. This either comes from an import
    /// marked with the `prelude_import` attribute, or (in the normal case) from
    /// a dependency (`std` or `core`).
    pub(crate) prelude: Option<ModuleId>,
    pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>,

    edition: Edition,
    diagnostics: Vec<DefDiagnostic>,
}

impl std::ops::Index<LocalModuleId> for CrateDefMap {
    type Output = ModuleData;
    fn index(&self, id: LocalModuleId) -> &ModuleData {
        &self.modules[id]
    }
}

#[derive(Default, Debug, PartialEq, Eq)]
pub struct ModuleData {
    pub parent: Option<LocalModuleId>,
    pub children: FxHashMap<Name, LocalModuleId>,
    pub scope: ModuleScope,

    //  FIXME: these can't be both null, we need a three-state enum here.
    /// None for root
    pub declaration: Option<AstId<ast::Module>>,
    /// None for inline modules.
    ///
    /// Note that non-inline modules, by definition, live inside non-macro file.
    pub definition: Option<FileId>,

    pub impls: Vec<ImplId>,
}

#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct Declarations {
    fns: FxHashMap<FileAstId<ast::FnDef>, FunctionId>,
}

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ModuleScope {
    items: FxHashMap<Name, Resolution>,
    /// Macros visable in current module in legacy textual scope
    ///
    /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
    /// If it yields no result, then it turns to module scoped `macros`.
    /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
    /// and only normal scoped `macros` will be searched in.
    ///
    /// Note that this automatically inherit macros defined textually before the definition of module itself.
    ///
    /// Module scoped macros will be inserted into `items` instead of here.
    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
    // be all resolved to the last one defined if shadowing happens.
    legacy_macros: FxHashMap<Name, MacroDefId>,
}

static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
    BuiltinType::ALL
        .iter()
        .map(|(name, ty)| {
            (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
        })
        .collect()
});

/// Shadow mode for builtin type which can be shadowed by module.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BuiltinShadowMode {
    // Prefer Module
    Module,
    // Prefer Other Types
    Other,
}

/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
/// Other methods will only resolve values, types and module scoped macros only.
impl ModuleScope {
    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
        //FIXME: shadowing
        self.items.iter().chain(BUILTIN_SCOPE.iter())
    }

    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
        self.entries()
            .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
            .flat_map(|per_ns| {
                per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
            })
    }

    /// Iterate over all module scoped macros
    pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.items
            .iter()
            .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
    }

    /// Iterate over all legacy textual scoped macros visable at the end of the module
    pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
        self.legacy_macros.iter().map(|(name, def)| (name, *def))
    }

    /// Get a name from current module scope, legacy macros are not included
    pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
        match shadow {
            BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
            BuiltinShadowMode::Other => {
                let item = self.items.get(name);
                if let Some(res) = item {
                    if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
                        return BUILTIN_SCOPE.get(name).or(item);
                    }
                }

                item.or_else(|| BUILTIN_SCOPE.get(name))
            }
        }
    }

    pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
        self.items.values().filter_map(|r| match r.def.take_types() {
            Some(ModuleDefId::TraitId(t)) => Some(t),
            _ => None,
        })
    }

    fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
        self.legacy_macros.get(name).copied()
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Resolution {
    /// None for unresolved
    pub def: PerNs,
    /// ident by which this is imported into local scope.
    pub import: Option<LocalImportId>,
}

impl CrateDefMap {
    pub(crate) fn crate_def_map_query(
        // Note that this doesn't have `+ AstDatabase`!
        // This gurantess that `CrateDefMap` is stable across reparses.
        db: &impl DefDatabase,
        krate: CrateId,
    ) -> Arc<CrateDefMap> {
        let _p = profile("crate_def_map_query");
        let def_map = {
            let crate_graph = db.crate_graph();
            let edition = crate_graph.edition(krate);
            let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
            let root = modules.alloc(ModuleData::default());
            CrateDefMap {
                krate,
                edition,
                extern_prelude: FxHashMap::default(),
                prelude: None,
                root,
                modules,
                diagnostics: Vec::new(),
            }
        };
        let def_map = collector::collect_defs(db, def_map);
        Arc::new(def_map)
    }

    pub fn add_diagnostics(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        sink: &mut DiagnosticSink,
    ) {
        self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
    }

    pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
        self.modules
            .iter()
            .filter(move |(_id, data)| data.definition == Some(file_id))
            .map(|(id, _data)| id)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl DefDatabase,
        original_module: LocalModuleId,
        path: &Path,
        shadow: BuiltinShadowMode,
    ) -> (PerNs, Option<usize>) {
        let res =
            self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
        (res.resolved_def, res.segment_index)
    }
}

impl ModuleData {
    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
    pub fn definition_source(
        &self,
        db: &impl DefDatabase,
    ) -> InFile<Either<ast::SourceFile, ast::Module>> {
        if let Some(file_id) = self.definition {
            let sf = db.parse(file_id).tree();
            return InFile::new(file_id.into(), Either::A(sf));
        }
        let decl = self.declaration.unwrap();
        InFile::new(decl.file_id, Either::B(decl.to_node(db)))
    }

    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
    /// `None` for the crate root.
    pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
        let decl = self.declaration?;
        let value = decl.to_node(db);
        Some(InFile { file_id: decl.file_id, value })
    }
}

mod diagnostics {
    use hir_expand::diagnostics::DiagnosticSink;
    use ra_db::RelativePathBuf;
    use ra_syntax::{ast, AstPtr};

    use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};

    #[derive(Debug, PartialEq, Eq)]
    pub(super) enum DefDiagnostic {
        UnresolvedModule {
            module: LocalModuleId,
            declaration: AstId<ast::Module>,
            candidate: RelativePathBuf,
        },
    }

    impl DefDiagnostic {
        pub(super) fn add_to(
            &self,
            db: &impl DefDatabase,
            target_module: LocalModuleId,
            sink: &mut DiagnosticSink,
        ) {
            match self {
                DefDiagnostic::UnresolvedModule { module, declaration, candidate } => {
                    if *module != target_module {
                        return;
                    }
                    let decl = declaration.to_node(db);
                    sink.push(UnresolvedModule {
                        file: declaration.file_id,
                        decl: AstPtr::new(&decl),
                        candidate: candidate.clone(),
                    })
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Code to handle a single block device.

use std::fs::OpenOptions;
use std::path::PathBuf;

use chrono::{DateTime, TimeZone, Utc};

use devicemapper::{Device, Sectors};

use super::super::engine::{BlockDev, HasUuid};
use super::super::errors::EngineResult;
use super::super::types::{BlockDevState, DevUuid, PoolUuid};

use super::metadata::BDA;
use super::range_alloc::RangeAllocator;
use super::serde_structs::{BlockDevSave, Recordable};

#[derive(Debug)]
pub struct StratBlockDev {
    dev: Device,
    pub devnode: PathBuf,
    bda: BDA,
    used: RangeAllocator,
    user_info: Option<String>,
    hardware_info: Option<String>,
}

impl StratBlockDev {
    pub fn new(dev: Device,
               devnode: PathBuf,
               bda: BDA,
               allocator: RangeAllocator,
               user_info: Option<String>,
               hardware_info: Option<String>)
               -> StratBlockDev {
        StratBlockDev {
            dev,
            devnode,
            bda,
            used: allocator,
            user_info,
            hardware_info,
        }
    }

    /// Returns the blockdev's Device
    pub fn device(&self) -> &Device {
        &self.dev
    }

    pub fn wipe_metadata(&self) -> EngineResult<()> {
        let mut f = OpenOptions::new().write(true).open(&self.devnode)?;
        BDA::wipe(&mut f)
    }

    pub fn save_state(&mut self, time: &DateTime<Utc>, metadata: &[u8]) -> EngineResult<()> {
        let mut f = OpenOptions::new().write(true).open(&self.devnode)?;
        self.bda.save_state(time, metadata, &mut f)
    }

    /// List the available-for-upper-layer-use range in this blockdev.
    pub fn avail_range(&self) -> (Sectors, Sectors) {
        let start = self.metadata_size();
        let size = self.current_capacity();
        // Blockdev size is at least MIN_DEV_SIZE, so this can fail only if
        // size of metadata area exceeds 1 GiB. Initial metadata area size
        // is 4 MiB.
        assert!(start <= size);
        (start, size - start)
    }

    /// The device's UUID.
    pub fn uuid(&self) -> DevUuid {
        self.bda.dev_uuid()
    }

    /// The device's pool's UUID.
    #[allow(dead_code)]
    pub fn pool_uuid(&self) -> PoolUuid {
        self.bda.pool_uuid()
    }

    /// Last time metadata was written to this device.
    #[allow(dead_code)]
    pub fn last_update_time(&self) -> Option<&DateTime<Utc>> {
        self.bda.last_update_time()
    }

    /// Find some sector ranges that could be allocated. If more
    /// sectors are needed than our capacity, return partial results.
    /// If all sectors are desired, use available() method to get all.
    pub fn request_space(&mut self, size: Sectors) -> (Sectors, Vec<(Sectors, Sectors)>) {
        self.used.request(size)
    }

    // ALL SIZE METHODS

    /// The size of the device as recorded in the metadata.
    #[allow(dead_code)]
    pub fn recorded_size(&self) -> Sectors {
        self.bda.dev_size()
    }

    /// The actual size of the device now.
    pub fn current_capacity(&self) -> Sectors {
        self.used.capacity()
    }

    /// The number of Sectors on this device used by Stratis for metadata
    pub fn metadata_size(&self) -> Sectors {
        self.bda.size()
    }

    /// The number of Sectors on this device not allocated for any purpose.
    /// self.current_capacity() - self.metadata_size() >= self.available()
    pub fn available(&self) -> Sectors {
        self.used.available()
    }

    /// The maximum size of variable length metadata that can be accommodated.
    /// self.max_metadata_size() < self.metadata_size()
    pub fn max_metadata_size(&self) -> Sectors {
        self.bda.max_data_size()
    }
}

impl HasUuid for StratBlockDev {
    fn uuid(&self) -> DevUuid {
        self.bda.dev_uuid()
    }
}

impl BlockDev for StratBlockDev {
    fn devnode(&self) -> PathBuf {
        self.devnode.clone()
    }

    fn user_info(&self) -> Option<&str> {
        self.user_info.as_ref().map(|x| &**x)
    }

    fn set_user_info(&mut self, user_info: Option<&str>) -> bool {
        set_blockdev_user_info!(self; user_info)
    }

    fn hardware_info(&self) -> Option<&str> {
        self.hardware_info.as_ref().map(|x| &**x)
    }

    fn initialization_time(&self) -> DateTime<Utc> {
        // This cast will result in an incorrect, negative value starting in
        // the year 292,277,026,596. :-)
        Utc.timestamp(self.bda.initialization_time() as i64, 0)
    }

    fn total_size(&self) -> Sectors {
        self.avail_range().1
    }

    fn state(&self) -> BlockDevState {
        // TODO: Implement states for blockdevs
        BlockDevState::InUse
    }
}

impl Recordable<BlockDevSave> for StratBlockDev {
    fn record(&self) -> BlockDevSave {
        BlockDevSave {
            devnode: Some(self.devnode.clone()),
            user_info: self.user_info.clone(),
            hardware_info: self.hardware_info.clone(),
        }
    }
}
<commit_msg>Get rid of StratBlockDev::avail_range entirely<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Code to handle a single block device.

use std::fs::OpenOptions;
use std::path::PathBuf;

use chrono::{DateTime, TimeZone, Utc};

use devicemapper::{Device, Sectors};

use super::super::engine::{BlockDev, HasUuid};
use super::super::errors::EngineResult;
use super::super::types::{BlockDevState, DevUuid, PoolUuid};

use super::metadata::BDA;
use super::range_alloc::RangeAllocator;
use super::serde_structs::{BlockDevSave, Recordable};

#[derive(Debug)]
pub struct StratBlockDev {
    dev: Device,
    pub devnode: PathBuf,
    bda: BDA,
    used: RangeAllocator,
    user_info: Option<String>,
    hardware_info: Option<String>,
}

impl StratBlockDev {
    pub fn new(dev: Device,
               devnode: PathBuf,
               bda: BDA,
               allocator: RangeAllocator,
               user_info: Option<String>,
               hardware_info: Option<String>)
               -> StratBlockDev {
        StratBlockDev {
            dev,
            devnode,
            bda,
            used: allocator,
            user_info,
            hardware_info,
        }
    }

    /// Returns the blockdev's Device
    pub fn device(&self) -> &Device {
        &self.dev
    }

    pub fn wipe_metadata(&self) -> EngineResult<()> {
        let mut f = OpenOptions::new().write(true).open(&self.devnode)?;
        BDA::wipe(&mut f)
    }

    pub fn save_state(&mut self, time: &DateTime<Utc>, metadata: &[u8]) -> EngineResult<()> {
        let mut f = OpenOptions::new().write(true).open(&self.devnode)?;
        self.bda.save_state(time, metadata, &mut f)
    }

    /// The device's UUID.
    pub fn uuid(&self) -> DevUuid {
        self.bda.dev_uuid()
    }

    /// The device's pool's UUID.
    #[allow(dead_code)]
    pub fn pool_uuid(&self) -> PoolUuid {
        self.bda.pool_uuid()
    }

    /// Last time metadata was written to this device.
    #[allow(dead_code)]
    pub fn last_update_time(&self) -> Option<&DateTime<Utc>> {
        self.bda.last_update_time()
    }

    /// Find some sector ranges that could be allocated. If more
    /// sectors are needed than our capacity, return partial results.
    /// If all sectors are desired, use available() method to get all.
    pub fn request_space(&mut self, size: Sectors) -> (Sectors, Vec<(Sectors, Sectors)>) {
        self.used.request(size)
    }

    // ALL SIZE METHODS

    /// The size of the device as recorded in the metadata.
    #[allow(dead_code)]
    pub fn recorded_size(&self) -> Sectors {
        self.bda.dev_size()
    }

    /// The actual size of the device now.
    pub fn current_capacity(&self) -> Sectors {
        self.used.capacity()
    }

    /// The number of Sectors on this device used by Stratis for metadata
    pub fn metadata_size(&self) -> Sectors {
        self.bda.size()
    }

    /// The number of Sectors on this device not allocated for any purpose.
    /// self.current_capacity() - self.metadata_size() >= self.available()
    pub fn available(&self) -> Sectors {
        self.used.available()
    }

    /// The maximum size of variable length metadata that can be accommodated.
    /// self.max_metadata_size() < self.metadata_size()
    pub fn max_metadata_size(&self) -> Sectors {
        self.bda.max_data_size()
    }
}

impl HasUuid for StratBlockDev {
    fn uuid(&self) -> DevUuid {
        self.bda.dev_uuid()
    }
}

impl BlockDev for StratBlockDev {
    fn devnode(&self) -> PathBuf {
        self.devnode.clone()
    }

    fn user_info(&self) -> Option<&str> {
        self.user_info.as_ref().map(|x| &**x)
    }

    fn set_user_info(&mut self, user_info: Option<&str>) -> bool {
        set_blockdev_user_info!(self; user_info)
    }

    fn hardware_info(&self) -> Option<&str> {
        self.hardware_info.as_ref().map(|x| &**x)
    }

    fn initialization_time(&self) -> DateTime<Utc> {
        // This cast will result in an incorrect, negative value starting in
        // the year 292,277,026,596. :-)
        Utc.timestamp(self.bda.initialization_time() as i64, 0)
    }

    fn total_size(&self) -> Sectors {
        let start = self.metadata_size();
        let size = self.current_capacity();
        // Blockdev size is at least MIN_DEV_SIZE, so this can fail only if
        // size of metadata area exceeds 1 GiB. Initial metadata area size
        // is 4 MiB.
        assert!(start <= size);
        size - start
    }

    fn state(&self) -> BlockDevState {
        // TODO: Implement states for blockdevs
        BlockDevState::InUse
    }
}

impl Recordable<BlockDevSave> for StratBlockDev {
    fn record(&self) -> BlockDevSave {
        BlockDevSave {
            devnode: Some(self.devnode.clone()),
            user_info: self.user_info.clone(),
            hardware_info: self.hardware_info.clone(),
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/// Code to handle management of a pool's thinpool device.

use std::process::Command;

use devicemapper;
use devicemapper::{Bytes, DM, DataBlocks, DmError, DmResult, LinearDev, MetaBlocks, Sectors,
                   Segment, ThinDev, ThinDevId, ThinPoolDev, ThinPoolStatus};

use super::super::consts::IEC;
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::types::PoolUuid;

use super::dmdevice::{FlexRole, ThinDevIdPool, ThinPoolRole, format_flex_name,
                      format_thinpool_name};
use super::serde_structs::{Recordable, ThinPoolDevSave};

pub const DATA_BLOCK_SIZE: Sectors = Sectors(2048);
pub const DATA_LOWATER: DataBlocks = DataBlocks(512);
pub const META_LOWATER: MetaBlocks = MetaBlocks(512);

/// A ThinPool struct contains the thinpool itself, but also the spare
/// segments for its metadata device.
#[derive(Debug)]
pub struct ThinPool {
    thin_pool: ThinPoolDev,
    meta_spare: Vec<Segment>,
    id_gen: ThinDevIdPool,
}

impl ThinPool {
    /// Make a new thin pool.
    pub fn new(pool_uuid: PoolUuid,
               dm: &DM,
               data_block_size: Sectors,
               low_water_mark: DataBlocks,
               spare_segments: Vec<Segment>,
               meta_dev: LinearDev,
               data_dev: LinearDev)
               -> EngineResult<ThinPool> {
        let name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        let thinpool_dev = try!(ThinPoolDev::new(&name,
                                                 dm,
                                                 try!(data_dev.size()),
                                                 data_block_size,
                                                 low_water_mark,
                                                 meta_dev,
                                                 data_dev));
        Ok(ThinPool {
               thin_pool: thinpool_dev,
               meta_spare: spare_segments,
               id_gen: ThinDevIdPool::new_from_ids(&[]),
           })
    }

    /// Set up an "existing" thin pool.
    /// A thin pool must store the metadata for its thin devices, regardless of
    /// whether it has an existing device node. An existing thin pool device
    /// is a device where the metadata is already stored on its meta device.
    /// If initial setup fails due to a thin_check failure, attempt to fix
    /// the problem by running thin_repair. If failure recurs, return an
    /// error.
    pub fn setup(pool_uuid: PoolUuid,
                 dm: &DM,
                 data_block_size: Sectors,
                 low_water_mark: DataBlocks,
                 thin_ids: &[ThinDevId],
                 spare_segments: Vec<Segment>,
                 meta_dev: LinearDev,
                 data_dev: LinearDev)
                 -> EngineResult<ThinPool> {
        let name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        let size = try!(data_dev.size());
        match ThinPoolDev::setup(&name,
                                 dm,
                                 size,
                                 data_block_size,
                                 low_water_mark,
                                 meta_dev,
                                 data_dev) {
            Ok(dev) => {
                Ok(ThinPool {
                       thin_pool: dev,
                       meta_spare: spare_segments,
                       id_gen: ThinDevIdPool::new_from_ids(thin_ids),
                   })
            }
            Err(DmError::Dm(devicemapper::ErrorEnum::CheckFailed(meta_dev, data_dev), _)) => {
                let (new_meta_dev, new_spare_segments) =
                    try!(attempt_thin_repair(pool_uuid, dm, meta_dev, spare_segments));
                Ok(ThinPool {
                       thin_pool: try!(ThinPoolDev::setup(&name,
                                                          dm,
                                                          size,
                                                          data_block_size,
                                                          low_water_mark,
                                                          new_meta_dev,
                                                          data_dev)),
                       meta_spare: new_spare_segments,
                       id_gen: ThinDevIdPool::new_from_ids(thin_ids),
                   })
            }
            Err(err) => Err(err.into()),
        }
    }

    /// The status of the thin pool as calculated by DM.
    pub fn thin_pool_status(&self, dm: &DM) -> EngineResult<ThinPoolStatus> {
        Ok(try!(self.thin_pool.status(dm)))
    }

    /// Make a new thin device.
    pub fn make_thin_device(&mut self,
                            dm: &DM,
                            name: &str,
                            size: Option<Sectors>)
                            -> EngineResult<ThinDev> {
        Ok(try!(ThinDev::new(name,
                             dm,
                             &self.thin_pool,
                             try!(self.id_gen.new_id()),
                             size.unwrap_or(Bytes(IEC::Ti).sectors()))))
    }

    /// Setup a previously constructed thin device.
    pub fn setup_thin_device(&self,
                             dm: &DM,
                             name: &str,
                             id: ThinDevId,
                             size: Sectors)
                             -> EngineResult<ThinDev> {
        Ok(try!(ThinDev::setup(name, dm, &self.thin_pool, id, size)))
    }

    /// Tear down the thin pool.
    pub fn teardown(self, dm: &DM) -> DmResult<()> {
        self.thin_pool.teardown(dm)
    }

    /// Get an immutable reference to the sparse segments of the ThinPool.
    pub fn spare_segments(&self) -> &[Segment] {
        &self.meta_spare
    }

    /// The segments belonging to the thin pool meta device.
    pub fn thin_pool_meta_segments(&self) -> &[Segment] {
        self.thin_pool.meta_dev().segments()
    }

    /// The segments belonging to the thin pool data device.
    pub fn thin_pool_data_segments(&self) -> &[Segment] {
        self.thin_pool.data_dev().segments()
    }

    /// Extend the thinpool with new data regions.
    pub fn extend_data(&mut self, dm: &DM, segs: Vec<Segment>) -> EngineResult<()> {
        Ok(try!(self.thin_pool.extend_data(dm, segs)))
    }

    /// The number of physical sectors in use, that is, unavailable for storage
    /// of additional user data, by this pool.
    // This includes all the sectors being held as spares for the meta device,
    // all the sectors allocated to the meta data device, and all the sectors
    // in use on the data device.
    pub fn total_physical_used(&self) -> EngineResult<Sectors> {
        let data_dev_used = match try!(self.thin_pool.status(&try!(DM::new()))) {
            ThinPoolStatus::Good(_, usage) => *usage.used_data * DATA_BLOCK_SIZE,
            _ => {
                let err_msg = "thin pool failed, could not obtain usage";
                return Err(EngineError::Engine(ErrorEnum::Invalid, err_msg.into()));
            }
        };

        let spare_total = self.spare_segments().iter().map(|s| s.length).sum();
        let meta_dev_total = self.thin_pool
            .meta_dev()
            .segments()
            .iter()
            .map(|s| s.length)
            .sum();

        Ok(data_dev_used + spare_total + meta_dev_total)
    }
}

impl Recordable<ThinPoolDevSave> for ThinPool {
    fn record(&self) -> EngineResult<ThinPoolDevSave> {
        Ok(ThinPoolDevSave { data_block_size: self.thin_pool.data_block_size() })
    }
}

/// Attempt a thin repair operation on the meta device.
/// If the operation succeeds, teardown the old meta device,
/// and return the new meta device and the new spare segments.
fn attempt_thin_repair(pool_uuid: PoolUuid,
                       dm: &DM,
                       meta_dev: LinearDev,
                       mut spare_segments: Vec<Segment>)
                       -> EngineResult<(LinearDev, Vec<Segment>)> {
    let mut new_meta_dev = try!(LinearDev::new(&format_flex_name(&pool_uuid,
                                                                 FlexRole::ThinMetaSpare),
                                               dm,
                                               spare_segments.drain(..).collect()));

    if try!(Command::new("thin_repair")
                .arg("-i")
                .arg(&try!(meta_dev.devnode()))
                .arg("-o")
                .arg(&try!(new_meta_dev.devnode()))
                .status())
               .success() == false {
        return Err(EngineError::Engine(ErrorEnum::Error,
                                       "thin_repair failed, pool unusable".into()));
    }

    let name = meta_dev.name().to_owned();
    let new_spare_segments = meta_dev
        .segments()
        .iter()
        .map(|x| {
                 Segment {
                     start: x.start,
                     length: x.length,
                     device: x.device,
                 }
             })
        .collect();
    try!(meta_dev.teardown(dm));
    try!(new_meta_dev.set_name(dm, &name));

    Ok((new_meta_dev, new_spare_segments))
}
<commit_msg>Eliminate any unnecessary comparison with bool in if<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

/// Code to handle management of a pool's thinpool device.

use std::process::Command;

use devicemapper;
use devicemapper::{Bytes, DM, DataBlocks, DmError, DmResult, LinearDev, MetaBlocks, Sectors,
                   Segment, ThinDev, ThinDevId, ThinPoolDev, ThinPoolStatus};

use super::super::consts::IEC;
use super::super::errors::{EngineError, EngineResult, ErrorEnum};
use super::super::types::PoolUuid;

use super::dmdevice::{FlexRole, ThinDevIdPool, ThinPoolRole, format_flex_name,
                      format_thinpool_name};
use super::serde_structs::{Recordable, ThinPoolDevSave};

pub const DATA_BLOCK_SIZE: Sectors = Sectors(2048);
pub const DATA_LOWATER: DataBlocks = DataBlocks(512);
pub const META_LOWATER: MetaBlocks = MetaBlocks(512);

/// A ThinPool struct contains the thinpool itself, but also the spare
/// segments for its metadata device.
#[derive(Debug)]
pub struct ThinPool {
    thin_pool: ThinPoolDev,
    meta_spare: Vec<Segment>,
    id_gen: ThinDevIdPool,
}

impl ThinPool {
    /// Make a new thin pool.
    pub fn new(pool_uuid: PoolUuid,
               dm: &DM,
               data_block_size: Sectors,
               low_water_mark: DataBlocks,
               spare_segments: Vec<Segment>,
               meta_dev: LinearDev,
               data_dev: LinearDev)
               -> EngineResult<ThinPool> {
        let name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        let thinpool_dev = try!(ThinPoolDev::new(&name,
                                                 dm,
                                                 try!(data_dev.size()),
                                                 data_block_size,
                                                 low_water_mark,
                                                 meta_dev,
                                                 data_dev));
        Ok(ThinPool {
               thin_pool: thinpool_dev,
               meta_spare: spare_segments,
               id_gen: ThinDevIdPool::new_from_ids(&[]),
           })
    }

    /// Set up an "existing" thin pool.
    /// A thin pool must store the metadata for its thin devices, regardless of
    /// whether it has an existing device node. An existing thin pool device
    /// is a device where the metadata is already stored on its meta device.
    /// If initial setup fails due to a thin_check failure, attempt to fix
    /// the problem by running thin_repair. If failure recurs, return an
    /// error.
    pub fn setup(pool_uuid: PoolUuid,
                 dm: &DM,
                 data_block_size: Sectors,
                 low_water_mark: DataBlocks,
                 thin_ids: &[ThinDevId],
                 spare_segments: Vec<Segment>,
                 meta_dev: LinearDev,
                 data_dev: LinearDev)
                 -> EngineResult<ThinPool> {
        let name = format_thinpool_name(&pool_uuid, ThinPoolRole::Pool);
        let size = try!(data_dev.size());
        match ThinPoolDev::setup(&name,
                                 dm,
                                 size,
                                 data_block_size,
                                 low_water_mark,
                                 meta_dev,
                                 data_dev) {
            Ok(dev) => {
                Ok(ThinPool {
                       thin_pool: dev,
                       meta_spare: spare_segments,
                       id_gen: ThinDevIdPool::new_from_ids(thin_ids),
                   })
            }
            Err(DmError::Dm(devicemapper::ErrorEnum::CheckFailed(meta_dev, data_dev), _)) => {
                let (new_meta_dev, new_spare_segments) =
                    try!(attempt_thin_repair(pool_uuid, dm, meta_dev, spare_segments));
                Ok(ThinPool {
                       thin_pool: try!(ThinPoolDev::setup(&name,
                                                          dm,
                                                          size,
                                                          data_block_size,
                                                          low_water_mark,
                                                          new_meta_dev,
                                                          data_dev)),
                       meta_spare: new_spare_segments,
                       id_gen: ThinDevIdPool::new_from_ids(thin_ids),
                   })
            }
            Err(err) => Err(err.into()),
        }
    }

    /// The status of the thin pool as calculated by DM.
    pub fn thin_pool_status(&self, dm: &DM) -> EngineResult<ThinPoolStatus> {
        Ok(try!(self.thin_pool.status(dm)))
    }

    /// Make a new thin device.
    pub fn make_thin_device(&mut self,
                            dm: &DM,
                            name: &str,
                            size: Option<Sectors>)
                            -> EngineResult<ThinDev> {
        Ok(try!(ThinDev::new(name,
                             dm,
                             &self.thin_pool,
                             try!(self.id_gen.new_id()),
                             size.unwrap_or(Bytes(IEC::Ti).sectors()))))
    }

    /// Setup a previously constructed thin device.
    pub fn setup_thin_device(&self,
                             dm: &DM,
                             name: &str,
                             id: ThinDevId,
                             size: Sectors)
                             -> EngineResult<ThinDev> {
        Ok(try!(ThinDev::setup(name, dm, &self.thin_pool, id, size)))
    }

    /// Tear down the thin pool.
    pub fn teardown(self, dm: &DM) -> DmResult<()> {
        self.thin_pool.teardown(dm)
    }

    /// Get an immutable reference to the sparse segments of the ThinPool.
    pub fn spare_segments(&self) -> &[Segment] {
        &self.meta_spare
    }

    /// The segments belonging to the thin pool meta device.
    pub fn thin_pool_meta_segments(&self) -> &[Segment] {
        self.thin_pool.meta_dev().segments()
    }

    /// The segments belonging to the thin pool data device.
    pub fn thin_pool_data_segments(&self) -> &[Segment] {
        self.thin_pool.data_dev().segments()
    }

    /// Extend the thinpool with new data regions.
    pub fn extend_data(&mut self, dm: &DM, segs: Vec<Segment>) -> EngineResult<()> {
        Ok(try!(self.thin_pool.extend_data(dm, segs)))
    }

    /// The number of physical sectors in use, that is, unavailable for storage
    /// of additional user data, by this pool.
    // This includes all the sectors being held as spares for the meta device,
    // all the sectors allocated to the meta data device, and all the sectors
    // in use on the data device.
    pub fn total_physical_used(&self) -> EngineResult<Sectors> {
        let data_dev_used = match try!(self.thin_pool.status(&try!(DM::new()))) {
            ThinPoolStatus::Good(_, usage) => *usage.used_data * DATA_BLOCK_SIZE,
            _ => {
                let err_msg = "thin pool failed, could not obtain usage";
                return Err(EngineError::Engine(ErrorEnum::Invalid, err_msg.into()));
            }
        };

        let spare_total = self.spare_segments().iter().map(|s| s.length).sum();
        let meta_dev_total = self.thin_pool
            .meta_dev()
            .segments()
            .iter()
            .map(|s| s.length)
            .sum();

        Ok(data_dev_used + spare_total + meta_dev_total)
    }
}

impl Recordable<ThinPoolDevSave> for ThinPool {
    fn record(&self) -> EngineResult<ThinPoolDevSave> {
        Ok(ThinPoolDevSave { data_block_size: self.thin_pool.data_block_size() })
    }
}

/// Attempt a thin repair operation on the meta device.
/// If the operation succeeds, teardown the old meta device,
/// and return the new meta device and the new spare segments.
fn attempt_thin_repair(pool_uuid: PoolUuid,
                       dm: &DM,
                       meta_dev: LinearDev,
                       mut spare_segments: Vec<Segment>)
                       -> EngineResult<(LinearDev, Vec<Segment>)> {
    let mut new_meta_dev = try!(LinearDev::new(&format_flex_name(&pool_uuid,
                                                                 FlexRole::ThinMetaSpare),
                                               dm,
                                               spare_segments.drain(..).collect()));

    if !try!(Command::new("thin_repair")
                 .arg("-i")
                 .arg(&try!(meta_dev.devnode()))
                 .arg("-o")
                 .arg(&try!(new_meta_dev.devnode()))
                 .status())
                .success() {
        return Err(EngineError::Engine(ErrorEnum::Error,
                                       "thin_repair failed, pool unusable".into()));
    }

    let name = meta_dev.name().to_owned();
    let new_spare_segments = meta_dev
        .segments()
        .iter()
        .map(|x| {
                 Segment {
                     start: x.start,
                     length: x.length,
                     device: x.device,
                 }
             })
        .collect();
    try!(meta_dev.teardown(dm));
    try!(new_meta_dev.set_name(dm, &name));

    Ok((new_meta_dev, new_spare_segments))
}
<|endoftext|>