<commit_before>#![feature(asm)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate blue_pill;

use cortex_m::peripheral::SystClkSource;
use rtfm::{app, Threshold};
use blue_pill::stm32f103xx::Interrupt;

mod font5x7;
mod i2c;
mod ssd1306;

use ssd1306::SSD1306;

const OLED_ADDR: u8 = 0x3c;

pub enum Keys {
    A,
    B,
    AB,
    None,
}

pub struct State {
    pub keys: Keys,
}

app! {
    device: blue_pill::stm32f103xx,

    resources: {
        static TICKS: u32 = 0;
        static KEYS: Keys = Keys::None;
    },

    tasks: {
        SYS_TICK: {
            path: tick,
            resources: [TICKS],
        },
        EXTI0: {
            path: update_ui,
            resources: [I2C1, KEYS],
        },
        EXTI9_5: {
            path: exti9_5,
            resources: [KEYS, GPIOA, EXTI],
        },
    },
}

fn init(p: init::Peripherals, _r: init::Resources) {
    // 48Mhz
    p.FLASH.acr.modify(
        |_, w| w.prftbe().enabled().latency().one(),
    );

    p.RCC.cfgr.modify(|_, w| unsafe { w.bits(0x0068840A) });
    p.RCC.cr.modify(
        |_, w| w.pllon().set_bit().hsion().set_bit(),
    );
    while p.RCC.cr.read().pllrdy().bit_is_clear() {}
    while p.RCC.cr.read().hsirdy().bit_is_clear() {}

    p.RCC.apb2enr.modify(|_, w| {
        w.iopaen().enabled().iopben().enabled().afioen().enabled()
    });

    p.AFIO.mapr.modify(|_, w| unsafe {
        w.swj_cfg().bits(2).i2c1_remap().clear_bit()
    });

    p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled());

    p.I2C1.cr1.write(|w| w.pe().clear_bit());

    p.GPIOA.crl.modify(|_, w| w.mode6().input());
    p.GPIOA.crh.modify(|_, w| {
        w.mode8().output50().cnf8().push().mode9().input()
    });
    p.GPIOA.bsrr.write(|w| {
        w.bs6().set_bit().bs8().set_bit().bs9().set_bit()
    });

    p.GPIOB.crl.modify(|_, w| {
        w.mode5()
            .input()
            .mode6()
            .output50()
            .cnf6()
            .alt_open()
            .mode7()
            .output50()
            .cnf7()
            .alt_open()
    });
    p.GPIOB.bsrr.write(|w| w.bs5().set_bit());

    p.AFIO.exticr2.modify(|_, w| unsafe {
        w.exti5().bits(1).exti6().bits(0)
    });

    p.AFIO.exticr3.modify(|_, w| unsafe { w.exti9().bits(0) });

    p.EXTI.imr.modify(|_, w| {
        w.mr5().set_bit().mr6().set_bit().mr9().set_bit()
    });
    p.EXTI.rtsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });
    p.EXTI.ftsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });

    p.I2C1.cr2.modify(|_, w| unsafe { w.freq().bits(24) });
    p.I2C1.cr1.modify(|_, w| w.pe().clear_bit());
    p.I2C1.trise.modify(
        |_, w| unsafe { w.trise().bits(24 + 1) },
    );
    p.I2C1.ccr.modify(|_, w| unsafe {
        w.f_s().clear_bit().duty().clear_bit().ccr().bits(120)
    });

    p.I2C1.cr1.modify(|_, w| {
        w.nostretch()
            .clear_bit()
            .ack()
            .set_bit()
            .smbus()
            .clear_bit()
    });

    p.I2C1.cr1.write(|w| w.pe().set_bit());
    p.I2C1.oar1.write(|w| unsafe {
        w.addmode()
            .clear_bit()
            .add0()
            .clear_bit()
            .add7()
            .bits(0)
            .add10()
            .bits(0)
    });

    let oled = SSD1306(OLED_ADDR, &p.I2C1);
    oled.init();
    oled.print(0, 0, "   Hello from   ");
    oled.print(0, 1, "      Rust      ");

    p.SYST.set_clock_source(SystClkSource::Core);
    p.SYST.set_reload(48_000_000);
    p.SYST.enable_interrupt();
    p.SYST.enable_counter();
}

fn idle() -> ! {
    rtfm::set_pending(Interrupt::EXTI0);

    loop {
        rtfm::wfi();
    }
}

fn tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
    **r.TICKS += 1;
}

fn update_ui(_t: &mut Threshold, r: EXTI0::Resources) {
    let i2c1 = &**r.I2C1;
    let oled = SSD1306(OLED_ADDR, &i2c1);

    match **r.KEYS {
        Keys::A => {
            oled.print(0, 0, "        A       ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::B => {
            oled.print(0, 0, "        B       ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::AB => {
            oled.print(0, 0, "     A and B    ");
            oled.print(0, 1, "     pressed    ");
        }
        Keys::None => {
            oled.print(0, 0, "   Hello from   ");
            oled.print(0, 1, "      Rust      ");
        }
    }
}

fn exti9_5(_t: &mut Threshold, r: EXTI9_5::Resources) {
    let exti = &**r.EXTI;
    let gpioa = &**r.GPIOA;

    // Button A
    if exti.pr.read().pr6().bit_is_set() {
        **r.KEYS = if gpioa.idr.read().idr6().bit_is_clear() {
            Keys::A
        } else {
            Keys::None
        };
        exti.pr.write(|w| w.pr6().set_bit());
    // Button B
    } else if exti.pr.read().pr9().bit_is_set() {
        **r.KEYS = if gpioa.idr.read().idr9().bit_is_clear() {
            Keys::B
        } else {
            Keys::None
        };
        exti.pr.write(|w| w.pr9().set_bit());
    // Movement
    } else if exti.pr.read().pr5().bit_is_set() {
        exti.pr.write(|w| w.pr5().set_bit());
    }

    rtfm::set_pending(Interrupt::EXTI0);
}
<commit_msg>adds simple state machine<commit_after>#![feature(asm)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate blue_pill;

use cortex_m::peripheral::SystClkSource;
use rtfm::{app, Threshold};
use blue_pill::stm32f103xx::Interrupt;

mod font5x7;
mod i2c;
mod ssd1306;

use ssd1306::SSD1306;

const OLED_ADDR: u8 = 0x3c;

#[derive(Clone, Copy)]
pub enum ConfigPage {
    Save,
}

#[derive(Clone, Copy)]
pub enum State {
    Idle,
    Soldering,
    TemperatureControl,
    Config(ConfigPage),
    Sleep,
    Cooling,
    Thermometer,
}

pub enum Keys {
    A,
    B,
    AB,
    None,
}

pub struct StateMachine {
    keys: Keys,
    state: State,
}

impl StateMachine {
    pub const fn new() -> Self {
        StateMachine {
            keys: Keys::None,
            state: State::Idle,
        }
    }

    pub fn update_keys(&mut self, keys: Keys) {
        self.keys = keys;
    }

    pub fn current_state(&self) -> State {
        self.state
    }

    pub fn update_state(&mut self) {
        use State::*;
        use Keys::*;

        self.state = match (&self.state, &self.keys) {
            (&Idle, &A) => Soldering,
            (&Idle, &B) => Thermometer,
            (&Soldering, &A) | (&Soldering, &B) => TemperatureControl,
            (&Soldering, &AB) => Idle,
            (_, &None) => self.state,
            _ => Idle,
        };

        self.keys = Keys::None;
    }
}

app! {
    device: blue_pill::stm32f103xx,

    resources: {
        static TICKS: u32 = 0;
        static STATE: StateMachine = StateMachine::new();
    },

    tasks: {
        SYS_TICK: {
            path: tick,
            resources: [TICKS],
        },
        EXTI0: {
            path: update_ui,
            resources: [I2C1, STATE],
        },
        EXTI9_5: {
            path: exti9_5,
            resources: [STATE, GPIOA, EXTI],
        },
    },
}

fn init(p: init::Peripherals, _r: init::Resources) {
    // 48Mhz
    p.FLASH.acr.modify(
        |_, w| w.prftbe().enabled().latency().one(),
    );

    p.RCC.cfgr.modify(|_, w| unsafe { w.bits(0x0068840A) });
    p.RCC.cr.modify(
        |_, w| w.pllon().set_bit().hsion().set_bit(),
    );
    while p.RCC.cr.read().pllrdy().bit_is_clear() {}
    while p.RCC.cr.read().hsirdy().bit_is_clear() {}

    p.RCC.apb2enr.modify(|_, w| {
        w.iopaen().enabled().iopben().enabled().afioen().enabled()
    });

    p.AFIO.mapr.modify(|_, w| unsafe {
        w.swj_cfg().bits(2).i2c1_remap().clear_bit()
    });

    p.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled());

    p.I2C1.cr1.write(|w| w.pe().clear_bit());

    p.GPIOA.crl.modify(|_, w| w.mode6().input());
    p.GPIOA.crh.modify(|_, w| {
        w.mode8().output50().cnf8().push().mode9().input()
    });
    p.GPIOA.bsrr.write(|w| {
        w.bs6().set_bit().bs8().set_bit().bs9().set_bit()
    });

    p.GPIOB.crl.modify(|_, w| {
        w.mode5()
            .input()
            .mode6()
            .output50()
            .cnf6()
            .alt_open()
            .mode7()
            .output50()
            .cnf7()
            .alt_open()
    });
    p.GPIOB.bsrr.write(|w| w.bs5().set_bit());

    p.AFIO.exticr2.modify(|_, w| unsafe {
        w.exti5().bits(1).exti6().bits(0)
    });

    p.AFIO.exticr3.modify(|_, w| unsafe { w.exti9().bits(0) });

    p.EXTI.imr.modify(|_, w| {
        w.mr5().set_bit().mr6().set_bit().mr9().set_bit()
    });
    p.EXTI.rtsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });
    p.EXTI.ftsr.modify(|_, w| {
        w.tr5().set_bit().tr6().set_bit().tr9().set_bit()
    });

    p.I2C1.cr2.modify(|_, w| unsafe { w.freq().bits(24) });
    p.I2C1.cr1.modify(|_, w| w.pe().clear_bit());
    p.I2C1.trise.modify(
        |_, w| unsafe { w.trise().bits(24 + 1) },
    );
    p.I2C1.ccr.modify(|_, w| unsafe {
        w.f_s().clear_bit().duty().clear_bit().ccr().bits(120)
    });

    p.I2C1.cr1.modify(|_, w| {
        w.nostretch()
            .clear_bit()
            .ack()
            .set_bit()
            .smbus()
            .clear_bit()
    });

    p.I2C1.cr1.write(|w| w.pe().set_bit());
    p.I2C1.oar1.write(|w| unsafe {
        w.addmode()
            .clear_bit()
            .add0()
            .clear_bit()
            .add7()
            .bits(0)
            .add10()
            .bits(0)
    });

    let oled = SSD1306(OLED_ADDR, &p.I2C1);
    oled.init();
    oled.print(0, 0, "   Hello from   ");
    oled.print(0, 1, "      Rust      ");

    p.SYST.set_clock_source(SystClkSource::Core);
    p.SYST.set_reload(48_000_000);
    p.SYST.enable_interrupt();
    p.SYST.enable_counter();
}

