<commit_before>// Copyright (C) 2020 Julen Ruiz Aizpuru, https://github.com/julen

//! # Plurr
//!
//! A library for handling plurals/genders/conditionals.

use std::collections::HashMap;

mod plurals;
mod utils;

const _PLURAL: &str = "_PLURAL";

#[derive(Debug, PartialEq)]
pub enum PlurrError {
    EmptyPlaceholder,
    EmptyVariants,
    NotZeroOrPositiveValue,
    UnmatchedOpeningBrace,
    UnmatchedClosingBrace,
    UndefinedParameter,
    UndefinedParameterPairs,
}

type PlurrParams = HashMap<String, String>;

#[derive(Debug)]
pub struct Plurr {
    locale: String,
    auto_plurals: bool,
    strict: bool,
    params: PlurrParams,
}

impl Default for Plurr {
    fn default() -> Self {
        Plurr::new()
    }
}

impl Plurr {
    pub fn new() -> Self {
        Plurr {
            locale: "en".to_string(),
            auto_plurals: true,
            strict: true,
            params: PlurrParams::new(),
        }
    }

    /// Sets the locale for Plurr. If this is not called or an incompatible
    /// `locale_code` is provided, it defaults to English.
    pub fn locale(&mut self, locale_code: &str) -> &mut Plurr {
        self.locale = locale_code.to_string();
        self
    }

    /// Toggles the auto-plural behavior.
    /// * With auto-plurals, Plurr will automatically select the plural form for
    /// the current locale.
    /// * Without auto-plurals, you will need to manually provide an `N_PLURAL`
    /// parameter before calling `format()`.
    pub fn auto_plurals(&mut self, auto_plurals: bool) -> &mut Plurr {
        self.auto_plurals = auto_plurals;
        self
    }

    /// Toggles strict mode. In strict mode, errors are not skipped.
    pub fn strict(&mut self, strict: bool) -> &mut Plurr {
        self.strict = strict;
        self
    }

    /// Stores a parameter value. Parameters must be fed before calling
    /// `format()`.
    pub fn param(&mut self, key: &str, value: &str) -> &mut Plurr {
        self.params.insert(key.to_string(), value.to_string());
        self
    }

    /// Formats a Plurr string and returns the evaluated string.
    ///
    /// For the format spec please check out the project
    /// [README](https://github.com/loctools/plurr/blob/master/README.md).
    ///
    /// # Examples
    ///
    /// ```
    /// use plurr::Plurr;
    ///
    /// let mut p = Plurr::new();
    /// let s = "Delete {N_PLURAL:{N} file|{N} files}?";
    ///
    /// assert_eq!(
    ///     p.param("N", "5").format(s),
    ///     Ok("Delete 5 files?".to_string())
    /// );
    /// ```
    pub fn format(&mut self, value: &str) -> Result<String, PlurrError> {
        let mut bracket_count = 0;
        let mut blocks = vec!["".to_string()];

        for chunk in utils::split_string(value, "{", "}") {
            if chunk == "{" {
                bracket_count += 1;
                blocks.push("".to_string());
                continue;
            }

            if chunk == "}" {
                bracket_count -= 1;
                if bracket_count < 0 {
                    return Err(PlurrError::UnmatchedClosingBrace);
                }

                let block = blocks.pop().unwrap();
                let colon_pos_maybe = block.find(':');

                let name = match colon_pos_maybe {
                    Some(colon_pos) => {
                        if self.strict && colon_pos == 0 {
                            return Err(PlurrError::EmptyPlaceholder);
                        }
                        // Multiple choices
                        block[0..colon_pos].to_string()
                    }
                    // Simple placeholder
                    None => block.to_owned(),
                };

                if !self.params.contains_key(&name) {
                    let p_pos = name.find(_PLURAL);
                    if self.auto_plurals
                        && p_pos.is_some()
                        && p_pos.unwrap() == name.len() - _PLURAL.len()
                    {
                        let prefix = name[0..p_pos.unwrap()].to_string();
                        if !self.params.contains_key(&prefix) && self.strict {
                            return Err(PlurrError::UndefinedParameterPairs);
                        }

                        // This is where the actual parameter replacing happens
                        let prefix_value_maybe = self.params.get(&prefix).unwrap();
                        let prefix_value;
                        match prefix_value_maybe.parse::<usize>() {
                            Ok(parsed_value) => prefix_value = parsed_value,
                            Err(_) => {
                                if self.strict {
                                    return Err(PlurrError::NotZeroOrPositiveValue);
                                }
                                prefix_value = 0;
                            }
                        }

                        self.params.insert(
                            name.clone(),
                            plurals::plural_func(&self.locale, prefix_value).to_string(),
                        );
                    } else if self.strict {
                        return Err(PlurrError::UndefinedParameter);
                    }
                }

                let result = match colon_pos_maybe {
                    Some(colon_pos) => {
                        // multiple choices
                        let block_len = block.len();

                        if self.strict && colon_pos == block_len - 1 {
                            return Err(PlurrError::EmptyVariants);
                        }

                        let value = self.params.get(&name).unwrap();
                        let mut choice_idx: usize = value.parse().unwrap_or(0);

                        let content_start = colon_pos + 1;
                        let clean_block = &block[content_start..];

                        let parts: Vec<&str> = clean_block.split('|').collect();
                        if choice_idx >= parts.len() {
                            choice_idx = parts.len() - 1;
                        }
                        parts[choice_idx]
                    }
                    None => self.params.get(&name).unwrap(),
                };

                let index = blocks.len() - 1;
                blocks[index].push_str(result);

                continue;
            }

            let index = blocks.len() - 1;
            blocks[index].push_str(&chunk);
        }

        if bracket_count > 0 {
            return Err(PlurrError::UnmatchedOpeningBrace);
        }

        // Clear params for subsequent calls
        self.params.clear();

        Ok(blocks[0].clone())
    }
}
<commit_msg>Locale: store as an str pointer<commit_after>// Copyright (C) 2020 Julen Ruiz Aizpuru, https://github.com/julen

//! # Plurr
//!
//! A library for handling plurals/genders/conditionals.

use std::collections::HashMap;

mod plurals;
mod utils;

const _PLURAL: &str = "_PLURAL";

#[derive(Debug, PartialEq)]
pub enum PlurrError {
    EmptyPlaceholder,
    EmptyVariants,
    NotZeroOrPositiveValue,
    UnmatchedOpeningBrace,
    UnmatchedClosingBrace,
    UndefinedParameter,
    UndefinedParameterPairs,
}

type PlurrParams = HashMap<String, String>;

#[derive(Debug)]
pub struct Plurr<'a> {
    locale: &'a str,
    auto_plurals: bool,
    strict: bool,
    params: PlurrParams,
}

impl<'a> Default for Plurr<'a> {
    fn default() -> Self {
        Plurr::new()
    }
}

impl<'a> Plurr<'a> {
    pub fn new() -> Self {
        Plurr {
            locale: "en",
            auto_plurals: true,
            strict: true,
            params: PlurrParams::new(),
        }
    }

    /// Sets the locale for Plurr. If this is not called or an incompatible
    /// `locale_code` is provided, it defaults to English.
    pub fn locale(&mut self, locale_code: &'a str) -> &mut Plurr<'a> {
        self.locale = locale_code;
        self
    }

    /// Toggles the auto-plural behavior.
    /// * With auto-plurals, Plurr will automatically select the plural form for
    /// the current locale.
    /// * Without auto-plurals, you will need to manually provide an `N_PLURAL`
    /// parameter before calling `format()`.
    pub fn auto_plurals(&mut self, auto_plurals: bool) -> &mut Plurr<'a> {
        self.auto_plurals = auto_plurals;
        self
    }