fn idle() -> ! {
    rtfm::set_pending(Interrupt::EXTI0);

    loop {
        rtfm::wfi();
    }
}

fn tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
    **r.TICKS += 1;
}

fn update_ui(_t: &mut Threshold, r: EXTI0::Resources) {
    let i2c1 = &**r.I2C1;
    let oled = SSD1306(OLED_ADDR, &i2c1);

    r.STATE.update_state();

    match r.STATE.current_state() {
        State::Idle => {
            oled.print(0, 0, "      IDLE      ");
            oled.print(0, 1, "                ");
        }
        State::Soldering => {
            oled.print(0, 0, "    SOLDERING   ");
            oled.print(0, 1, "                ");
        }
        State::Cooling => {
            oled.print(0, 0, "     COOLING    ");
            oled.print(0, 1, "                ");
        }
        State::Sleep => {
            oled.print(0, 0, "     zZzZzZ     ");
            oled.print(0, 1, "                ");
        }
        State::TemperatureControl => {
            oled.print(0, 0, " <    200 C   > ");
        }
        State::Thermometer => {
            oled.print(0, 0, "     200.1 C    ");
        }
        State::Config(page) => {
            match page {
                ConfigPage::Save => {
                    oled.print(0, 0, "Save and Reset? ");
                }
            }
        }
    }
}

fn exti9_5(_t: &mut Threshold, r: EXTI9_5::Resources) {
    let exti = &**r.EXTI;
    let gpioa = &**r.GPIOA;

    // Button A
    if exti.pr.read().pr6().bit_is_set() {
        if gpioa.idr.read().idr6().bit_is_clear() {
            r.STATE.update_keys(Keys::A);
        } else {
            r.STATE.update_keys(Keys::None);
        };
        exti.pr.write(|w| w.pr6().set_bit());
    // Button B
    } else if exti.pr.read().pr9().bit_is_set() {
        if gpioa.idr.read().idr9().bit_is_clear() {
            r.STATE.update_keys(Keys::B)
        } else {
            r.STATE.update_keys(Keys::None)
        };
        exti.pr.write(|w| w.pr9().set_bit());
    // Movement
    } else if exti.pr.read().pr5().bit_is_set() {
        exti.pr.write(|w| w.pr5().set_bit());
    }

    rtfm::set_pending(Interrupt::EXTI0);
}
<|endoftext|>


<commit_before>use std::ffi::NulError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use fitserror::FitsError;