    /// Toggles strict mode. In strict mode, errors are not skipped.
    pub fn strict(&mut self, strict: bool) -> &mut Plurr<'a> {
        self.strict = strict;
        self
    }

    /// Stores a parameter value. Parameters must be fed before calling
    /// `format()`.
    pub fn param(&mut self, key: &str, value: &str) -> &mut Plurr<'a> {
        self.params.insert(key.to_string(), value.to_string());
        self
    }

    /// Formats a Plurr string and returns the evaluated string.
    ///
    /// For the format spec please check out the project
    /// [README](https://github.com/loctools/plurr/blob/master/README.md).
    ///
    /// # Examples
    ///
    /// ```
    /// use plurr::Plurr;
    ///
    /// let mut p = Plurr::new();
    /// let s = "Delete {N_PLURAL:{N} file|{N} files}?";
    ///
    /// assert_eq!(
    ///     p.param("N", "5").format(s),
    ///     Ok("Delete 5 files?".to_string())
    /// );
    /// ```
    pub fn format(&mut self, value: &str) -> Result<String, PlurrError> {
        let mut bracket_count = 0;
        let mut blocks = vec!["".to_string()];

        for chunk in utils::split_string(value, "{", "}") {
            if chunk == "{" {
                bracket_count += 1;
                blocks.push("".to_string());
                continue;
            }

            if chunk == "}" {
                bracket_count -= 1;
                if bracket_count < 0 {
                    return Err(PlurrError::UnmatchedClosingBrace);
                }

                let block = blocks.pop().unwrap();
                let colon_pos_maybe = block.find(':');

                let name = match colon_pos_maybe {
                    Some(colon_pos) => {
                        if self.strict && colon_pos == 0 {
                            return Err(PlurrError::EmptyPlaceholder);
                        }
                        // Multiple choices
                        block[0..colon_pos].to_string()
                    }
                    // Simple placeholder
                    None => block.to_owned(),
                };

                if !self.params.contains_key(&name) {
                    let p_pos = name.find(_PLURAL);
                    if self.auto_plurals
                        && p_pos.is_some()
                        && p_pos.unwrap() == name.len() - _PLURAL.len()
                    {
                        let prefix = name[0..p_pos.unwrap()].to_string();
                        if !self.params.contains_key(&prefix) && self.strict {
                            return Err(PlurrError::UndefinedParameterPairs);
                        }

                        // This is where the actual parameter replacing happens
                        let prefix_value_maybe = self.params.get(&prefix).unwrap();
                        let prefix_value;
                        match prefix_value_maybe.parse::<usize>() {
                            Ok(parsed_value) => prefix_value = parsed_value,
                            Err(_) => {
                                if self.strict {
                                    return Err(PlurrError::NotZeroOrPositiveValue);
                                }
                                prefix_value = 0;
                            }
                        }

                        self.params.insert(
                            name.clone(),
                            plurals::plural_func(&self.locale, prefix_value).to_string(),
                        );
                    } else if self.strict {
                        return Err(PlurrError::UndefinedParameter);
                    }
                }

                let result = match colon_pos_maybe {
                    Some(colon_pos) => {
                        // multiple choices
                        let block_len = block.len();

                        if self.strict && colon_pos == block_len - 1 {
                            return Err(PlurrError::EmptyVariants);
                        }

                        let value = self.params.get(&name).unwrap();
                        let mut choice_idx: usize = value.parse().unwrap_or(0);

                        let content_start = colon_pos + 1;
                        let clean_block = &block[content_start..];

                        let parts: Vec<&str> = clean_block.split('|').collect();
                        if choice_idx >= parts.len() {
                            choice_idx = parts.len() - 1;
                        }
                        parts[choice_idx]
                    }
                    None => self.params.get(&name).unwrap(),
                };

                let index = blocks.len() - 1;
                blocks[index].push_str(result);

                continue;
            }

            let index = blocks.len() - 1;
            blocks[index].push_str(&chunk);
        }

        if bracket_count > 0 {
            return Err(PlurrError::UnmatchedOpeningBrace);
        }

        // Clear params for subsequent calls
        self.params.clear();

        Ok(blocks[0].clone())
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge {
    count: usize,
    states: Vec<State<u32>>,
}

impl Merge {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let mut states: Vec<State<u32>> = Vec::with_capacity(count);
        for i in 0..count {
            let collection = Box::new(get_collection(filename, i).unwrap());
            let state = State(collection, None);
            states.push(state);
        }
        Merge {
            count: count,
            states: states,
        }
    }
}

impl Iterator for Merge {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let mut state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let mut min = u32::MAX;
            let mut min_index = usize::MIN;
            for i in 0..count {
                let state = &mut states[i];
                if let Some(val) = state.1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output(filename: &str) -> io::Result<impl Iterator<Item = u32>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = u32>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = u32>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<u32> {
        if let Ok(i) = v.parse::<u32>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<_>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<_>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(
        iter1: &mut impl Iterator<Item = u32>,
        iter2: &mut impl Iterator<Item = u32>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<commit_msg>reduce mut<commit_after>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};

#[macro_use]
extern crate lazy_static;

struct State<T>(Box<dyn Iterator<Item = T>>, Option<T>);
pub struct Merge {
    count: usize,
    states: Vec<State<u32>>,
}

impl Merge {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states: Vec<State<u32>> = (0..count).map(|i| {
            let collection = Box::new(get_collection(filename, i).unwrap());
            State(collection, None)
        }).collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl Iterator for Merge {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        loop {
            for i in 0..count {
                let mut state = &mut states[i];
                if state.1.is_none() {
                    state.1 = state.0.next();
                }
            }
            let not_done = states.iter().any(|s| s.1.is_some());
            if !not_done {
                return None;
            }

            let mut min = u32::MAX;
            let mut min_index = usize::MIN;
            for i in 0..count {
                let state = &mut states[i];
                if let Some(val) = state.1 {
                    if val < min {
                        min = val;
                        min_index = i;
                    }
                }
            }
            states[min_index].1 = None;
            return Some(min);
        }
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output(filename: &str) -> io::Result<impl Iterator<Item = u32>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection(filename: &str, idx: usize) -> io::Result<impl Iterator<Item = u32>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = u32>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<u32> {
        if let Ok(i) = v.parse::<u32>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt").unwrap().collect::<Vec<_>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<_>>(),
            output
        );
    }

    fn merge(filename: &str) -> (impl Iterator<Item = u32>, impl Iterator<Item = u32>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator(
        iter1: &mut impl Iterator<Item = u32>,
        iter2: &mut impl Iterator<Item = u32>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>


<commit_before>//! This crate provides bindings to the official wayland protocol extensions
//! provided in <https://gitlab.freedesktop.org/wayland/wayland-protocols>
//!
//! These bindings are built on top of the crates wayland-client and wayland-server.
//!
//! Each protocol module contains a `client` and a `server` submodules, for each side of the
//! protocol. The creation of these modules (and the dependency on the associated crate) is
//! controlled by the two cargo features `client` and `server`.
//!
//! ## Protocol categories
//!
//! The protocols provided in this crate are grouped in 3 main categories:
//!
//! - The [`wp`] module contains general purpose wayland protocols
//! - The [`xdg`] module contains protocols specifically related to window management
//! - The [`ext`] module contains protocols that do not fit into the two previous categories.
//!
//! ## Staging protocols
//!
//! The cargo feature `staging` enables the generation of the staging protocols.
//!
//! These protocols are ready for wider adoption and clients and compositors are encouraged to
//! implement staging protocol extensions where a protocol's functionality is desired.
//!
//! Although these protocols should be stable, the protocols may still be completely replaced in a new
//! major version or with a completely different protocol.
//!
//! ## Unstable protocols
//!
//! The `wayland-protocols` project previously had a notion of "unstable protocols" representing protocols
//! that are still being worked on and evolving. These protocols are recognized by the use of the prefix `z`
//! in their interface names.
//!
//! This category has now been deprecated and is no longer supposed to be used, however several protocols
//! are still under that umbrella. We can expect them to be replaced by staging and stable protocols in the
//! long term, but in the meantime you can enable them with the `unstable` cargo feature.

#![warn(missing_docs)]
#![forbid(improper_ctypes, unsafe_op_in_unsafe_fn)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]

#[macro_use]
mod protocol_macro;

pub mod ext;
pub mod wp;
pub mod xdg;
<commit_msg>Link to wlr, plasma and misc protocols in the wayland_protocol docs (#501)<commit_after>//! This crate provides bindings to the official wayland protocol extensions
//! provided in <https://gitlab.freedesktop.org/wayland/wayland-protocols>
//!
//! These bindings are built on top of the crates wayland-client and wayland-server.
//!
//! Each protocol module contains a `client` and a `server` submodules, for each side of the
//! protocol. The creation of these modules (and the dependency on the associated crate) is
//! controlled by the two cargo features `client` and `server`.
//!
//! ## Protocol categories
//!
//! The protocols provided in this crate are grouped in 3 main categories:
//!
//! - The [`wp`] module contains general purpose wayland protocols
//! - The [`xdg`] module contains protocols specifically related to window management
//! - The [`ext`] module contains protocols that do not fit into the two previous categories.
//!
//! ## Staging protocols
//!
//! The cargo feature `staging` enables the generation of the staging protocols.
//!
//! These protocols are ready for wider adoption and clients and compositors are encouraged to
//! implement staging protocol extensions where a protocol's functionality is desired.
//!
//! Although these protocols should be stable, the protocols may still be completely replaced in a new
//! major version or with a completely different protocol.
//!
//! ## Unstable protocols
//!
//! The `wayland-protocols` project previously had a notion of "unstable protocols" representing protocols
//! that are still being worked on and evolving. These protocols are recognized by the use of the prefix `z`
//! in their interface names.
//!
//! This category has now been deprecated and is no longer supposed to be used, however several protocols
//! are still under that umbrella. We can expect them to be replaced by staging and stable protocols in the
//! long term, but in the meantime you can enable them with the `unstable` cargo feature.
//!
//! ## Other protocols
//!
//! Additionally, more protocol extensions are provided here:
//! - [wayland-protocols-wlr](https://docs.rs/wayland-protocols-wlr)
//! - [wayland-protocols-plasma](https://docs.rs/wayland-protocols-plasma)
//! - [wayland-protocols-misc](https://docs.rs/wayland-protocols-misc)

#![warn(missing_docs)]
#![forbid(improper_ctypes, unsafe_op_in_unsafe_fn)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]

#[macro_use]
mod protocol_macro;

pub mod ext;
pub mod wp;
pub mod xdg;
<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

//! Contains all the structures of the request and response
//! from the agent.

/// Body of `info` response.
pub mod info;

/// Body of `probe` request and response.
pub mod probe {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub custom_server: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "snake_case")]
    pub enum Response {
        Updating,
        NoUpdate,
        TryAgain(i64),
    }
}

/// Body of `local_install` request.
pub mod local_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub file: std::path::PathBuf,
    }
}

/// Body of `remote_install` request.
pub mod remote_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub url: String,
    }
}

/// Body of `state` response.
pub mod state {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Response {
        Park,
        EntryPoint,
        Poll,
        Probe,
        Validation,
        Download,
        Install,
        Reboot,
        DirectDownload,
        PrepareLocalInstall,
        Error,
    }
}

/// Body of `abort_download` response.
///
/// # Successful case
///
/// On a successful request, the body of response is a struct
/// called `Response` with a successful message.
///
/// # Failed case
///
/// On a failed request, the body of response is a struct
/// called `Refused` with a error message.
pub mod abort_download {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Response {
        pub message: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Refused {
        pub error: String,
    }
}

/// Body of `log` response.
pub mod log {
    use serde::{Deserialize, Serialize};
    use std::collections::HashMap;

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Level {
        Critical,
        Error,
        Warning,
        Info,
        Debug,
        Trace,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Log {
        entries: Vec<Entry>,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Entry {
        level: Level,
        message: String,
        time: String,
        data: HashMap<String, String>,
    }

    impl core::fmt::Display for Log {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
            for entry in &self.entries {
                let level = match entry.level {
                    Level::Critical => "CRIT",
                    Level::Error => "ERRO",
                    Level::Warning => "WARN",
                    Level::Info => "INFO",
                    Level::Debug => "DEBG",
                    Level::Trace => "TRCE",
                };

                writeln!(
                    f,
                    "{timestamp} {level} {msg}",
                    timestamp = entry.time,
                    level = level,
                    msg = entry.message
                )?;
            }
            Ok(())
        }
    }
}
<commit_msg>sdk: Accept short variants on api::log::Level<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

//! Contains all the structures of the request and response
//! from the agent.

/// Body of `info` response.
pub mod info;

/// Body of `probe` request and response.
pub mod probe {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub custom_server: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "snake_case")]
    pub enum Response {
        Updating,
        NoUpdate,
        TryAgain(i64),
    }
}

/// Body of `local_install` request.
pub mod local_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub file: std::path::PathBuf,
    }
}

/// Body of `remote_install` request.
pub mod remote_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub url: String,
    }
}

/// Body of `state` response.
pub mod state {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Response {
        Park,
        EntryPoint,
        Poll,
        Probe,
        Validation,
        Download,
        Install,
        Reboot,
        DirectDownload,
        PrepareLocalInstall,
        Error,
    }
}

/// Body of `abort_download` response.
///
/// # Successful case
///
/// On a successful request, the body of response is a struct
/// called `Response` with a successful message.
///
/// # Failed case
///
/// On a failed request, the body of response is a struct
/// called `Refused` with a error message.
pub mod abort_download {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Response {
        pub message: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Refused {
        pub error: String,
    }
}

/// Body of `log` response.
pub mod log {
    use serde::{Deserialize, Serialize};
    use std::collections::HashMap;

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Level {
        // We use alias here since some string conversions of slog::Level use
        // short names even when requesting the full name:
        // https://github.com/slog-rs/slog/issues/282
        #[serde(alias = "crit")]
        Critical,
        #[serde(alias = "erro")]
        Error,
        #[serde(alias = "warn")]
        Warning,
        #[serde(alias = "info")]
        Info,
        #[serde(alias = "debg")]
        Debug,
        #[serde(alias = "trce")]
        Trace,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Log {
        entries: Vec<Entry>,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Entry {
        level: Level,
        message: String,
        time: String,
        data: HashMap<String, String>,
    }

    impl core::fmt::Display for Log {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
            for entry in &self.entries {
                let level = match entry.level {
                    Level::Critical => "CRIT",
                    Level::Error => "ERRO",
                    Level::Warning => "WARN",
                    Level::Info => "INFO",
                    Level::Debug => "DEBG",
                    Level::Trace => "TRCE",
                };

                writeln!(
                    f,
                    "{timestamp} {level} {msg}",
                    timestamp = entry.time,
                    level = level,
                    msg = entry.message
                )?;
            }
            Ok(())
        }
    }
}
<|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/. */

use dom::bindings::codegen::BindingDeclarations::HTMLFrameSetElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLFrameSetElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLFrameSetElement {
    pub htmlelement: HTMLElement
}

impl HTMLFrameSetElementDerived for EventTarget {
    fn is_htmlframesetelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLFrameSetElementTypeId))
    }
}

impl HTMLFrameSetElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLFrameSetElement {
        HTMLFrameSetElement {
            htmlelement: HTMLElement::new_inherited(HTMLFrameSetElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLFrameSetElement> {
        let element = HTMLFrameSetElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap)
    }
}

pub trait HTMLFrameSetElementMethods {
    fn Cols(&self) -> DOMString;
    fn SetCols(&mut self, _cols: DOMString) -> ErrorResult;
    fn Rows(&self) -> DOMString;
    fn SetRows(&mut self, _rows: DOMString) -> ErrorResult;
}

impl<'a> HTMLFrameSetElementMethods for JSRef<'a, HTMLFrameSetElement> {
    fn Cols(&self) -> DOMString {
        "".to_owned()
    }

    fn SetCols(&mut self, _cols: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Rows(&self) -> DOMString {
        "".to_owned()
    }

    fn SetRows(&mut self, _rows: DOMString) -> ErrorResult {
        Ok(())
    }
}
<commit_msg>Remove needless '&mut self' from HTMLFrameSetElementMethods.<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/. */

use dom::bindings::codegen::BindingDeclarations::HTMLFrameSetElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLFrameSetElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLFrameSetElement {
    pub htmlelement: HTMLElement
}

impl HTMLFrameSetElementDerived for EventTarget {
    fn is_htmlframesetelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLFrameSetElementTypeId))
    }
}

impl HTMLFrameSetElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLFrameSetElement {
        HTMLFrameSetElement {
            htmlelement: HTMLElement::new_inherited(HTMLFrameSetElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLFrameSetElement> {
        let element = HTMLFrameSetElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap)
    }
}

pub trait HTMLFrameSetElementMethods {
    fn Cols(&self) -> DOMString;
    fn SetCols(&self, _cols: DOMString) -> ErrorResult;
    fn Rows(&self) -> DOMString;
    fn SetRows(&self, _rows: DOMString) -> ErrorResult;
}

impl<'a> HTMLFrameSetElementMethods for JSRef<'a, HTMLFrameSetElement> {
    fn Cols(&self) -> DOMString {
        "".to_owned()
    }