#[derive(Debug, PartialEq)]
pub enum Error {
    Fits(FitsError),
    Message(String),
    Null(NulError),
    Utf8(Utf8Error),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl ::std::convert::From<FitsError> for Error {
    fn from(error: FitsError) -> Self {
        Error::Fits(error)
    }
}

impl<'a> ::std::convert::From<&'a str> for Error {
    fn from(error: &'a str) -> Self {
        Error::Message(error.to_string())
    }
}

impl ::std::convert::From<NulError> for Error {
    fn from(error: NulError) -> Self {
        Error::Null(error)
    }
}

impl ::std::convert::From<FromUtf8Error> for Error {
    fn from(error: FromUtf8Error) -> Self {
        Error::Utf8(error.utf8_error())
    }
}

impl ::std::convert::From<Utf8Error> for Error {
    fn from(error: Utf8Error) -> Self {
        Error::Utf8(error)
    }
}

impl ::std::convert::From<Box<::std::error::Error>> for Error {
    fn from(error: Box<::std::error::Error>) -> Self {
        let description = error.description();
        let message = match error.cause() {
            Some(msg) => format!("Error: {} caused by {}", description, msg),
            None => format!("Error: {}", description),
        };
        Error::Message(message)
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        match *self {
            Error::Fits(ref e) => write!(f, "Fits error: {:?}", e),
            Error::Message(ref s) => write!(f, "Error: {}", s),
            Error::Null(ref e) => write!(f, "Error: {}", e),
            Error::Utf8(ref e) => write!(f, "Error: {}", e),
            _ => Ok(()),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        "fitsio error"
    }
}
<commit_msg>Remove unreachable pattern<commit_after>use std::ffi::NulError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use fitserror::FitsError;

#[derive(Debug, PartialEq)]
pub enum Error {
    Fits(FitsError),
    Message(String),
    Null(NulError),
    Utf8(Utf8Error),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl ::std::convert::From<FitsError> for Error {
    fn from(error: FitsError) -> Self {
        Error::Fits(error)
    }
}

impl<'a> ::std::convert::From<&'a str> for Error {
    fn from(error: &'a str) -> Self {
        Error::Message(error.to_string())
    }
}

impl ::std::convert::From<NulError> for Error {
    fn from(error: NulError) -> Self {
        Error::Null(error)
    }
}

impl ::std::convert::From<FromUtf8Error> for Error {
    fn from(error: FromUtf8Error) -> Self {
        Error::Utf8(error.utf8_error())
    }
}

impl ::std::convert::From<Utf8Error> for Error {
    fn from(error: Utf8Error) -> Self {
        Error::Utf8(error)
    }
}

impl ::std::convert::From<Box<::std::error::Error>> for Error {
    fn from(error: Box<::std::error::Error>) -> Self {
        let description = error.description();
        let message = match error.cause() {
            Some(msg) => format!("Error: {} caused by {}", description, msg),
            None => format!("Error: {}", description),
        };
        Error::Message(message)
    }
}

impl ::std::fmt::Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
        match *self {
            Error::Fits(ref e) => write!(f, "Fits error: {:?}", e),
            Error::Message(ref s) => write!(f, "Error: {}", s),
            Error::Null(ref e) => write!(f, "Error: {}", e),
            Error::Utf8(ref e) => write!(f, "Error: {}", e),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        "fitsio error"
    }
}
<|endoftext|>


<commit_before>use log::{debug, trace};
use petgraph::Direction;
use std::rc::Rc;

use super::{
    calc_this_type_for_method, java_code, merge_rule, JavaContext, JavaConverter,
    JavaForeignTypeInfo, NullAnnotation,
};
use crate::{
    error::{invalid_src_id_span, DiagnosticError, Result, SourceIdSpan},
    typemap::{
        ast::{if_option_return_some_type, DisplayToTokens, TyParamsSubstList},
        ty::{ForeignType, RustType, TraitNamesSet},
        ExpandedFType, ForeignTypeInfo, MapToForeignFlag, TypeMapConvRuleInfoExpanderHelper,
        FROM_VAR_TEMPLATE,
    },
    TypeMap,
};

struct JavaContextForArg<'a, 'b> {
    ctx: &'a mut JavaContext<'b>,
    arg_ty_span: SourceIdSpan,
    direction: Direction,
}

pub(in crate::java_jni) fn map_type(
    ctx: &mut JavaContext,
    arg_ty: &RustType,
    direction: Direction,
    arg_ty_span: SourceIdSpan,
) -> Result<JavaForeignTypeInfo> {
    debug!("map_type: arg_ty {}", arg_ty);

    let fti = do_map_type(ctx, arg_ty, direction, arg_ty_span)?;
    let ftype = &ctx.conv_map[fti];
    let origin_ftype_span = ftype.src_id_span();
    if !ftype.provides_by_module.is_empty() {
        unimplemented!();
    }
    let rule = match direction {
        petgraph::Direction::Outgoing => ftype.into_from_rust.as_ref(),
        petgraph::Direction::Incoming => ftype.from_into_rust.as_ref(),
    }
    .ok_or_else(|| {
        DiagnosticError::new2(
            origin_ftype_span,
            format!(
                "No rule to convert foreign type {} as input/output type",
                ftype.name
            ),
        )
    })?;
    let base_rt;
    let base_ft_name = ftype.typename();
    let mut java_converter = None;
    if let Some(intermediate) = rule.intermediate.as_ref() {
        if intermediate.input_to_output {
            unimplemented!();
        }
        base_rt = intermediate.intermediate_ty;
        let typename = ftype.typename();
        let converter = intermediate.conv_code.to_string();
        let intermediate_ty = intermediate.intermediate_ty;

        let rty = ctx.conv_map[intermediate_ty].clone();
        let arg_span = intermediate.conv_code.full_span();
        let inter_ft = map_type(ctx, &rty, direction, arg_span)?;
        if inter_ft.java_converter.is_some()
            || base_rt != inter_ft.base.correspoding_rust_type.to_idx()
        {
            return Err(DiagnosticError::new2(
                origin_ftype_span,
                format!(
                    "Error during conversation {} for {},\n
                    intermidiate type '{}' can not directrly converted to Java",
                    typename,
                    match direction {
                        petgraph::Direction::Outgoing => "output",
                        petgraph::Direction::Incoming => "input",
                    },
                    rty
                ),
            )
            .add_span_note(
                invalid_src_id_span(),
                if let Some(java_conv) = inter_ft.java_converter {
                    format!(
                        "it requires Java code to convert from '{}' to '{}'",
                        java_conv.java_transition_type, inter_ft.base.name
                    )
                } else {
                    format!(
                        "Type '{}' require conversation to type '{}' before usage as Java type",
                        ctx.conv_map[base_rt], inter_ft.base.correspoding_rust_type
                    )
                },
            ));
        }

        java_converter = Some(JavaConverter {
            java_transition_type: inter_ft.base.name,
            converter,
        });
    } else {
        base_rt = rule.rust_ty;
    }
    let annotation = if base_ft_name.contains("@Nullable") {
        Some(NullAnnotation::Nullable)
    } else if base_ft_name.contains("@NonNull") {
        Some(NullAnnotation::NonNull)
    } else {
        None
    };
    let mut fti = JavaForeignTypeInfo {
        base: ForeignTypeInfo {
            name: base_ft_name,
            correspoding_rust_type: ctx.conv_map[base_rt].clone(),
        },
        java_converter,
        annotation,
    };
    if fti.annotation.is_none() && !is_primitive_type(&fti.base.name) {
        fti.annotation = Some(if if_option_return_some_type(arg_ty).is_none() {
            NullAnnotation::NonNull
        } else {
            NullAnnotation::Nullable
        });
    }
    debug!("map_type: return fti: {:?}", fti);
    Ok(fti)
}

fn do_map_type(
    ctx: &mut JavaContext,
    arg_ty: &RustType,
    direction: Direction,
    arg_ty_span: SourceIdSpan,
) -> Result<ForeignType> {
    debug!("do_map_type: arg_ty {}, direction {:?}", arg_ty, direction);
    if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
        arg_ty.to_idx(),
        direction,
        MapToForeignFlag::FastSearch,
        arg_ty_span,
        calc_this_type_for_method,
    ) {
        return Ok(ftype);
    }

    let idx_subst_map: Option<(Rc<_>, TyParamsSubstList)> =
        ctx.conv_map.generic_rules().iter().find_map(|grule| {
            grule
                .is_ty_subst_of_my_generic_rtype(&arg_ty.ty, direction, |ty, traits| -> bool {
                    is_ty_implement_traits(ctx.conv_map, ty, traits)
                })
                .map(|sm| (grule.clone(), sm.into()))
        });
    if let Some((grule, subst_list)) = idx_subst_map {
        debug!(
            "do_map_type: we found generic rule for {}: {:?}",
            arg_ty, subst_list
        );
        if grule.c_types.is_some() || grule.generic_c_types.is_some() {
            return Err(DiagnosticError::new(
                grule.src_id,
                grule.span,
                "Can not handle C types for Java/JNI",
            ));
        }
        let subst_map = subst_list.as_slice().into();
        let new_rule = grule
            .subst_generic_params(
                subst_map,
                direction,
                &mut JavaContextForArg {
                    ctx,
                    arg_ty_span,
                    direction,
                },
            )
            .map_err(|err| {
                err.add_span_note(
                    (grule.src_id, grule.span),
                    "subst. of generic params into rule failed",
                )
            })?;
        debug_assert!(!new_rule.is_empty());
        merge_rule(ctx, new_rule)?;
        if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
            arg_ty.to_idx(),
            direction,
            MapToForeignFlag::FullSearch,
            arg_ty_span,
            calc_this_type_for_method,
        ) {
            return Ok(ftype);
        }
    } else if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
        arg_ty.to_idx(),
        direction,
        MapToForeignFlag::FullSearch,
        arg_ty_span,
        calc_this_type_for_method,
    ) {
        return Ok(ftype);
    }

    match direction {
        Direction::Outgoing => Err(DiagnosticError::new2(
            arg_ty_span,
            format!(
                "Do not know conversation from \
                 such rust type '{}' to Java type",
                arg_ty
            ),
        )),

        Direction::Incoming => Err(DiagnosticError::new2(
            arg_ty_span,
            format!(
                "Do not know conversation from Java type \
                 to such rust type '{}'",
                arg_ty
            ),
        )),
    }
}

fn is_primitive_type(type_name: &str) -> bool {
    match type_name {
        "void" | "boolean" | "byte" | "short" | "int" | "long" | "float" | "double" => true,
        _ => false,
    }
}

fn is_ty_implement_traits(tmap: &TypeMap, ty: &syn::Type, traits: &TraitNamesSet) -> bool {
    if let Some(rty) = tmap.ty_to_rust_type_checked(ty) {
        for tname in traits.iter() {
            if !rty.implements.contains_path(tname) {
                return false;
            }
        }
        true
    } else {
        println!(
            "warning=mapping types: type {} unknown",
            DisplayToTokens(ty)
        );
        false
    }
}

impl<'a, 'b> TypeMapConvRuleInfoExpanderHelper for JavaContextForArg<'a, 'b> {
    fn swig_i_type(&mut self, ty: &syn::Type) -> Result<syn::Type> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, self.direction, self.arg_ty_span)?;
        trace!("swig_i_type return {}", f_info.base.correspoding_rust_type);
        Ok(f_info.base.correspoding_rust_type.ty.clone())
    }
    fn swig_from_rust_to_i_type(
        &mut self,
        ty: &syn::Type,
        in_var_name: &str,
        out_var_name: &str,
    ) -> Result<String> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, Direction::Outgoing, self.arg_ty_span)?;

        let (mut conv_deps, conv_code) = self.ctx.conv_map.convert_rust_types(
            rust_ty.to_idx(),
            f_info.base.correspoding_rust_type.to_idx(),
            in_var_name,
            out_var_name,
            "#error",
            self.arg_ty_span,
        )?;
        self.ctx.rust_code.append(&mut conv_deps);
        Ok(conv_code)
    }
    fn swig_from_i_type_to_rust(
        &mut self,
        _ty: &syn::Type,
        _in_var_name: &str,
        _out_var_name: &str,
    ) -> Result<String> {
        unimplemented!();
    }
    fn swig_f_type(&mut self, ty: &syn::Type, param1: Option<&str>) -> Result<ExpandedFType> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, self.direction, self.arg_ty_span)?;
        let fname = match param1 {
            Some("NoNullAnnotations") => java_code::filter_null_annotation(&f_info.base.name)
                .trim()
                .into(),
            None => f_info.base.name.into(),
            Some(param) => {
                return Err(DiagnosticError::new2(
                    self.arg_ty_span,
                    format!("Invalid argument '{}' for swig_f_type", param),
                ))
            }
        };
        Ok(ExpandedFType {
            name: fname,
            provides_by_module: vec![],
        })
    }
    fn swig_foreign_to_i_type(&mut self, _ty: &syn::Type, _var_name: &str) -> Result<String> {
        unimplemented!();
    }
    fn swig_foreign_from_i_type(&mut self, ty: &syn::Type, var_name: &str) -> Result<String> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, Direction::Outgoing, self.arg_ty_span)?;
        if let Some(java_conv) = f_info.java_converter {
            Ok(java_conv
                .converter
                .as_str()
                .replace(FROM_VAR_TEMPLATE, var_name))
        } else {
            Ok(String::new())
        }
    }
}
<commit_msg>clippy cleanups<commit_after>use log::{debug, trace};
use petgraph::Direction;
use std::rc::Rc;