    fn SetCols(&self, _cols: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Rows(&self) -> DOMString {
        "".to_owned()
    }

    fn SetRows(&self, _rows: DOMString) -> ErrorResult {
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "stable_graph")]

extern crate petgraph;
extern crate itertools;
#[macro_use] extern crate defmac;

use petgraph::prelude::*;
use petgraph::stable_graph::node_index as n;
use petgraph::EdgeType;
use petgraph::algo::{kosaraju_scc, tarjan_scc};
use petgraph::visit::{
    NodeIndexable,
    IntoNodeReferences,
    IntoEdgeReferences,
};

use itertools::assert_equal;

#[test]
fn node_indices() {
    let mut g = StableGraph::<_, ()>::new();
    let a = g.add_node(0);
    let b = g.add_node(1);
    let c = g.add_node(2);
    g.remove_node(b);
    let mut iter = g.node_indices();
    assert_eq!(iter.next(), Some(a));
    assert_eq!(iter.next(), Some(c));
    assert_eq!(iter.next(), None);
}

#[test]
fn node_bound() {
    let mut g = StableGraph::<_, ()>::new();
    assert_eq!(g.node_bound(), g.node_count());
    for i in 0..10 {
        g.add_node(i);
        assert_eq!(g.node_bound(), g.node_count());
    }
    let full_count = g.node_count();
    g.remove_node(n(0));
    g.remove_node(n(2));
    assert_eq!(g.node_bound(), full_count);
    g.clear();
    assert_eq!(g.node_bound(), 0);
}

fn assert_sccs_eq(mut res: Vec<Vec<NodeIndex>>, normalized: Vec<Vec<NodeIndex>>) {
    // normalize the result and compare with the answer.
    for scc in &mut res {
        scc.sort();
    }
    // sort by minimum element
    res.sort_by(|v, w| v[0].cmp(&w[0]));
    assert_eq!(res, normalized);
}

fn scc_graph() -> StableGraph<(), ()> {
    let mut gr: StableGraph<(), ()> = StableGraph::from_edges(&[
        (6, 0),
        (0, 3),
        (3, 6),
        (8, 6), (8, 2),
        (2, 5), (5, 8), (7, 5),
        (1, 7),
        (7, 4),
        (4, 1)]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, ());
    gr.add_edge(x, n(1), ());
    gr.remove_node(n(4));
    gr
}

#[test]
fn test_scc() {
    let gr = scc_graph();
    println!("{:?}", gr);

    let x = n(gr.node_bound() - 1);
    assert_sccs_eq(kosaraju_scc(&gr), vec![
        vec![n(0), n(3), n(6)],
        vec![n(1), n(7),   x ],
        vec![n(2), n(5), n(8)],
    ]);
}

#[test]
fn test_tarjan_scc() {
    let mut gr: StableGraph<(), ()> = StableGraph::from_edges(&[
        (6, 0),
        (0, 3),
        (3, 6),
        (8, 6), (8, 2),
        (2, 5), (5, 8), (7, 5),
        (1, 7),
        (7, 4),
        (4, 1)]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, ());
    gr.add_edge(x, n(1), ());
    gr.remove_node(n(4));

    assert_sccs_eq(tarjan_scc(&gr), vec![
        vec![n(0), n(3), n(6)],
        vec![n(1), n(7),   x ],
        vec![n(2), n(5), n(8)],
    ]);
}

fn make_graph<Ty>() -> StableGraph<(), i32, Ty>
    where Ty: EdgeType,
{
    let mut gr = StableGraph::default();
    let mut c = 0..;
    let mut e = || -> i32 { c.next().unwrap() };
    gr.extend_with_edges(&[
        (6, 0, e()),
        (0, 3, e()),
        (3, 6, e()),
        (8, 6, e()),
        (8, 2, e()),
        (2, 5, e()),
        (5, 8, e()),
        (7, 5, e()),
        (1, 7, e()),
        (7, 4, e()),
        (8, 6, e()), // parallel edge
        (4, 1, e())]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, e());
    gr.add_edge(x, n(1), e());
    gr.add_edge(x, x, e()); // make two self loops
    let rm_self_loop = gr.add_edge(x, x, e());
    gr.add_edge(x, x, e());
    gr.remove_node(n(4));
    gr.remove_node(n(6));
    gr.remove_edge(rm_self_loop);
    gr
}

defmac!(edges ref gr, x => gr.edges(x).map(|r| (r.target(), *r.weight())));

#[test]
fn test_edges_directed() {
    let gr = make_graph::<Directed>();
    let x = n(9);
    assert_equal(edges!(gr, x), vec![(x, 16), (x, 14), (n(1), 13)]);
    assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]);
    assert_equal(edges!(gr, n(4)), vec![]);
}

#[test]
fn test_edge_references() {
    let gr = make_graph::<Directed>();
    assert_eq!(gr.edge_count(), gr.edge_references().count());
}

#[test]
fn test_edges_undirected() {
    let gr = make_graph::<Undirected>();
    let x = n(9);
    assert_equal(edges!(gr, x), vec![(x, 16), (x, 14), (n(1), 13), (n(7), 12)]);
    assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]);
    assert_equal(edges!(gr, n(4)), vec![]);
}

#[test]
fn test_edge_iterators_directed() {
    let gr = make_graph::<Directed>();
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Outgoing),
            gr.edges(i));
    }
    let mut incoming = vec![Vec::new(); gr.node_bound()];

    for i in gr.node_indices() {
        for j in gr.neighbors(i) {
            incoming[j.index()].push(i);
        }
    }

    println!("{:#?}", gr);
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Incoming).map(|e| e.source()),
            incoming[i.index()].iter().rev().cloned());
    }
}

#[test]
fn test_edge_iterators_undir() {
    let gr = make_graph::<Undirected>();
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Outgoing),
            gr.edges(i));
    }
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Incoming),
            gr.edges(i));
    }
}

#[test]
fn test_node_references() {
    let gr = scc_graph();

    itertools::assert_equal(
        gr.node_references().map(|(i, _)| i),
        gr.node_indices());
}

#[test]
fn iterators_undir() {
    let mut g = StableUnGraph::<_, _>::default();
    let a = g.add_node(0);
    let b = g.add_node(1);
    let c = g.add_node(2);
    let d = g.add_node(3);
    g.extend_with_edges(&[
        (a, b, 1),
        (a, c, 2),
        (b, c, 3),
        (c, c, 4),
        (a, d, 5),
    ]);
    g.remove_node(b);

    itertools::assert_equal(
        g.neighbors(a),
        vec![d, c],
    );
    itertools::assert_equal(
        g.neighbors(c),
        vec![c, a],
    );
    itertools::assert_equal(
        g.neighbors(d),
        vec![a],
    );

    // the node that was removed
    itertools::assert_equal(
        g.neighbors(b),
        vec![],
    );

    // remove one more
    g.remove_node(c);
    itertools::assert_equal(
        g.neighbors(c),
        vec![],
    );
}
<commit_msg>MAINT: Add test for using Dot with StableGraph<commit_after>#![cfg(feature = "stable_graph")]

extern crate petgraph;
extern crate itertools;
#[macro_use] extern crate defmac;

use petgraph::prelude::*;
use petgraph::stable_graph::node_index as n;
use petgraph::EdgeType;
use petgraph::algo::{kosaraju_scc, tarjan_scc};
use petgraph::visit::{
    NodeIndexable,
    IntoNodeReferences,
    IntoEdgeReferences,
};
use petgraph::dot::Dot;

use itertools::assert_equal;

#[test]
fn node_indices() {
    let mut g = StableGraph::<_, ()>::new();
    let a = g.add_node(0);
    let b = g.add_node(1);
    let c = g.add_node(2);
    g.remove_node(b);
    let mut iter = g.node_indices();
    assert_eq!(iter.next(), Some(a));
    assert_eq!(iter.next(), Some(c));
    assert_eq!(iter.next(), None);
}

#[test]
fn node_bound() {
    let mut g = StableGraph::<_, ()>::new();
    assert_eq!(g.node_bound(), g.node_count());
    for i in 0..10 {
        g.add_node(i);
        assert_eq!(g.node_bound(), g.node_count());
    }
    let full_count = g.node_count();
    g.remove_node(n(0));
    g.remove_node(n(2));
    assert_eq!(g.node_bound(), full_count);
    g.clear();
    assert_eq!(g.node_bound(), 0);
}

fn assert_sccs_eq(mut res: Vec<Vec<NodeIndex>>, normalized: Vec<Vec<NodeIndex>>) {
    // normalize the result and compare with the answer.
    for scc in &mut res {
        scc.sort();
    }
    // sort by minimum element
    res.sort_by(|v, w| v[0].cmp(&w[0]));
    assert_eq!(res, normalized);
}