use super::{
    calc_this_type_for_method, java_code, merge_rule, JavaContext, JavaConverter,
    JavaForeignTypeInfo, NullAnnotation,
};
use crate::{
    error::{invalid_src_id_span, DiagnosticError, Result, SourceIdSpan},
    typemap::{
        ast::{if_option_return_some_type, DisplayToTokens, TyParamsSubstList},
        ty::{ForeignType, RustType, TraitNamesSet},
        ExpandedFType, ForeignTypeInfo, MapToForeignFlag, TypeMapConvRuleInfoExpanderHelper,
        FROM_VAR_TEMPLATE,
    },
    TypeMap,
};

struct JavaContextForArg<'a, 'b> {
    ctx: &'a mut JavaContext<'b>,
    arg_ty_span: SourceIdSpan,
    direction: Direction,
}

pub(in crate::java_jni) fn map_type(
    ctx: &mut JavaContext,
    arg_ty: &RustType,
    direction: Direction,
    arg_ty_span: SourceIdSpan,
) -> Result<JavaForeignTypeInfo> {
    debug!("map_type: arg_ty {}", arg_ty);

    let fti = do_map_type(ctx, arg_ty, direction, arg_ty_span)?;
    let ftype = &ctx.conv_map[fti];
    let origin_ftype_span = ftype.src_id_span();
    if !ftype.provides_by_module.is_empty() {
        unimplemented!();
    }
    let rule = match direction {
        petgraph::Direction::Outgoing => ftype.into_from_rust.as_ref(),
        petgraph::Direction::Incoming => ftype.from_into_rust.as_ref(),
    }
    .ok_or_else(|| {
        DiagnosticError::new2(
            origin_ftype_span,
            format!(
                "No rule to convert foreign type {} as input/output type",
                ftype.name
            ),
        )
    })?;
    let base_rt;
    let base_ft_name = ftype.typename();
    let mut java_converter = None;
    if let Some(intermediate) = rule.intermediate.as_ref() {
        if intermediate.input_to_output {
            unimplemented!();
        }
        base_rt = intermediate.intermediate_ty;
        let typename = ftype.typename();
        let converter = intermediate.conv_code.to_string();
        let intermediate_ty = intermediate.intermediate_ty;

        let rty = ctx.conv_map[intermediate_ty].clone();
        let arg_span = intermediate.conv_code.full_span();
        let inter_ft = map_type(ctx, &rty, direction, arg_span)?;
        if inter_ft.java_converter.is_some()
            || base_rt != inter_ft.base.correspoding_rust_type.to_idx()
        {
            return Err(DiagnosticError::new2(
                origin_ftype_span,
                format!(
                    "Error during conversation {} for {},\n
                    intermidiate type '{}' can not directrly converted to Java",
                    typename,
                    match direction {
                        petgraph::Direction::Outgoing => "output",
                        petgraph::Direction::Incoming => "input",
                    },
                    rty
                ),
            )
            .add_span_note(
                invalid_src_id_span(),
                if let Some(java_conv) = inter_ft.java_converter {
                    format!(
                        "it requires Java code to convert from '{}' to '{}'",
                        java_conv.java_transition_type, inter_ft.base.name
                    )
                } else {
                    format!(
                        "Type '{}' require conversation to type '{}' before usage as Java type",
                        ctx.conv_map[base_rt], inter_ft.base.correspoding_rust_type
                    )
                },
            ));
        }

        java_converter = Some(JavaConverter {
            java_transition_type: inter_ft.base.name,
            converter,
        });
    } else {
        base_rt = rule.rust_ty;
    }
    let annotation = if base_ft_name.contains("@Nullable") {
        Some(NullAnnotation::Nullable)
    } else if base_ft_name.contains("@NonNull") {
        Some(NullAnnotation::NonNull)
    } else {
        None
    };
    let mut fti = JavaForeignTypeInfo {
        base: ForeignTypeInfo {
            name: base_ft_name,
            correspoding_rust_type: ctx.conv_map[base_rt].clone(),
        },
        java_converter,
        annotation,
    };
    if fti.annotation.is_none() && !is_primitive_type(&fti.base.name) {
        fti.annotation = Some(if if_option_return_some_type(arg_ty).is_none() {
            NullAnnotation::NonNull
        } else {
            NullAnnotation::Nullable
        });
    }
    debug!("map_type: return fti: {:?}", fti);
    Ok(fti)
}

fn do_map_type(
    ctx: &mut JavaContext,
    arg_ty: &RustType,
    direction: Direction,
    arg_ty_span: SourceIdSpan,
) -> Result<ForeignType> {
    debug!("do_map_type: arg_ty {}, direction {:?}", arg_ty, direction);
    if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
        arg_ty.to_idx(),
        direction,
        MapToForeignFlag::FastSearch,
        arg_ty_span,
        calc_this_type_for_method,
    ) {
        return Ok(ftype);
    }

    let idx_subst_map: Option<(Rc<_>, TyParamsSubstList)> =
        ctx.conv_map.generic_rules().iter().find_map(|grule| {
            grule
                .is_ty_subst_of_my_generic_rtype(&arg_ty.ty, direction, |ty, traits| -> bool {
                    is_ty_implement_traits(ctx.conv_map, ty, traits)
                })
                .map(|sm| (grule.clone(), sm.into()))
        });
    if let Some((grule, subst_list)) = idx_subst_map {
        debug!(
            "do_map_type: we found generic rule for {}: {:?}",
            arg_ty, subst_list
        );
        if grule.c_types.is_some() || grule.generic_c_types.is_some() {
            return Err(DiagnosticError::new(
                grule.src_id,
                grule.span,
                "Can not handle C types for Java/JNI",
            ));
        }
        let subst_map = subst_list.as_slice().into();
        let new_rule = grule
            .subst_generic_params(
                subst_map,
                direction,
                &mut JavaContextForArg {
                    ctx,
                    arg_ty_span,
                    direction,
                },
            )
            .map_err(|err| {
                err.add_span_note(
                    (grule.src_id, grule.span),
                    "subst. of generic params into rule failed",
                )
            })?;
        debug_assert!(!new_rule.is_empty());
        merge_rule(ctx, new_rule)?;
        if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
            arg_ty.to_idx(),
            direction,
            MapToForeignFlag::FullSearch,
            arg_ty_span,
            calc_this_type_for_method,
        ) {
            return Ok(ftype);
        }
    } else if let Some(ftype) = ctx.conv_map.map_through_conversation_to_foreign(
        arg_ty.to_idx(),
        direction,
        MapToForeignFlag::FullSearch,
        arg_ty_span,
        calc_this_type_for_method,
    ) {
        return Ok(ftype);
    }

    match direction {
        Direction::Outgoing => Err(DiagnosticError::new2(
            arg_ty_span,
            format!(
                "Do not know conversation from \
                 such rust type '{}' to Java type",
                arg_ty
            ),
        )),

        Direction::Incoming => Err(DiagnosticError::new2(
            arg_ty_span,
            format!(
                "Do not know conversation from Java type \
                 to such rust type '{}'",
                arg_ty
            ),
        )),
    }
}

fn is_primitive_type(type_name: &str) -> bool {
    match type_name {
        "void" | "boolean" | "byte" | "short" | "int" | "long" | "float" | "double" => true,
        _ => false,
    }
}

fn is_ty_implement_traits(tmap: &TypeMap, ty: &syn::Type, traits: &TraitNamesSet) -> bool {
    if let Some(rty) = tmap.ty_to_rust_type_checked(ty) {
        for tname in traits.iter() {
            if !rty.implements.contains_path(tname) {
                return false;
            }
        }
        true
    } else {
        println!(
            "warning=mapping types: type {} unknown",
            DisplayToTokens(ty)
        );
        false
    }
}

impl<'a, 'b> TypeMapConvRuleInfoExpanderHelper for JavaContextForArg<'a, 'b> {
    fn swig_i_type(&mut self, ty: &syn::Type) -> Result<syn::Type> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, self.direction, self.arg_ty_span)?;
        trace!("swig_i_type return {}", f_info.base.correspoding_rust_type);
        Ok(f_info.base.correspoding_rust_type.ty.clone())
    }
    fn swig_from_rust_to_i_type(
        &mut self,
        ty: &syn::Type,
        in_var_name: &str,
        out_var_name: &str,
    ) -> Result<String> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, Direction::Outgoing, self.arg_ty_span)?;

        let (mut conv_deps, conv_code) = self.ctx.conv_map.convert_rust_types(
            rust_ty.to_idx(),
            f_info.base.correspoding_rust_type.to_idx(),
            in_var_name,
            out_var_name,
            "#error",
            self.arg_ty_span,
        )?;
        self.ctx.rust_code.append(&mut conv_deps);
        Ok(conv_code)
    }
    fn swig_from_i_type_to_rust(
        &mut self,
        _ty: &syn::Type,
        _in_var_name: &str,
        _out_var_name: &str,
    ) -> Result<String> {
        unimplemented!();
    }
    fn swig_f_type(&mut self, ty: &syn::Type, param1: Option<&str>) -> Result<ExpandedFType> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, self.direction, self.arg_ty_span)?;
        let fname = match param1 {
            Some("NoNullAnnotations") => java_code::filter_null_annotation(&f_info.base.name)
                .trim()
                .into(),
            None => f_info.base.name,
            Some(param) => {
                return Err(DiagnosticError::new2(
                    self.arg_ty_span,
                    format!("Invalid argument '{}' for swig_f_type", param),
                ))
            }
        };
        Ok(ExpandedFType {
            name: fname,
            provides_by_module: vec![],
        })
    }
    fn swig_foreign_to_i_type(&mut self, _ty: &syn::Type, _var_name: &str) -> Result<String> {
        unimplemented!();
    }
    fn swig_foreign_from_i_type(&mut self, ty: &syn::Type, var_name: &str) -> Result<String> {
        let rust_ty = self
            .ctx
            .conv_map
            .find_or_alloc_rust_type(ty, self.arg_ty_span.0);
        let f_info = map_type(self.ctx, &rust_ty, Direction::Outgoing, self.arg_ty_span)?;
        if let Some(java_conv) = f_info.java_converter {
            Ok(java_conv
                .converter
                .as_str()
                .replace(FROM_VAR_TEMPLATE, var_name))
        } else {
            Ok(String::new())
        }
    }
}
<|endoftext|>


<commit_before>use alloc::collections::VecDeque;
use alloc::vec::Vec;
use alloc::string::String;
use alloc::borrow::ToOwned;
use core::ptr::Unique;

use super::{keyboard::EventAction, vga};
use d7keymap::{KeyAction, KeySymbol};

/// Screen and scrollback history
#[derive(Debug, Clone)]
pub struct Output {
    lines: VecDeque<Vec<u8>>,
    height: usize,
    width: usize,
}
impl Output {
    pub fn new() -> Self {
        Self {
            lines: VecDeque::new(),
            height: 25,
            width: 80,
        }
    }

    pub fn write_str(&mut self, text: &[u8]) {
        for byte in text {
            self.write_byte(*byte);
        }
    }

    pub fn write_byte(&mut self, byte: u8) {
        assert!(byte != 0);
        assert!(byte != b'\r');

        if byte == b'\n' {
            self.new_line();
            return;
        }

        // Ensure that there is a last line and it has space for one character
        if let Some(last_line) = self.lines.back_mut() {
            if last_line.len() == self.width {
                self.new_line();
            }
        } else {
            self.lines.push_back(Vec::new());
        };

        self.lines.back_mut().unwrap().push(byte);
    }

    pub fn new_line(&mut self) {
        self.lines.push_back(Vec::new());
        if self.lines.len() > self.height {
            self.lines.pop_front();
        }
    }

    /// Render to vga buffer
    pub fn render(&mut self, buffer: &mut Unique<vga::Buffer>) {
        let color = vga::CellColor::new(vga::Color::White, vga::Color::Black);
        let mut it = self.lines.iter().rev().take(25).rev();
        let empty = Vec::new();
        for line in 0..self.height {
            let text = it.next().unwrap_or(&empty);
            for column in 0..self.width {
                let character = *text.get(column).unwrap_or(&b' ');
                unsafe {
                    buffer.as_mut().chars[line][column].write(vga::CharCell { character, color });
                }
            }
        }
    }
}

/// Keyboard input
#[derive(Debug, Clone)]
pub struct Input {
    dead_key_buffer: String,
    input_buffer: String,
}
impl Input {
    pub fn new() -> Self {
        Self {
            dead_key_buffer: String::new(),
            input_buffer: String::new(),
        }
    }

    pub fn keyboard_event(&mut self, action: EventAction) {
        use unicode_normalization::UnicodeNormalization;
        use unicode_segmentation::UnicodeSegmentation;

        match action {
            EventAction::KeyAction(action) => match action {
                KeyAction::Text(text) => {
                    if !self.dead_key_buffer.is_empty() {
                        self.input_buffer.extend(self.dead_key_buffer.drain(..));
                    }
                    self.input_buffer.push_str(&text);
                    self.input_buffer = self.input_buffer.nfc().collect();
                }
                KeyAction::Buffer(text) => {
                    self.dead_key_buffer.push_str(&text);
                }
                KeyAction::Remap(_) => unreachable!(),
                KeyAction::Ignore => {}
            },
            EventAction::Unmatched(symbol, modifiers) => match symbol.as_str() {
                "Enter" if modifiers.is_empty() => {
                    self.input_buffer.push('\n');
                }
                "Backspace" if modifiers.is_empty() => {
                    self.dead_key_buffer.clear();
                    let mut c: Vec<_> =
                        UnicodeSegmentation::graphemes(self.input_buffer.as_str(), true).collect();
                    c.pop();
                    self.input_buffer = c.join("");
                }
                _ => {}
            },
            EventAction::Ignore | EventAction::NoSuchSymbol => {}
        }
    }
}

#[derive(Debug)]
pub struct VirtualConsole {
    pub output: Output,
    pub input: Input,
}
impl VirtualConsole {
    pub fn new() -> Self {
        Self {
            output: Output::new(),
            input: Input::new(),
        }
    }

    pub fn render(&mut self, buffer: &mut Unique<vga::Buffer>) {
        // Build last line from the input and last line
        let mut s = self.output.clone();
        s.write_str(&self.input.input_buffer.as_bytes());
        s.render(buffer);
    }
}
<commit_msg>Ignore \r characters in virtual console output<commit_after>use alloc::collections::VecDeque;
use alloc::vec::Vec;
use alloc::string::String;
use alloc::borrow::ToOwned;
use core::ptr::Unique;

use super::{keyboard::EventAction, vga};
use d7keymap::{KeyAction, KeySymbol};

/// Screen and scrollback history
#[derive(Debug, Clone)]
pub struct Output {
    lines: VecDeque<Vec<u8>>,
    height: usize,
    width: usize,
}
impl Output {
    pub fn new() -> Self {
        Self {
            lines: VecDeque::new(),
            height: 25,
            width: 80,
        }
    }

    pub fn write_str(&mut self, text: &[u8]) {
        for byte in text {
            self.write_byte(*byte);
        }
    }

    pub fn write_byte(&mut self, byte: u8) {
        assert!(byte != 0);

        if byte == b'\r' {
            return;
        }

        if byte == b'\n' {
            self.new_line();
            return;
        }

        // Ensure that there is a last line and it has space for one character
        if let Some(last_line) = self.lines.back_mut() {
            if last_line.len() == self.width {
                self.new_line();
            }
        } else {
            self.lines.push_back(Vec::new());
        };

        self.lines.back_mut().unwrap().push(byte);
    }

    pub fn new_line(&mut self) {
        self.lines.push_back(Vec::new());
        if self.lines.len() > self.height {
            self.lines.pop_front();
        }
    }

    /// Render to vga buffer
    pub fn render(&mut self, buffer: &mut Unique<vga::Buffer>) {
        let color = vga::CellColor::new(vga::Color::White, vga::Color::Black);
        let mut it = self.lines.iter().rev().take(25).rev();
        let empty = Vec::new();
        for line in 0..self.height {
            let text = it.next().unwrap_or(&empty);
            for column in 0..self.width {
                let character = *text.get(column).unwrap_or(&b' ');
                unsafe {
                    buffer.as_mut().chars[line][column].write(vga::CharCell { character, color });
                }
            }
        }
    }
}