fn scc_graph() -> StableGraph<(), ()> {
    let mut gr: StableGraph<(), ()> = StableGraph::from_edges(&[
        (6, 0),
        (0, 3),
        (3, 6),
        (8, 6), (8, 2),
        (2, 5), (5, 8), (7, 5),
        (1, 7),
        (7, 4),
        (4, 1)]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, ());
    gr.add_edge(x, n(1), ());
    gr.remove_node(n(4));
    gr
}

#[test]
fn test_scc() {
    let gr = scc_graph();
    println!("{:?}", gr);

    let x = n(gr.node_bound() - 1);
    assert_sccs_eq(kosaraju_scc(&gr), vec![
        vec![n(0), n(3), n(6)],
        vec![n(1), n(7),   x ],
        vec![n(2), n(5), n(8)],
    ]);
}

#[test]
fn test_tarjan_scc() {
    let mut gr: StableGraph<(), ()> = StableGraph::from_edges(&[
        (6, 0),
        (0, 3),
        (3, 6),
        (8, 6), (8, 2),
        (2, 5), (5, 8), (7, 5),
        (1, 7),
        (7, 4),
        (4, 1)]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, ());
    gr.add_edge(x, n(1), ());
    gr.remove_node(n(4));

    assert_sccs_eq(tarjan_scc(&gr), vec![
        vec![n(0), n(3), n(6)],
        vec![n(1), n(7),   x ],
        vec![n(2), n(5), n(8)],
    ]);
}

fn make_graph<Ty>() -> StableGraph<(), i32, Ty>
    where Ty: EdgeType,
{
    let mut gr = StableGraph::default();
    let mut c = 0..;
    let mut e = || -> i32 { c.next().unwrap() };
    gr.extend_with_edges(&[
        (6, 0, e()),
        (0, 3, e()),
        (3, 6, e()),
        (8, 6, e()),
        (8, 2, e()),
        (2, 5, e()),
        (5, 8, e()),
        (7, 5, e()),
        (1, 7, e()),
        (7, 4, e()),
        (8, 6, e()), // parallel edge
        (4, 1, e())]);
    // make an identical replacement of n(4) and leave a hole
    let x = gr.add_node(());
    gr.add_edge(n(7), x, e());
    gr.add_edge(x, n(1), e());
    gr.add_edge(x, x, e()); // make two self loops
    let rm_self_loop = gr.add_edge(x, x, e());
    gr.add_edge(x, x, e());
    gr.remove_node(n(4));
    gr.remove_node(n(6));
    gr.remove_edge(rm_self_loop);
    gr
}

defmac!(edges ref gr, x => gr.edges(x).map(|r| (r.target(), *r.weight())));

#[test]
fn test_edges_directed() {
    let gr = make_graph::<Directed>();
    let x = n(9);
    assert_equal(edges!(gr, x), vec![(x, 16), (x, 14), (n(1), 13)]);
    assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]);
    assert_equal(edges!(gr, n(4)), vec![]);
}

#[test]
fn test_edge_references() {
    let gr = make_graph::<Directed>();
    assert_eq!(gr.edge_count(), gr.edge_references().count());
}

#[test]
fn test_edges_undirected() {
    let gr = make_graph::<Undirected>();
    let x = n(9);
    assert_equal(edges!(gr, x), vec![(x, 16), (x, 14), (n(1), 13), (n(7), 12)]);
    assert_equal(edges!(gr, n(0)), vec![(n(3), 1)]);
    assert_equal(edges!(gr, n(4)), vec![]);
}

#[test]
fn test_edge_iterators_directed() {
    let gr = make_graph::<Directed>();
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Outgoing),
            gr.edges(i));
    }
    let mut incoming = vec![Vec::new(); gr.node_bound()];

    for i in gr.node_indices() {
        for j in gr.neighbors(i) {
            incoming[j.index()].push(i);
        }
    }

    println!("{:#?}", gr);
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Incoming).map(|e| e.source()),
            incoming[i.index()].iter().rev().cloned());
    }
}

#[test]
fn test_edge_iterators_undir() {
    let gr = make_graph::<Undirected>();
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Outgoing),
            gr.edges(i));
    }
    for i in gr.node_indices() {
        itertools::assert_equal(
            gr.edges_directed(i, Incoming),
            gr.edges(i));
    }
}

#[test]
fn test_node_references() {
    let gr = scc_graph();

    itertools::assert_equal(
        gr.node_references().map(|(i, _)| i),
        gr.node_indices());
}

#[test]
fn iterators_undir() {
    let mut g = StableUnGraph::<_, _>::default();
    let a = g.add_node(0);
    let b = g.add_node(1);
    let c = g.add_node(2);
    let d = g.add_node(3);
    g.extend_with_edges(&[
        (a, b, 1),
        (a, c, 2),
        (b, c, 3),
        (c, c, 4),
        (a, d, 5),
    ]);
    g.remove_node(b);

    itertools::assert_equal(
        g.neighbors(a),
        vec![d, c],
    );
    itertools::assert_equal(
        g.neighbors(c),
        vec![c, a],
    );
    itertools::assert_equal(
        g.neighbors(d),
        vec![a],
    );

    // the node that was removed
    itertools::assert_equal(
        g.neighbors(b),
        vec![],
    );

    // remove one more
    g.remove_node(c);
    itertools::assert_equal(
        g.neighbors(c),
        vec![],
    );
}

#[test]
fn dot() {
    let mut gr = StableGraph::new();
    let a = gr.add_node("x");
    let b = gr.add_node("y");
    gr.add_edge(a, a, "10");
    gr.add_edge(a, b, "20");
    let dot_output = format!("{}", Dot::new(&gr));
    assert_eq!(dot_output,
r#"digraph {
    0 [label="x"]
    1 [label="y"]
    0 -> 0 [label="10"]
    0 -> 1 [label="20"]
}
"#);
}
<|endoftext|>


<commit_before>use crate::ty::context::TyCtxt;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_query_system::query::QueryCache;
use rustc_query_system::query::QueryState;
use std::fmt::Debug;
use std::io::Write;

pub struct QueryKeyStringCache {
    def_id_cache: FxHashMap<DefId, StringId>,
}

impl QueryKeyStringCache {
    pub fn new() -> QueryKeyStringCache {
        QueryKeyStringCache { def_id_cache: Default::default() }
    }
}

pub struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
    profiler: &'p SelfProfiler,
    tcx: TyCtxt<'tcx>,
    string_cache: &'c mut QueryKeyStringCache,
}

impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
    pub fn new(
        profiler: &'p SelfProfiler,
        tcx: TyCtxt<'tcx>,
        string_cache: &'c mut QueryKeyStringCache,
    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
        QueryKeyStringBuilder { profiler, tcx, string_cache }
    }

    // The current implementation is rather crude. In the future it might be a
    // good idea to base this on `ty::print` in order to get nicer and more
    // efficient query keys.
    fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
        if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
            return string_id;
        }

        let def_key = self.tcx.def_key(def_id);

        let (parent_string_id, start_index) = match def_key.parent {
            Some(parent_index) => {
                let parent_def_id = DefId { index: parent_index, krate: def_id.krate };

                (self.def_id_to_string_id(parent_def_id), 0)
            }
            None => (StringId::INVALID, 2),
        };

        let dis_buffer = &mut [0u8; 16];
        let name;
        let dis;
        let end_index;

        match def_key.disambiguated_data.data {
            DefPathData::CrateRoot => {
                name = self.tcx.original_crate_name(def_id.krate);
                dis = "";
                end_index = 3;
            }
            other => {
                name = other.as_symbol();
                if def_key.disambiguated_data.disambiguator == 0 {
                    dis = "";
                    end_index = 3;
                } else {
                    write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
                        .unwrap();
                    let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
                    dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
                    end_index = 4;
                }
            }
        }

        let name = &*name.as_str();
        let components = [
            StringComponent::Ref(parent_string_id),
            StringComponent::Value("::"),
            StringComponent::Value(name),
            StringComponent::Value(dis),
        ];

        let string_id = self.profiler.alloc_string(&components[start_index..end_index]);

        self.string_cache.def_id_cache.insert(def_id, string_id);

        string_id
    }
}

pub trait IntoSelfProfilingString {
    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
}

// The default implementation of `IntoSelfProfilingString` just uses `Debug`
// which is slow and causes lots of duplication of string data.
// The specialized impls below take care of making the `DefId` case more
// efficient.
impl<T: Debug> IntoSelfProfilingString for T {
    default fn to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        let s = format!("{:?}", self);
        builder.profiler.alloc_string(&s[..])
    }
}

impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
        self.spec_to_self_profile_string(builder)
    }
}

#[rustc_specialization_trait]
pub trait SpecIntoSelfProfilingString: Debug {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId;
}

impl SpecIntoSelfProfilingString for DefId {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(*self)
    }
}

impl SpecIntoSelfProfilingString for CrateNum {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
    }
}

impl SpecIntoSelfProfilingString for DefIndex {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
    }
}

impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
    T0: SpecIntoSelfProfilingString,
    T1: SpecIntoSelfProfilingString,
{
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        let val0 = self.0.to_self_profile_string(builder);
        let val1 = self.1.to_self_profile_string(builder);

        let components = &[
            StringComponent::Value("("),
            StringComponent::Ref(val0),
            StringComponent::Value(","),
            StringComponent::Ref(val1),
            StringComponent::Value(")"),
        ];

        builder.profiler.alloc_string(components)
    }
}

/// Allocate the self-profiling query strings for a single query cache. This
/// method is called from `alloc_self_profile_query_strings` which knows all
/// the queries via macro magic.
pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
    tcx: TyCtxt<'tcx>,
    query_name: &'static str,
    query_state: &QueryState<TyCtxt<'tcx>, C>,
    string_cache: &mut QueryKeyStringCache,
) where
    C: QueryCache,
    C::Key: Debug + Clone,
{
    tcx.prof.with_profiler(|profiler| {
        let event_id_builder = profiler.event_id_builder();

        // Walk the entire query cache and allocate the appropriate
        // string representations. Each cache entry is uniquely
        // identified by its dep_node_index.
        if profiler.query_key_recording_enabled() {
            let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);

            let query_name = profiler.get_or_alloc_cached_string(query_name);

            // Since building the string representation of query keys might
            // need to invoke queries itself, we cannot keep the query caches
            // locked while doing so. Instead we copy out the
            // `(query_key, dep_node_index)` pairs and release the lock again.
            let query_keys_and_indices: Vec<_> = query_state
                .iter_results(|results| results.map(|(k, _, i)| (k.clone(), i)).collect());

            // Now actually allocate the strings. If allocating the strings
            // generates new entries in the query cache, we'll miss them but
            // we don't actually care.
            for (query_key, dep_node_index) in query_keys_and_indices {
                // Translate the DepNodeIndex into a QueryInvocationId
                let query_invocation_id = dep_node_index.into();

                // Create the string version of the query-key
                let query_key = query_key.to_self_profile_string(&mut query_string_builder);
                let event_id = event_id_builder.from_label_and_arg(query_name, query_key);

                // Doing this in bulk might be a good idea:
                profiler.map_query_invocation_id_to_string(
                    query_invocation_id,
                    event_id.to_string_id(),
                );
            }
        } else {
            // In this branch we don't allocate query keys
            let query_name = profiler.get_or_alloc_cached_string(query_name);
            let event_id = event_id_builder.from_label(query_name).to_string_id();

            query_state.iter_results(|results| {
                let query_invocation_ids: Vec<_> = results.map(|v| v.2.into()).collect();

                profiler.bulk_map_query_invocation_id_to_single_string(
                    query_invocation_ids.into_iter(),
                    event_id,
                );
            });
        }
    });
}
<commit_msg>Rollup merge of #75452 - michaelwoerister:sp-cache-more-query-keys, r=lcnr<commit_after>use crate::ty::context::TyCtxt;
use crate::ty::WithOptConstParam;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_query_system::query::QueryCache;
use rustc_query_system::query::QueryState;
use std::fmt::Debug;
use std::io::Write;

pub struct QueryKeyStringCache {
    def_id_cache: FxHashMap<DefId, StringId>,
}

impl QueryKeyStringCache {
    pub fn new() -> QueryKeyStringCache {
        QueryKeyStringCache { def_id_cache: Default::default() }
    }
}

pub struct QueryKeyStringBuilder<'p, 'c, 'tcx> {
    profiler: &'p SelfProfiler,
    tcx: TyCtxt<'tcx>,
    string_cache: &'c mut QueryKeyStringCache,
}

impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
    pub fn new(
        profiler: &'p SelfProfiler,
        tcx: TyCtxt<'tcx>,
        string_cache: &'c mut QueryKeyStringCache,
    ) -> QueryKeyStringBuilder<'p, 'c, 'tcx> {
        QueryKeyStringBuilder { profiler, tcx, string_cache }
    }

    // The current implementation is rather crude. In the future it might be a
    // good idea to base this on `ty::print` in order to get nicer and more
    // efficient query keys.
    fn def_id_to_string_id(&mut self, def_id: DefId) -> StringId {
        if let Some(&string_id) = self.string_cache.def_id_cache.get(&def_id) {
            return string_id;
        }

        let def_key = self.tcx.def_key(def_id);

        let (parent_string_id, start_index) = match def_key.parent {
            Some(parent_index) => {
                let parent_def_id = DefId { index: parent_index, krate: def_id.krate };

                (self.def_id_to_string_id(parent_def_id), 0)
            }
            None => (StringId::INVALID, 2),
        };

        let dis_buffer = &mut [0u8; 16];
        let name;
        let dis;
        let end_index;

        match def_key.disambiguated_data.data {
            DefPathData::CrateRoot => {
                name = self.tcx.original_crate_name(def_id.krate);
                dis = "";
                end_index = 3;
            }
            other => {
                name = other.as_symbol();
                if def_key.disambiguated_data.disambiguator == 0 {
                    dis = "";
                    end_index = 3;
                } else {
                    write!(&mut dis_buffer[..], "[{}]", def_key.disambiguated_data.disambiguator)
                        .unwrap();
                    let end_of_dis = dis_buffer.iter().position(|&c| c == b']').unwrap();
                    dis = std::str::from_utf8(&dis_buffer[..end_of_dis + 1]).unwrap();
                    end_index = 4;
                }
            }
        }

        let name = &*name.as_str();
        let components = [
            StringComponent::Ref(parent_string_id),
            StringComponent::Value("::"),
            StringComponent::Value(name),
            StringComponent::Value(dis),
        ];

        let string_id = self.profiler.alloc_string(&components[start_index..end_index]);

        self.string_cache.def_id_cache.insert(def_id, string_id);

        string_id
    }
}

pub trait IntoSelfProfilingString {
    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId;
}

// The default implementation of `IntoSelfProfilingString` just uses `Debug`
// which is slow and causes lots of duplication of string data.
// The specialized impls below take care of making the `DefId` case more
// efficient.
impl<T: Debug> IntoSelfProfilingString for T {
    default fn to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        let s = format!("{:?}", self);
        builder.profiler.alloc_string(&s[..])
    }
}

impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
        self.spec_to_self_profile_string(builder)
    }
}

#[rustc_specialization_trait]
pub trait SpecIntoSelfProfilingString: Debug {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId;
}

impl SpecIntoSelfProfilingString for DefId {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(*self)
    }
}

impl SpecIntoSelfProfilingString for CrateNum {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
    }
}

impl SpecIntoSelfProfilingString for DefIndex {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
    }
}

impl SpecIntoSelfProfilingString for LocalDefId {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
    }
}

impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        // We print `WithOptConstParam` values as tuples to make them shorter
        // and more readable, without losing information:
        //
        // "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
        // becomes "(foo::bar, foo::baz)" and
        // "WithOptConstParam { did: foo::bar, const_param_did: None }"
        // becomes "(foo::bar, _)".

        let did = StringComponent::Ref(self.did.to_self_profile_string(builder));

        let const_param_did = if let Some(const_param_did) = self.const_param_did {
            let const_param_did = builder.def_id_to_string_id(const_param_did);
            StringComponent::Ref(const_param_did)
        } else {
            StringComponent::Value("_")
        };

        let components = [
            StringComponent::Value("("),
            did,
            StringComponent::Value(", "),
            const_param_did,
            StringComponent::Value(")"),
        ];

        builder.profiler.alloc_string(&components[..])
    }
}

impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
    T0: SpecIntoSelfProfilingString,
    T1: SpecIntoSelfProfilingString,
{
    fn spec_to_self_profile_string(
        &self,
        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
    ) -> StringId {
        let val0 = self.0.to_self_profile_string(builder);
        let val1 = self.1.to_self_profile_string(builder);

        let components = &[
            StringComponent::Value("("),
            StringComponent::Ref(val0),
            StringComponent::Value(","),
            StringComponent::Ref(val1),
            StringComponent::Value(")"),
        ];

        builder.profiler.alloc_string(components)
    }
}

/// Allocate the self-profiling query strings for a single query cache. This
/// method is called from `alloc_self_profile_query_strings` which knows all
/// the queries via macro magic.
pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
    tcx: TyCtxt<'tcx>,
    query_name: &'static str,
    query_state: &QueryState<TyCtxt<'tcx>, C>,
    string_cache: &mut QueryKeyStringCache,
) where
    C: QueryCache,
    C::Key: Debug + Clone,
{
    tcx.prof.with_profiler(|profiler| {
        let event_id_builder = profiler.event_id_builder();

        // Walk the entire query cache and allocate the appropriate
        // string representations. Each cache entry is uniquely
        // identified by its dep_node_index.
        if profiler.query_key_recording_enabled() {
            let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache);

            let query_name = profiler.get_or_alloc_cached_string(query_name);

            // Since building the string representation of query keys might
            // need to invoke queries itself, we cannot keep the query caches
            // locked while doing so. Instead we copy out the
            // `(query_key, dep_node_index)` pairs and release the lock again.
            let query_keys_and_indices: Vec<_> = query_state
                .iter_results(|results| results.map(|(k, _, i)| (k.clone(), i)).collect());

            // Now actually allocate the strings. If allocating the strings
            // generates new entries in the query cache, we'll miss them but
            // we don't actually care.
            for (query_key, dep_node_index) in query_keys_and_indices {
                // Translate the DepNodeIndex into a QueryInvocationId
                let query_invocation_id = dep_node_index.into();

                // Create the string version of the query-key
                let query_key = query_key.to_self_profile_string(&mut query_string_builder);
                let event_id = event_id_builder.from_label_and_arg(query_name, query_key);

                // Doing this in bulk might be a good idea:
                profiler.map_query_invocation_id_to_string(
                    query_invocation_id,
                    event_id.to_string_id(),
                );
            }
        } else {
            // In this branch we don't allocate query keys
            let query_name = profiler.get_or_alloc_cached_string(query_name);
            let event_id = event_id_builder.from_label(query_name).to_string_id();

            query_state.iter_results(|results| {
                let query_invocation_ids: Vec<_> = results.map(|v| v.2.into()).collect();

                profiler.bulk_map_query_invocation_id_to_single_string(
                    query_invocation_ids.into_iter(),
                    event_id,
                );
            });
        }
    });
}
<|endoftext|>


<commit_before>// Copyright 2020 lowRISC contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#![no_std]

mod console_reader;
mod fuse;
mod manticore_support;
mod sfdp;
mod spi_host;
mod spi_host_h1;
mod spi_host_helper;
mod spi_device;
mod spi_processor;

use crate::spi_host_helper::SpiHostHelper;
use crate::spi_processor::SpiProcessor;

use core::fmt::Write;

use libtock::console::Console;
use libtock::result::TockError;
use libtock::result::TockResult;
use libtock::syscalls::raw::yieldk;

use spiutils::driver::AddressConfig;
use spiutils::driver::HandlerMode;
use spiutils::protocol::flash::AddressMode;

//////////////////////////////////////////////////////////////////////////////

fn run_host_helper_demo() -> TockResult<()> {
    let mut console = Console::new();

    // We cannot use the SPI host if passthrough is enabled.
    spi_host_h1::get().set_passthrough(false)?;

    let host_helper = SpiHostHelper {};

    writeln!(console, "Host: Entering 4B mode")?;
    host_helper.enter_4b()?;

    writeln!(console, "Host: Reading data")?;
    host_helper.read_and_print_data(0x0)?;
    host_helper.read_and_print_data(0x1)?;

    if spi_device::get().get_address_mode() == AddressMode::ThreeByte {
        writeln!(console, "Host: Exiting 4B mode")?;
        host_helper.exit_4b()?;
    }

    Ok(())
}

fn run() -> TockResult<()> {
    let mut console = Console::new();

    //////////////////////////////////////////////////////////////////////////////

    run_host_helper_demo()?;

    //////////////////////////////////////////////////////////////////////////////

    let mut identity = manticore_support::Identity {
        version: [0; 32],
        device_id: [0; 64],
    };

    {
        let mut idx : usize = 0;
        for val in "v1.00".as_bytes() {
            if idx > identity.version.len() { break; }
            identity.version[idx] = *val;
            idx = idx + 1;
        }
    }

    {
        let mut idx : usize = 0;
        for val in "1234567890".as_bytes() {
            if idx > identity.device_id.len() { break; }
            identity.device_id[idx] = *val;
            idx = idx + 1;
        }
    }

    let mut spi_processor = SpiProcessor {
        server: manticore_support::get_pa_rot(&identity),
        print_flash_headers: false,  // Enable to print incoming SPI flash headers
    };

    //////////////////////////////////////////////////////////////////////////////

    writeln!(console, "Device: Configuring address_mode handling to KernelSpace")?;
    spi_device::get().set_address_mode_handling(HandlerMode::KernelSpace)?;
    spi_device::get().configure_addresses(AddressConfig {
        flash_virtual_base: 0x0,
        flash_physical_base: 0x0,
        flash_physical_size: spi_processor::SPI_FLASH_SIZE,
        ram_virtual_base: spi_processor::SPI_MAILBOX_ADDRESS,
        virtual_size: spi_processor::SPI_FLASH_SIZE,
    })?;

    //////////////////////////////////////////////////////////////////////////////

    // OpenTitan JEDEC ID
    /*
    spi_device::get().set_jedec_id(&mut [
        0x26, // Manufacturer (Visic, should actually be
              // 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x26)
        0x31, // Device (OpenTitan)
        0x19, // Size (2^25 = 256 Mb)
        ])?;
    */

    // Legacy JEDEC ID
    spi_device::get().set_jedec_id(&mut [
        0x26, // Manufacturer
        0x02, // Device
        0x17, // Size
        ])?;

    //////////////////////////////////////////////////////////////////////////////

    {
        let mut sfdp = [0xff; 128];
        sfdp::get_table(
            &mut sfdp,
            spi_processor::SPI_FLASH_SIZE * 8, // image_size_bits
            spi_device::get().get_address_mode(), // startup_address_mode
            spi_device::get().get_address_mode() == AddressMode::ThreeByte, // support_address_mode_switch
            spi_processor::SPI_MAILBOX_ADDRESS, // mailbox_offset
            spi_device::MAX_READ_BUFFER_SIZE as u32, // mailbox_size
            0 // google_capabilities
            ).map_err(|_| TockError::Format)?;
        spi_device::get().set_sfdp(&mut sfdp)?;
    }

    //////////////////////////////////////////////////////////////////////////////

    // We need SPI passthrough to be fully operational.
    spi_host_h1::get().set_passthrough(true)?;

    //////////////////////////////////////////////////////////////////////////////

    loop {
        while !spi_device::get().have_transaction()
            && !console_reader::get().have_data() {

            // Note: Do NOT use the console here, as that results in a "hidden"
            // yieldk() which causes us to lose track of the conditions above.
            unsafe { yieldk(); }
        }

        if spi_device::get().have_transaction() {
            let rx_buf = spi_device::get().get_read_buffer();
            match spi_processor.process_spi_packet(rx_buf) {
                Ok(()) => {}
                Err(why) => {
                    // Ignore error from writeln. There's nothing we can do here anyway.
                    let _ = writeln!(console, "Device: Error processing SPI packet: {:?}", why);
                    if spi_device::get().is_busy_set() {
                        if let Err(_) = spi_device::get().end_transaction_with_status(true, false) {
                            // Ignore error from writeln. There's nothing we can do here anyway.
                            let _ = writeln!(console, "Device: Error ending transaction.");
                        }
                    } else {
                        spi_device::get().end_transaction();
                    }
                }
            }
        }

        if console_reader::get().have_data() {
            let data = console_reader::get().get_data();
            writeln!(console, "Have data (len={}): 0x{:x}", data.len(), data[0])?;
            console_reader::get().allow_read(1)?;
        }
    }
}

const BANNER: &'static str = concat!(
    env!("CARGO_PKG_NAME"), ' ',
    env!("CARGO_PKG_VERSION"), ' ',
    include_str!("../../../build/gitlongtag")
);