/// Keyboard input
#[derive(Debug, Clone)]
pub struct Input {
    dead_key_buffer: String,
    input_buffer: String,
}
impl Input {
    pub fn new() -> Self {
        Self {
            dead_key_buffer: String::new(),
            input_buffer: String::new(),
        }
    }

    pub fn keyboard_event(&mut self, action: EventAction) {
        use unicode_normalization::UnicodeNormalization;
        use unicode_segmentation::UnicodeSegmentation;

        match action {
            EventAction::KeyAction(action) => match action {
                KeyAction::Text(text) => {
                    if !self.dead_key_buffer.is_empty() {
                        self.input_buffer.extend(self.dead_key_buffer.drain(..));
                    }
                    self.input_buffer.push_str(&text);
                    self.input_buffer = self.input_buffer.nfc().collect();
                }
                KeyAction::Buffer(text) => {
                    self.dead_key_buffer.push_str(&text);
                }
                KeyAction::Remap(_) => unreachable!(),
                KeyAction::Ignore => {}
            },
            EventAction::Unmatched(symbol, modifiers) => match symbol.as_str() {
                "Enter" if modifiers.is_empty() => {
                    self.input_buffer.push('\n');
                }
                "Backspace" if modifiers.is_empty() => {
                    self.dead_key_buffer.clear();
                    let mut c: Vec<_> =
                        UnicodeSegmentation::graphemes(self.input_buffer.as_str(), true).collect();
                    c.pop();
                    self.input_buffer = c.join("");
                }
                _ => {}
            },
            EventAction::Ignore | EventAction::NoSuchSymbol => {}
        }
    }
}

#[derive(Debug)]
pub struct VirtualConsole {
    pub output: Output,
    pub input: Input,
}
impl VirtualConsole {
    pub fn new() -> Self {
        Self {
            output: Output::new(),
            input: Input::new(),
        }
    }

    pub fn render(&mut self, buffer: &mut Unique<vga::Buffer>) {
        // Build last line from the input and last line
        let mut s = self.output.clone();
        s.write_str(&self.input.input_buffer.as_bytes());
        s.render(buffer);
    }
}
<|endoftext|>


<commit_before>use clap::{Arg, App, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app.subcommand(SubCommand::with_name("create")
                   .about("Create an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("path")
                        .long("path")
                        .short("p")
                        .takes_value(true)
                        .required(false)
                        .help("Create at this store path"))
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(false)
                        .help("Same as --path, for consistency"))
                   .arg(Arg::with_name("from-raw")
                        .long("from-raw")
                        .takes_value(true)
                        .help("Create a new entry by reading this file ('-' for stdin)"))
                   .subcommand(SubCommand::with_name("entry")
                               .about("Create an entry via commandline")
                               .version("0.1")
                               .arg(Arg::with_name("content")
                                    .long("content")
                                    .short("c")
                                    .takes_value(true)
                                    .help("Content for the Entry from commandline"))
                               .arg(Arg::with_name("content-from")
                                    .long("content-from")
                                    .short("f")
                                    .takes_value(true)
                                    .help("Content for the Entry from this file ('-' for stdin)"))
                               .arg(Arg::with_name("header")
                                    .long("header")
                                    .short("h")
                                    .takes_value(true)
                                    .multiple(true)
                                    .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                               )
                   )

       .subcommand(SubCommand::with_name("retrieve")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retreive by Store Path, where root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))
                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("update")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Update Store Entry with this path. Root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .takes_value(true)
                        .help("Take the content for the new Entry from this file ('-' for stdin)"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .takes_value(true)
                        .multiple(true)
                        .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                   )

       .subcommand(SubCommand::with_name("delete")
                   .about("Delete an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Remove Store Entry with this path. Root (/) is the store itself"))
                   )
}

<commit_msg>Add clap::ArgGroup to rely on clap for mutually exclusive args<commit_after>use clap::{Arg, App, ArgGroup, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app.subcommand(SubCommand::with_name("create")
                   .about("Create an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("path")
                        .long("path")
                        .short("p")
                        .takes_value(true)
                        .required(false)
                        .help("Create at this store path"))
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(false)
                        .help("Same as --path, for consistency"))
                   .arg(Arg::with_name("from-raw")
                        .long("from-raw")
                        .takes_value(true)
                        .help("Create a new entry by reading this file ('-' for stdin)"))

                   .group(ArgGroup::with_name("create-destination-group")
                          .args(&["path", "id"])
                          .required(true))

                   .subcommand(SubCommand::with_name("entry")
                               .about("Create an entry via commandline")
                               .version("0.1")
                               .arg(Arg::with_name("content")
                                    .long("content")
                                    .short("c")
                                    .takes_value(true)
                                    .help("Content for the Entry from commandline"))
                               .arg(Arg::with_name("content-from")
                                    .long("content-from")
                                    .short("f")
                                    .takes_value(true)
                                    .help("Content for the Entry from this file ('-' for stdin)"))

                               .group(ArgGroup::with_name("create-content-group")
                                      .args(&["content", "content-from"])
                                      .required(false))

                               .arg(Arg::with_name("header")
                                    .long("header")
                                    .short("h")
                                    .takes_value(true)
                                    .multiple(true)
                                    .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                               )
                   )

       .subcommand(SubCommand::with_name("retrieve")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retreive by Store Path, where root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))

                   .group(ArgGroup::with_name("retrieve-print-group")
                          .args(&["header-json", "raw"])
                          .required(true))

                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("update")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Update Store Entry with this path. Root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .takes_value(true)
                        .help("Take the content for the new Entry from this file ('-' for stdin)"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .takes_value(true)
                        .multiple(true)
                        .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                   )

       .subcommand(SubCommand::with_name("delete")
                   .about("Delete an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Remove Store Entry with this path. Root (/) is the store itself"))
                   )
}

<|endoftext|>


<commit_before>extern crate ratelimit_meter;

use ratelimit_meter::{Decider, MultiDecider, NegativeMultiDecision, GCRA};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut gcra: GCRA = GCRA::for_capacity(5).unwrap().into();
    assert_eq!(Ok(()), gcra.check());
}
#[test]
fn rejects_too_many() {
    let mut gcra = GCRA::for_capacity(1).unwrap().build();
    let now = Instant::now();
    gcra.check_at(now).unwrap();
    gcra.check_at(now).unwrap();
    assert_ne!(Ok(()), gcra.check_at(now), "{:?}", gcra);
}
#[test]
fn allows_after_interval() {
    let mut gcra = GCRA::for_capacity(1).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    gcra.check_at(now).unwrap();
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert!(gcra.check_at(now + ms * 2).is_err());
    // should be ok again in 1s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_at(next));
}

#[test]
fn allows_n_after_interval() {
    let mut gcra = GCRA::for_capacity(2).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, now));
    assert!(!gcra.check_n_at(2, now + ms).is_ok());
    // should be ok again in 1.5s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, next), "now: {:?}", next);

    // should always accommodate 0 cells:
    assert_eq!(Ok(()), gcra.check_n_at(0, next));
}

#[test]
fn never_allows_more_than_capacity() {
    let mut gcra = GCRA::for_capacity(5).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert!(gcra.check_n_at(15, now).is_err());

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert!(gcra.check_n_at(15, now + (ms * 3 * 1000)).is_err());

    let result = gcra.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn actual_threadsafety() {
    let mut lim = GCRA::for_capacity(20).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut children = vec![];

    lim.check_at(now).unwrap();
    for _i in 0..20 {
        let mut lim = lim.clone();
        children.push(thread::spawn(move || {
            lim.check_at(now).unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
    assert!(!lim.check_at(now + ms * 2).is_ok());
    assert_eq!(Ok(()), lim.check_at(now + ms * 1000));
}
<commit_msg>Add a test case for the .per() argument in GCRA builders<commit_after>extern crate ratelimit_meter;

use ratelimit_meter::{Decider, MultiDecider, NegativeMultiDecision, GCRA};
use std::thread;
use std::time::{Duration, Instant};

#[test]
fn accepts_first_cell() {
    let mut gcra: GCRA = GCRA::for_capacity(5).unwrap().into();
    assert_eq!(Ok(()), gcra.check());
}
#[test]
fn rejects_too_many() {
    let mut gcra = GCRA::for_capacity(1).unwrap().build();
    let now = Instant::now();
    gcra.check_at(now).unwrap();
    gcra.check_at(now).unwrap();
    assert_ne!(Ok(()), gcra.check_at(now), "{:?}", gcra);
}

#[test]
fn allows_after_interval() {
    let mut gcra = GCRA::for_capacity(1).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    gcra.check_at(now).unwrap();
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert!(gcra.check_at(now + ms * 2).is_err());
    // should be ok again in 1s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_at(next));
}

#[test]
fn allows_n_after_interval() {
    let mut gcra = GCRA::for_capacity(2).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, now));
    assert!(!gcra.check_n_at(2, now + ms).is_ok());
    // should be ok again in 1.5s:
    let next = now + Duration::from_secs(1);
    assert_eq!(Ok(()), gcra.check_n_at(2, next), "now: {:?}", next);

    // should always accommodate 0 cells:
    assert_eq!(Ok(()), gcra.check_n_at(0, next));
}

#[test]
fn correctly_handles_per() {
    let ms = Duration::from_millis(1);
    let mut gcra = GCRA::for_capacity(1).unwrap().per(ms * 20).build();
    let now = Instant::now();

    assert_eq!(Ok(()), gcra.check_at(now));
    assert_eq!(Ok(()), gcra.check_at(now + ms));
    assert!(!gcra.check_at(now + ms * 10).is_ok());
    assert_eq!(Ok(()), gcra.check_at(now + ms * 20));
}

#[test]
fn never_allows_more_than_capacity() {
    let mut gcra = GCRA::for_capacity(5).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);

    // Should not allow the first 15 cells on a capacity 5 bucket:
    assert!(gcra.check_n_at(15, now).is_err());

    // After 3 and 20 seconds, it should not allow 15 on that bucket either:
    assert!(gcra.check_n_at(15, now + (ms * 3 * 1000)).is_err());

    let result = gcra.check_n_at(15, now + (ms * 20 * 1000));
    match result {
        Err(NegativeMultiDecision::InsufficientCapacity(n)) => assert_eq!(n, 15),
        _ => panic!("Did not expect {:?}", result),
    }
}

#[test]
fn actual_threadsafety() {
    let mut lim = GCRA::for_capacity(20).unwrap().build();
    let now = Instant::now();
    let ms = Duration::from_millis(1);
    let mut children = vec![];

    lim.check_at(now).unwrap();
    for _i in 0..20 {
        let mut lim = lim.clone();
        children.push(thread::spawn(move || {
            lim.check_at(now).unwrap();
        }));
    }
    for child in children {
        child.join().unwrap();
    }
    assert!(!lim.check_at(now + ms * 2).is_ok());
    assert_eq!(Ok(()), lim.check_at(now + ms * 1000));
}
<|endoftext|>


<commit_before>#![feature(abi_x86_interrupt)]
#![no_std]
#![no_main]

use core::panic::PanicInfo;
use lazy_static::lazy_static;
use testing::{exit_qemu, serial_print, serial_println, QemuExitCode};

#[no_mangle]
#[allow(unconditional_recursion)]
pub extern "C" fn _start() -> ! {
    serial_print!("double_fault_stack_overflow... ");
    testing::gdt::init();
    init_test_idt();

    fn stack_overflow() {
        stack_overflow(); // for each recursion, the return address is pushed
    }

    // trigger a stack overflow
    stack_overflow();

    serial_println!("[failed]");
    serial_println!("    No exception occured");
    exit_qemu(QemuExitCode::Failed);

    loop {}
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    testing::test_panic_handler(info)
}

use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};

lazy_static! {
    static ref TEST_IDT: InterruptDescriptorTable = {
        let mut idt = InterruptDescriptorTable::new();
        unsafe {
            idt.double_fault
                .set_handler_fn(double_fault_handler)
                .set_stack_index(testing::gdt::DOUBLE_FAULT_IST_INDEX);
        }

        idt
    };
}

pub fn init_test_idt() {
    TEST_IDT.load();
}

extern "x86-interrupt" fn double_fault_handler(
    _stack_frame: &mut InterruptStackFrame,
    _error_code: u64,
) {
    serial_println!("[ok]");
    exit_qemu(QemuExitCode::Success);
    loop {}
}
<commit_msg>Fix test by making double fault handler diverging<commit_after>#![feature(abi_x86_interrupt)]
#![no_std]
#![no_main]

use core::panic::PanicInfo;
use lazy_static::lazy_static;
use testing::{exit_qemu, serial_print, serial_println, QemuExitCode};

#[no_mangle]
#[allow(unconditional_recursion)]
pub extern "C" fn _start() -> ! {
    serial_print!("double_fault_stack_overflow... ");
    testing::gdt::init();
    init_test_idt();

    fn stack_overflow() {
        stack_overflow(); // for each recursion, the return address is pushed
    }

    // trigger a stack overflow
    stack_overflow();

    serial_println!("[failed]");
    serial_println!("    No exception occured");
    exit_qemu(QemuExitCode::Failed);

    loop {}
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    testing::test_panic_handler(info)
}

use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};

lazy_static! {
    static ref TEST_IDT: InterruptDescriptorTable = {
        let mut idt = InterruptDescriptorTable::new();
        unsafe {
            idt.double_fault
                .set_handler_fn(double_fault_handler)
                .set_stack_index(testing::gdt::DOUBLE_FAULT_IST_INDEX);
        }

        idt
    };
}

pub fn init_test_idt() {
    TEST_IDT.load();
}

extern "x86-interrupt" fn double_fault_handler(
    _stack_frame: &mut InterruptStackFrame,
    _error_code: u64,
) -> ! {
    serial_println!("[ok]");
    exit_qemu(QemuExitCode::Success);
    loop {}
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]

use std::borrow::Cow;

extern crate proc_macro2;
#[macro_use]
extern crate quote;

use proc_macro2::{Ident, Span, TokenStream};
use quote::TokenStreamExt;

mod conditional {
    #[cfg(integer128)]
    mod integer128;
}

struct X;

impl quote::ToTokens for X {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Ident::new("X", Span::call_site()));
    }
}