#[libtock::main]
async fn main() -> TockResult<()> {
    let mut console = Console::new();
    writeln!(console, "Starting {}", BANNER)?;
    writeln!(console, "DEV ID: 0x{:x}", fuse::get().get_dev_id()?)?;
    let result = run();
    if result.is_ok() {
        writeln!(console, "Returned OK.")?;
    } else {
        writeln!(console, "Returned error.")?;
    }
    result
}
<commit_msg>otpilot: Change JEDEC ID to OpenTitan.<commit_after>// Copyright 2020 lowRISC contributors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#![no_std]

mod console_reader;
mod fuse;
mod manticore_support;
mod sfdp;
mod spi_host;
mod spi_host_h1;
mod spi_host_helper;
mod spi_device;
mod spi_processor;

use crate::spi_host_helper::SpiHostHelper;
use crate::spi_processor::SpiProcessor;

use core::fmt::Write;

use libtock::console::Console;
use libtock::result::TockError;
use libtock::result::TockResult;
use libtock::syscalls::raw::yieldk;

use spiutils::driver::AddressConfig;
use spiutils::driver::HandlerMode;
use spiutils::protocol::flash::AddressMode;

//////////////////////////////////////////////////////////////////////////////

fn run_host_helper_demo() -> TockResult<()> {
    let mut console = Console::new();

    // We cannot use the SPI host if passthrough is enabled.
    spi_host_h1::get().set_passthrough(false)?;

    let host_helper = SpiHostHelper {};

    writeln!(console, "Host: Entering 4B mode")?;
    host_helper.enter_4b()?;

    writeln!(console, "Host: Reading data")?;
    host_helper.read_and_print_data(0x0)?;
    host_helper.read_and_print_data(0x1)?;

    if spi_device::get().get_address_mode() == AddressMode::ThreeByte {
        writeln!(console, "Host: Exiting 4B mode")?;
        host_helper.exit_4b()?;
    }

    Ok(())
}

fn run() -> TockResult<()> {
    let mut console = Console::new();

    //////////////////////////////////////////////////////////////////////////////

    run_host_helper_demo()?;

    //////////////////////////////////////////////////////////////////////////////

    let mut identity = manticore_support::Identity {
        version: [0; 32],
        device_id: [0; 64],
    };

    {
        let mut idx : usize = 0;
        for val in "v1.00".as_bytes() {
            if idx > identity.version.len() { break; }
            identity.version[idx] = *val;
            idx = idx + 1;
        }
    }

    {
        let mut idx : usize = 0;
        for val in "1234567890".as_bytes() {
            if idx > identity.device_id.len() { break; }
            identity.device_id[idx] = *val;
            idx = idx + 1;
        }
    }

    let mut spi_processor = SpiProcessor {
        server: manticore_support::get_pa_rot(&identity),
        print_flash_headers: false,  // Enable to print incoming SPI flash headers
    };

    //////////////////////////////////////////////////////////////////////////////

    writeln!(console, "Device: Configuring address_mode handling to KernelSpace")?;
    spi_device::get().set_address_mode_handling(HandlerMode::KernelSpace)?;
    spi_device::get().configure_addresses(AddressConfig {
        flash_virtual_base: 0x0,
        flash_physical_base: 0x0,
        flash_physical_size: spi_processor::SPI_FLASH_SIZE,
        ram_virtual_base: spi_processor::SPI_MAILBOX_ADDRESS,
        virtual_size: spi_processor::SPI_FLASH_SIZE,
    })?;

    //////////////////////////////////////////////////////////////////////////////

    // OpenTitan JEDEC ID
    spi_device::get().set_jedec_id(&mut [
        0x26, // Manufacturer (Visic, should actually be
              // 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x26)
        0x31, // Device (OpenTitan)
        0x19, // Size (2^25 = 256 Mb)
        ])?;

    //////////////////////////////////////////////////////////////////////////////

    {
        let mut sfdp = [0xff; 128];
        sfdp::get_table(
            &mut sfdp,
            spi_processor::SPI_FLASH_SIZE * 8, // image_size_bits
            spi_device::get().get_address_mode(), // startup_address_mode
            spi_device::get().get_address_mode() == AddressMode::ThreeByte, // support_address_mode_switch
            spi_processor::SPI_MAILBOX_ADDRESS, // mailbox_offset
            spi_device::MAX_READ_BUFFER_SIZE as u32, // mailbox_size
            0 // google_capabilities
            ).map_err(|_| TockError::Format)?;
        spi_device::get().set_sfdp(&mut sfdp)?;
    }

    //////////////////////////////////////////////////////////////////////////////

    // We need SPI passthrough to be fully operational.
    spi_host_h1::get().set_passthrough(true)?;

    //////////////////////////////////////////////////////////////////////////////

    loop {
        while !spi_device::get().have_transaction()
            && !console_reader::get().have_data() {

            // Note: Do NOT use the console here, as that results in a "hidden"
            // yieldk() which causes us to lose track of the conditions above.
            unsafe { yieldk(); }
        }

        if spi_device::get().have_transaction() {
            let rx_buf = spi_device::get().get_read_buffer();
            match spi_processor.process_spi_packet(rx_buf) {
                Ok(()) => {}
                Err(why) => {
                    // Ignore error from writeln. There's nothing we can do here anyway.
                    let _ = writeln!(console, "Device: Error processing SPI packet: {:?}", why);
                    if spi_device::get().is_busy_set() {
                        if let Err(_) = spi_device::get().end_transaction_with_status(true, false) {
                            // Ignore error from writeln. There's nothing we can do here anyway.
                            let _ = writeln!(console, "Device: Error ending transaction.");
                        }
                    } else {
                        spi_device::get().end_transaction();
                    }
                }
            }
        }

        if console_reader::get().have_data() {
            let data = console_reader::get().get_data();
            writeln!(console, "Have data (len={}): 0x{:x}", data.len(), data[0])?;
            console_reader::get().allow_read(1)?;
        }
    }
}

const BANNER: &'static str = concat!(
    env!("CARGO_PKG_NAME"), ' ',
    env!("CARGO_PKG_VERSION"), ' ',
    include_str!("../../../build/gitlongtag")
);

#[libtock::main]
async fn main() -> TockResult<()> {
    let mut console = Console::new();
    writeln!(console, "Starting {}", BANNER)?;
    writeln!(console, "DEV ID: 0x{:x}", fuse::get().get_dev_id()?)?;
    let result = run();
    if result.is_ok() {
        writeln!(console, "Returned OK.")?;
    } else {
        writeln!(console, "Returned error.")?;
    }
    result
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::account_address::AccountAddress;
use move_deps::move_cli::base::prove::run_move_prover;
use move_deps::move_prover;
use std::{collections::BTreeMap, path::PathBuf};
use tempfile::tempdir;

pub fn path_in_crate<S>(relative: S) -> PathBuf
where
    S: Into<String>,
{
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push(relative.into());
    path
}

pub fn run_prover_for_pkg(
    path_to_pkg: impl Into<String>,
    named_addr: BTreeMap<String, AccountAddress>,
) {
    let pkg_path = path_in_crate(path_to_pkg);
    let config = move_deps::move_package::BuildConfig {
        additional_named_addresses: named_addr,
        test_mode: true,
        install_dir: Some(tempdir().unwrap().path().to_path_buf()),
        ..Default::default()
    };
    run_move_prover(
        config,
        &pkg_path,
        &None,
        true,
        move_prover::cli::Options::default(),
    )
    .unwrap();
}

#[test]
fn test_hello_prover() {
    let named_address = BTreeMap::new();
    run_prover_for_pkg("hello_prover", named_address);
}
<commit_msg>Ignore the example Prover test (#2494)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::account_address::AccountAddress;
use move_deps::move_cli::base::prove::run_move_prover;
use move_deps::move_prover;
use std::{collections::BTreeMap, path::PathBuf};
use tempfile::tempdir;

pub fn path_in_crate<S>(relative: S) -> PathBuf
where
    S: Into<String>,
{
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push(relative.into());
    path
}

pub fn run_prover_for_pkg(
    path_to_pkg: impl Into<String>,
    named_addr: BTreeMap<String, AccountAddress>,
) {
    let pkg_path = path_in_crate(path_to_pkg);
    let config = move_deps::move_package::BuildConfig {
        additional_named_addresses: named_addr,
        test_mode: true,
        install_dir: Some(tempdir().unwrap().path().to_path_buf()),
        ..Default::default()
    };
    run_move_prover(
        config,
        &pkg_path,
        &None,
        true,
        move_prover::cli::Options::default(),
    )
    .unwrap();
}

#[ignore]
#[test]
fn test_hello_prover() {
    let named_address = BTreeMap::new();
    run_prover_for_pkg("hello_prover", named_address);
}
<|endoftext|>