#[test]
fn test_quote_impl() {
    let tokens = quote! {
        impl<'a, T: ToTokens> ToTokens for &'a T {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                (**self).to_tokens(tokens)
            }
        }
    };

    let expected = concat!(
        "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
        "fn to_tokens ( & self , tokens : & mut TokenStream ) { ",
        "( * * self ) . to_tokens ( tokens ) ",
        "} ",
        "}"
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_substitution() {
    let x = X;
    let tokens = quote!(#x <#x> (#x) [#x] {#x});

    let expected = "X < X > ( X ) [ X ] { X }";

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_iter() {
    let primes = &[X, X, X, X];

    assert_eq!("X X X X", quote!(#(#primes)*).to_string());

    assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());

    assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
}

#[test]
fn test_advanced() {
    let generics = quote!( <'a, T> );

    let where_clause = quote!( where T: Serialize );

    let field_ty = quote!(String);

    let item_ty = quote!(Cow<'a, str>);

    let path = quote!(SomeTrait::serialize_with);

    let value = quote!(self.x);

    let tokens = quote! {
        struct SerializeWith #generics #where_clause {
            value: &'a #field_ty,
            phantom: ::std::marker::PhantomData<#item_ty>,
        }

        impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
                where S: ::serde::Serializer
            {
                #path(self.value, s)
            }
        }

        SerializeWith {
            value: #value,
            phantom: ::std::marker::PhantomData::<#item_ty>,
        }
    };

    let expected = concat!(
        "struct SerializeWith < 'a , T > where T : Serialize { ",
        "value : & 'a String , ",
        "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
        "} ",
        "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
        "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
        "where S : :: serde :: Serializer ",
        "{ ",
        "SomeTrait :: serialize_with ( self . value , s ) ",
        "} ",
        "} ",
        "SerializeWith { ",
        "value : self . x , ",
        "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
        "}"
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_integer() {
    let ii8 = -1i8;
    let ii16 = -1i16;
    let ii32 = -1i32;
    let ii64 = -1i64;
    let iisize = -1isize;
    let uu8 = 1u8;
    let uu16 = 1u16;
    let uu32 = 1u32;
    let uu64 = 1u64;
    let uusize = 1usize;

    let tokens = quote! {
        #ii8 #ii16 #ii32 #ii64 #iisize
        #uu8 #uu16 #uu32 #uu64 #uusize
    };
    let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_floating() {
    let e32 = 2.345f32;

    let e64 = 2.345f64;

    let tokens = quote! {
        #e32
        #e64
    };
    let expected = concat!("2.345f32 2.345f64");
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_char() {
    let zero = '\0';
    let pound = '#';
    let quote = '"';
    let apost = '\'';
    let newline = '\n';
    let heart = '\u{2764}';

    let tokens = quote! {
        #zero #pound #quote #apost #newline #heart
    };
    let expected = "'\\u{0}' '#' '\\\"' '\\'' '\\n' '\\u{2764}'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_str() {
    let s = "\0 a 'b \" c";
    let tokens = quote!(#s);
    let expected = "\"\\u{0} a \\'b \\\" c\"";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_string() {
    let s = "\0 a 'b \" c".to_string();
    let tokens = quote!(#s);
    let expected = "\"\\u{0} a \\'b \\\" c\"";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_ident() {
    let foo = Ident::new("Foo", Span::call_site());
    let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
    let tokens = quote!(struct #foo; enum #bar {});
    let expected = "struct Foo ; enum Bar7 { }";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_duplicate() {
    let ch = 'x';

    let tokens = quote!(#ch #ch);

    let expected = "'x' 'x'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_fancy_repetition() {
    let foo = vec!["a", "b"];
    let bar = vec![true, false];

    let tokens = quote! {
        #(#foo: #bar),*
    };

    let expected = r#""a" : true , "b" : false"#;
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_nested_fancy_repetition() {
    let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];

    let tokens = quote! {
        #(
            #(#nested)*
        ),*
    };

    let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_repetition() {
    let tokens = quote!(#(a b)* #(c d),*);
    assert_eq!("", tokens.to_string());
}

#[test]
fn test_variable_name_conflict() {
    // The implementation of `#(...),*` uses the variable `_i` but it should be
    // fine, if a little confusing when debugging.
    let _i = vec!['a', 'b'];
    let tokens = quote! { #(#_i),* };
    let expected = "'a' , 'b'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_quote() {
    let tokens = quote!();
    assert_eq!("", tokens.to_string());
}

#[test]
fn test_box_str() {
    let b = "str".to_owned().into_boxed_str();
    let tokens = quote! { #b };
    assert_eq!("\"str\"", tokens.to_string());
}

#[test]
fn test_cow() {
    let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));

    let ident = Ident::new("borrowed", Span::call_site());
    let borrowed = Cow::Borrowed(&ident);

    let tokens = quote! { #owned #borrowed };
    assert_eq!("owned borrowed", tokens.to_string());
}

#[test]
fn test_closure() {
    fn field_i(i: usize) -> Ident {
        Ident::new(&format!("__field{}", i), Span::call_site())
    }

    let fields = (0usize..3)
        .map(field_i as fn(_) -> _)
        .map(|var| quote! { #var });

    let tokens = quote! { #(#fields)* };
    assert_eq!("__field0 __field1 __field2", tokens.to_string());
}

#[test]
fn test_append_tokens() {
    let mut a = quote!(a);
    let b = quote!(b);
    a.append_all(b);
    assert_eq!("a b", a.to_string());
}
<commit_msg>Update tests for new proc-macro2 escape behavior<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]

use std::borrow::Cow;

extern crate proc_macro2;
#[macro_use]
extern crate quote;

use proc_macro2::{Ident, Span, TokenStream};
use quote::TokenStreamExt;

mod conditional {
    #[cfg(integer128)]
    mod integer128;
}

struct X;

impl quote::ToTokens for X {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Ident::new("X", Span::call_site()));
    }
}

#[test]
fn test_quote_impl() {
    let tokens = quote! {
        impl<'a, T: ToTokens> ToTokens for &'a T {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                (**self).to_tokens(tokens)
            }
        }
    };

    let expected = concat!(
        "impl < 'a , T : ToTokens > ToTokens for & 'a T { ",
        "fn to_tokens ( & self , tokens : & mut TokenStream ) { ",
        "( * * self ) . to_tokens ( tokens ) ",
        "} ",
        "}"
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_substitution() {
    let x = X;
    let tokens = quote!(#x <#x> (#x) [#x] {#x});

    let expected = "X < X > ( X ) [ X ] { X }";

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_iter() {
    let primes = &[X, X, X, X];

    assert_eq!("X X X X", quote!(#(#primes)*).to_string());

    assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string());

    assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string());
}

#[test]
fn test_advanced() {
    let generics = quote!( <'a, T> );

    let where_clause = quote!( where T: Serialize );

    let field_ty = quote!(String);

    let item_ty = quote!(Cow<'a, str>);

    let path = quote!(SomeTrait::serialize_with);

    let value = quote!(self.x);

    let tokens = quote! {
        struct SerializeWith #generics #where_clause {
            value: &'a #field_ty,
            phantom: ::std::marker::PhantomData<#item_ty>,
        }

        impl #generics ::serde::Serialize for SerializeWith #generics #where_clause {
            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
                where S: ::serde::Serializer
            {
                #path(self.value, s)
            }
        }

        SerializeWith {
            value: #value,
            phantom: ::std::marker::PhantomData::<#item_ty>,
        }
    };

    let expected = concat!(
        "struct SerializeWith < 'a , T > where T : Serialize { ",
        "value : & 'a String , ",
        "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ",
        "} ",
        "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ",
        "fn serialize < S > ( & self , s : & mut S ) -> Result < ( ) , S :: Error > ",
        "where S : :: serde :: Serializer ",
        "{ ",
        "SomeTrait :: serialize_with ( self . value , s ) ",
        "} ",
        "} ",
        "SerializeWith { ",
        "value : self . x , ",
        "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ",
        "}"
    );

    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_integer() {
    let ii8 = -1i8;
    let ii16 = -1i16;
    let ii32 = -1i32;
    let ii64 = -1i64;
    let iisize = -1isize;
    let uu8 = 1u8;
    let uu16 = 1u16;
    let uu32 = 1u32;
    let uu64 = 1u64;
    let uusize = 1usize;

    let tokens = quote! {
        #ii8 #ii16 #ii32 #ii64 #iisize
        #uu8 #uu16 #uu32 #uu64 #uusize
    };
    let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_floating() {
    let e32 = 2.345f32;

    let e64 = 2.345f64;

    let tokens = quote! {
        #e32
        #e64
    };
    let expected = concat!("2.345f32 2.345f64");
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_char() {
    let zero = '\0';
    let pound = '#';
    let quote = '"';
    let apost = '\'';
    let newline = '\n';
    let heart = '\u{2764}';

    let tokens = quote! {
        #zero #pound #quote #apost #newline #heart
    };
    let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\\u{2764}'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_str() {
    let s = "\0 a 'b \" c";
    let tokens = quote!(#s);
    let expected = "\"\\u{0} a 'b \\\" c\"";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_string() {
    let s = "\0 a 'b \" c".to_string();
    let tokens = quote!(#s);
    let expected = "\"\\u{0} a 'b \\\" c\"";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_ident() {
    let foo = Ident::new("Foo", Span::call_site());
    let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
    let tokens = quote!(struct #foo; enum #bar {});
    let expected = "struct Foo ; enum Bar7 { }";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_duplicate() {
    let ch = 'x';

    let tokens = quote!(#ch #ch);

    let expected = "'x' 'x'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_fancy_repetition() {
    let foo = vec!["a", "b"];
    let bar = vec![true, false];

    let tokens = quote! {
        #(#foo: #bar),*
    };

    let expected = r#""a" : true , "b" : false"#;
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_nested_fancy_repetition() {
    let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']];

    let tokens = quote! {
        #(
            #(#nested)*
        ),*
    };

    let expected = "'a' 'b' 'c' , 'x' 'y' 'z'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_repetition() {
    let tokens = quote!(#(a b)* #(c d),*);
    assert_eq!("", tokens.to_string());
}

#[test]
fn test_variable_name_conflict() {
    // The implementation of `#(...),*` uses the variable `_i` but it should be
    // fine, if a little confusing when debugging.
    let _i = vec!['a', 'b'];
    let tokens = quote! { #(#_i),* };
    let expected = "'a' , 'b'";
    assert_eq!(expected, tokens.to_string());
}

#[test]
fn test_empty_quote() {
    let tokens = quote!();
    assert_eq!("", tokens.to_string());
}

#[test]
fn test_box_str() {
    let b = "str".to_owned().into_boxed_str();
    let tokens = quote! { #b };
    assert_eq!("\"str\"", tokens.to_string());
}

#[test]
fn test_cow() {
    let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));

    let ident = Ident::new("borrowed", Span::call_site());
    let borrowed = Cow::Borrowed(&ident);

    let tokens = quote! { #owned #borrowed };
    assert_eq!("owned borrowed", tokens.to_string());
}

#[test]
fn test_closure() {
    fn field_i(i: usize) -> Ident {
        Ident::new(&format!("__field{}", i), Span::call_site())
    }

    let fields = (0usize..3)
        .map(field_i as fn(_) -> _)
        .map(|var| quote! { #var });

    let tokens = quote! { #(#fields)* };
    assert_eq!("__field0 __field1 __field2", tokens.to_string());
}

#[test]
fn test_append_tokens() {
    let mut a = quote!(a);
    let b = quote!(b);
    a.append_all(b);
    assert_eq!("a b", a.to_string());
}
<|endoftext|>