<commit_before>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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
//
//     http://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.

//! # gl_generator
//!
//! `gl_generator` is an OpenGL bindings generator plugin. It defines a macro named
//!  `generate_gl_bindings!` which can be used to generate all constants and functions of a
//!  given OpenGL version.
//!
//! ## Example
//!
//! ```rust
//! #[phase(plugin)]
//! extern crate gl_generator;
//! extern crate libc;
//!
//! use std::mem;
//! use self::types::*;
//!
//! generate_gl_bindings!("gl", "core", "4.5", "static", [ "GL_EXT_texture_filter_anisotropic" ])
//! ```
//!
//! ## Parameters
//!
//! * API: Can be `gl`, `gles1`, `gles2`, `wgl`, `glx`, `egl`.
//! * Profile: Can be `core` or `compatibility`. `core` will only include all functions supported
//!    by the requested version it self, while `compatibility` will include all the functions from
//!    previous versions as well.
//! * Version: The requested version of OpenGL, WGL, GLX or EGL in the format `x.x`.
//! * Generator: Can be `static` or `struct`.
//! * Extensions (optional): An array of extensions to include in the bindings.
//!
//! ## About EGL
//!
//! When you generate bindings for EGL, the following platform-specific types must be declared
//!  *at the same level where you call `generate_gl_bindings`*:
//!
//! - khronos_utime_nanoseconds_t
//! - khronos_uint64_t
//! - khronos_ssize_t
//! - EGLNativeDisplayType
//! - EGLNativePixmapType
//! - EGLNativeWindowType
//! - EGLint
//! - NativeDisplayType
//! - NativePixmapType
//! - NativeWindowType
//!

#![crate_name = "gl_generator"]
#![comment = "OpenGL function loader generator."]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(phase)]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(plugin_registrar)]
#![feature(quote)]

#[phase(plugin, link)]
extern crate log;

#[phase(plugin)]
extern crate regex_macros;

extern crate khronos_api;
extern crate regex;
extern crate rustc;
extern crate syntax;

use std::path::Path;
use std::io::{File, Reader};

use syntax::parse::token;
use syntax::ast::{ Item, TokenTree };
use syntax::ext::base::{expr_to_string, get_exprs_from_tts, DummyResult, ExtCtxt, MacResult};
use syntax::codemap::Span;

use registry::*;
use static_gen::StaticGenerator;
use struct_gen::StructGenerator;

mod common;
pub mod static_gen;
pub mod struct_gen;
pub mod registry;
pub mod ty;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("generate_gl_bindings", macro_handler);
}

// this is the object that we will return from the "generate_gl_bindings" macro expansion
struct MacroResult {
    content: Vec<::std::gc::Gc<Item>>
}
impl MacResult for MacroResult {
    fn make_def(&self) -> Option<::syntax::ext::base::MacroDef> { None }
    fn make_expr(&self) -> Option<::std::gc::Gc<::syntax::ast::Expr>> { None }
    fn make_pat(&self) -> Option<::std::gc::Gc<::syntax::ast::Pat>> { None }
    fn make_stmt(&self) -> Option<::std::gc::Gc<::syntax::ast::Stmt>> { None }

    fn make_items(&self) -> Option<::syntax::util::small_vector::SmallVector<::std::gc::Gc<Item>>> {
        Some(::syntax::util::small_vector::SmallVector::many(self.content.clone()))
    }
}

// handler for generate_gl_bindings!
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult+'static> {
    // getting the arguments from the macro
    let (api, profile, version, generator, extensions) = match parse_macro_arguments(ecx, span.clone(), token_tree) {
        Some(t) => t,
        None => return DummyResult::any(span)
    };

    let (ns, source) = match api.as_slice() {
        "gl"  => (Gl, khronos_api::GL_XML),
        "glx" => (Glx, khronos_api::GLX_XML),
        "wgl" => (Wgl, khronos_api::WGL_XML),
        "egl" => (Egl, khronos_api::EGL_XML),
        "gles1"  => (Gles1, khronos_api::GL_XML),
        "gles2"  => (Gles2, khronos_api::GL_XML),
        ns => {
            ecx.span_err(span, format!("Unexpected opengl namespace '{}'", ns).as_slice());
            return DummyResult::any(span)
        }
    };

    let filter = Some(Filter {
        extensions: extensions,
        profile: profile,
        version: version,
        api: api,
    });

    // generating the registry of all bindings
    let reg = {
        use std::io::BufReader;
        use std::task;

        let result = task::try(proc() {
            let reader = BufReader::new(source.as_bytes());
            Registry::from_xml(reader, ns, filter)
        });

        match result {
            Ok(reg) => reg,
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while parsing the registry");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // generating the Rust bindings as a source code into "buffer"
    let buffer = {
        use std::io::MemWriter;
        use std::task;

        // calling the generator
        let result = match generator.as_slice() {
            "static" => task::try(proc() {
                let mut buffer = MemWriter::new();
                StaticGenerator::write(&mut buffer, &reg, ns);
                buffer
            }),

            "struct" => task::try(proc() {
                let mut buffer = MemWriter::new();
                StructGenerator::write(&mut buffer, &reg, ns);
                buffer
            }),

            generator => {
                ecx.span_err(span, format!("unknown generator type: {}", generator).as_slice());
                return DummyResult::any(span);
            },
        };

        // processing the result
        match result {
            Ok(buffer) => buffer.unwrap(),
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while generating the bindings");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while generating the bindings");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while generating the bindings");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // creating a new Rust parser from these bindings
    let content = match String::from_utf8(buffer) {
        Ok(s) => s,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };
    let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(),
        Path::new(ecx.codemap().span_to_filename(span)).display().to_string(), content);

    // getting all the items defined by the bindings
    let mut items = Vec::new();
    loop {
        match parser.parse_item_with_outer_attributes() {
            None => break,
            Some(i) => items.push(i)
        }
    }
    if !parser.eat(&token::EOF) {
        ecx.span_err(span, "the rust parser failed to compile all the generated bindings (meaning there is a bug in this library!)");
        return DummyResult::any(span)
    }
    box MacroResult { content: items } as Box<MacResult>
}

fn parse_macro_arguments(ecx: &mut ExtCtxt, span: Span, tts: &[syntax::ast::TokenTree])
                        -> Option<(String, String, String, String, Vec<String>)>
{
    // getting parameters list
    let values = match get_exprs_from_tts(ecx, span, tts) {
        Some(v) => v,
        None => return None
    };

    if values.len() != 4 && values.len() != 5 {
        ecx.span_err(span, format!("expected 4 or 5 arguments but got {}", values.len())
            .as_slice());
        return None;
    }

    // computing the extensions (last parameter)
    let extensions: Vec<String> = match values.as_slice().get(4) {
        None => Vec::new(),
        Some(vector) => {
            use syntax::ast::ExprVec;

            match vector.node {
                // only [ ... ] is accepted
                ExprVec(ref list) => {
                    // turning each element into a string
                    let mut result = Vec::new();
                    for element in list.iter() {
                        match expr_to_string(ecx, element.clone(), "expected string literal") {
                            Some((s, _)) => result.push(s.get().to_string()),
                            None => return None
                        }
                    }
                    result
                },
                _ => {
                    ecx.span_err(span, format!("last argument must be a vector").as_slice());
                    return None;
                }
            }
        }
    };

    // computing other parameters
    match (
        expr_to_string(ecx, values[0].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[1].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[2].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[3].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() })
    ) {
        (Some(a), Some(b), Some(c), Some(d)) => Some((a, b, c, d, extensions)),
        _ => None
    }
}
<commit_msg>fixed for latest rust<commit_after>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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
//
//     http://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.

//! # gl_generator
//!
//! `gl_generator` is an OpenGL bindings generator plugin. It defines a macro named
//!  `generate_gl_bindings!` which can be used to generate all constants and functions of a
//!  given OpenGL version.
//!
//! ## Example
//!
//! ```rust
//! #[phase(plugin)]
//! extern crate gl_generator;
//! extern crate libc;
//!
//! use std::mem;
//! use self::types::*;
//!
//! generate_gl_bindings!("gl", "core", "4.5", "static", [ "GL_EXT_texture_filter_anisotropic" ])
//! ```
//!
//! ## Parameters
//!
//! * API: Can be `gl`, `gles1`, `gles2`, `wgl`, `glx`, `egl`.
//! * Profile: Can be `core` or `compatibility`. `core` will only include all functions supported
//!    by the requested version it self, while `compatibility` will include all the functions from
//!    previous versions as well.
//! * Version: The requested version of OpenGL, WGL, GLX or EGL in the format `x.x`.
//! * Generator: Can be `static` or `struct`.
//! * Extensions (optional): An array of extensions to include in the bindings.
//!
//! ## About EGL
//!
//! When you generate bindings for EGL, the following platform-specific types must be declared
//!  *at the same level where you call `generate_gl_bindings`*:
//!
//! - khronos_utime_nanoseconds_t
//! - khronos_uint64_t
//! - khronos_ssize_t
//! - EGLNativeDisplayType
//! - EGLNativePixmapType
//! - EGLNativeWindowType
//! - EGLint
//! - NativeDisplayType
//! - NativePixmapType
//! - NativeWindowType
//!

#![crate_name = "gl_generator"]
#![comment = "OpenGL function loader generator."]
#![license = "ASL2"]
#![crate_type = "dylib"]

#![feature(phase)]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(plugin_registrar)]
#![feature(quote)]

#[phase(plugin, link)]
extern crate log;

#[phase(plugin)]
extern crate regex_macros;

extern crate khronos_api;
extern crate regex;
extern crate rustc;
extern crate syntax;

use std::path::Path;
use std::io::{File, Reader};

use syntax::parse::token;
use syntax::ast::{ Item, TokenTree };
use syntax::ext::base::{expr_to_string, get_exprs_from_tts, DummyResult, ExtCtxt, MacResult};
use syntax::codemap::Span;

use registry::*;
use static_gen::StaticGenerator;
use struct_gen::StructGenerator;

mod common;
pub mod static_gen;
pub mod struct_gen;
pub mod registry;
pub mod ty;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_macro("generate_gl_bindings", macro_handler);
}

// this is the object that we will return from the "generate_gl_bindings" macro expansion
struct MacroResult {
    content: Vec<::std::gc::Gc<Item>>
}
impl MacResult for MacroResult {
    fn make_def(&self) -> Option<::syntax::ext::base::MacroDef> { None }
    fn make_expr(&self) -> Option<::std::gc::Gc<::syntax::ast::Expr>> { None }
    fn make_pat(&self) -> Option<::std::gc::Gc<::syntax::ast::Pat>> { None }
    fn make_stmt(&self) -> Option<::std::gc::Gc<::syntax::ast::Stmt>> { None }

    fn make_items(&self) -> Option<::syntax::util::small_vector::SmallVector<::std::gc::Gc<Item>>> {
        Some(::syntax::util::small_vector::SmallVector::many(self.content.clone()))
    }
}

// handler for generate_gl_bindings!
fn macro_handler(ecx: &mut ExtCtxt, span: Span, token_tree: &[TokenTree]) -> Box<MacResult+'static> {
    // getting the arguments from the macro
    let (api, profile, version, generator, extensions) = match parse_macro_arguments(ecx, span.clone(), token_tree) {
        Some(t) => t,
        None => return DummyResult::any(span)
    };

    let (ns, source) = match api.as_slice() {
        "gl"  => (Gl, khronos_api::GL_XML),
        "glx" => (Glx, khronos_api::GLX_XML),
        "wgl" => (Wgl, khronos_api::WGL_XML),
        "egl" => (Egl, khronos_api::EGL_XML),
        "gles1"  => (Gles1, khronos_api::GL_XML),
        "gles2"  => (Gles2, khronos_api::GL_XML),
        ns => {
            ecx.span_err(span, format!("Unexpected opengl namespace '{}'", ns).as_slice());
            return DummyResult::any(span)
        }
    };

    let filter = Some(Filter {
        extensions: extensions,
        profile: profile,
        version: version,
        api: api,
    });

    // generating the registry of all bindings
    let reg = {
        use std::io::BufReader;
        use std::task;

        let result = task::try(proc() {
            let reader = BufReader::new(source.as_bytes());
            Registry::from_xml(reader, ns, filter)
        });

        match result {
            Ok(reg) => reg,
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = &*err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while parsing the registry");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while parsing the registry");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // generating the Rust bindings as a source code into "buffer"
    let buffer = {
        use std::io::MemWriter;
        use std::task;

        // calling the generator
        let result = match generator.as_slice() {
            "static" => task::try(proc() {
                let mut buffer = MemWriter::new();
                StaticGenerator::write(&mut buffer, &reg, ns);
                buffer
            }),

            "struct" => task::try(proc() {
                let mut buffer = MemWriter::new();
                StructGenerator::write(&mut buffer, &reg, ns);
                buffer
            }),

            generator => {
                ecx.span_err(span, format!("unknown generator type: {}", generator).as_slice());
                return DummyResult::any(span);
            },
        };

        // processing the result
        match result {
            Ok(buffer) => buffer.unwrap(),
            Err(err) => {
                use std::any::{Any, AnyRefExt};
                let err: &Any = &*err;

                match err {
                    err if err.is::<String>() => {
                        ecx.span_err(span, "error while generating the bindings");
                        ecx.span_err(span, err.downcast_ref::<String>().unwrap().as_slice());
                    },
                    err if err.is::<&'static str>() => {
                        ecx.span_err(span, "error while generating the bindings");
                        ecx.span_err(span, err.downcast_ref::<&'static str>().unwrap().as_slice());
                    },
                    _ => {
                        ecx.span_err(span, "unknown error while generating the bindings");
                    }
                }

                return DummyResult::any(span);
            }
        }
    };

    // creating a new Rust parser from these bindings
    let content = match String::from_utf8(buffer) {
        Ok(s) => s,
        Err(err) => {
            ecx.span_err(span, format!("{}", err).as_slice());
            return DummyResult::any(span)
        }
    };
    let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(),
        Path::new(ecx.codemap().span_to_filename(span)).display().to_string(), content);

    // getting all the items defined by the bindings
    let mut items = Vec::new();
    loop {
        match parser.parse_item_with_outer_attributes() {
            None => break,
            Some(i) => items.push(i)
        }
    }
    if !parser.eat(&token::EOF) {
        ecx.span_err(span, "the rust parser failed to compile all the generated bindings (meaning there is a bug in this library!)");
        return DummyResult::any(span)
    }
    box MacroResult { content: items } as Box<MacResult>
}

fn parse_macro_arguments(ecx: &mut ExtCtxt, span: Span, tts: &[syntax::ast::TokenTree])
                        -> Option<(String, String, String, String, Vec<String>)>
{
    // getting parameters list
    let values = match get_exprs_from_tts(ecx, span, tts) {
        Some(v) => v,
        None => return None
    };

    if values.len() != 4 && values.len() != 5 {
        ecx.span_err(span, format!("expected 4 or 5 arguments but got {}", values.len())
            .as_slice());
        return None;
    }

    // computing the extensions (last parameter)
    let extensions: Vec<String> = match values.as_slice().get(4) {
        None => Vec::new(),
        Some(vector) => {
            use syntax::ast::ExprVec;

            match vector.node {
                // only [ ... ] is accepted
                ExprVec(ref list) => {
                    // turning each element into a string
                    let mut result = Vec::new();
                    for element in list.iter() {
                        match expr_to_string(ecx, element.clone(), "expected string literal") {
                            Some((s, _)) => result.push(s.get().to_string()),
                            None => return None
                        }
                    }
                    result
                },
                _ => {
                    ecx.span_err(span, format!("last argument must be a vector").as_slice());
                    return None;
                }
            }
        }
    };

    // computing other parameters
    match (
        expr_to_string(ecx, values[0].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[1].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[2].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() }),
        expr_to_string(ecx, values[3].clone(), "expected string literal")
            .map(|e| match e { (s, _) => s.get().to_string() })
    ) {
        (Some(a), Some(b), Some(c), Some(d)) => Some((a, b, c, d, extensions)),
        _ => None
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Dzmitry "kvark" Malyshau <kvarkus@gmail.com>
//
// 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
//
//     http://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.

//! Routines for initialization of STM32F1.
//!
//! This module includes code for setting up the clock, flash, access time and
//! performing initial peripheral configuration.

//use hal::mem_init::init_data;
use core::default;
use core::intrinsics::abort;

use self::SystemClockSource::*;
use self::ClockAhbPrescaler::*;
use self::ClockApbPrescaler::*;
use self::McoSource::*;

#[path="../../util/wait_for.rs"]
#[macro_use] mod wait_for;

/// Phase-locked loop clock source.
#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllClockSource {
  /// Takes base clock from HSI/2.
  PllSourceHSIDiv2,
  /// Takes base clock from HSE.
  PllSourceHSE(u32),
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllMult {
  PllMul2,
  PllMul3,
  PllMul4,
  PllMul5,
  PllMul6,
  PllMul7,
  PllMul8,
  PllMul9,
  PllMul10,
  PllMul11,
  PllMul12,
  PllMul13,
  PllMul14,
  PllMul15,
  PllMul16,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllHsePrediv {
    PllHsePrediv1,
    PllHsePrediv2,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllUsbDiv {
    PllUsbDiv1,
    PllUsbDiv1p5,
}

#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub struct PllConf {
    pub source: PllClockSource,
    pub mult: PllMult,
    pub hse_prediv: PllHsePrediv,
    pub usb_psc: PllUsbDiv,
}

/// System clock source.
#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub enum SystemClockSource {
  /// High-speed internal oscillator, 8MHz.
  SystemClockHSI,
  /// High-speed external oscillator with configurable frequency.
  SystemClockHSE(u32),
  /// PLL.
  SystemClockPLL(PllConf),
}

impl default::Default for SystemClockSource {
  fn default() -> SystemClockSource {
    SystemClockHSI
  }
}

impl SystemClockSource {
  /// Returns the system clock frequency.
  pub fn frequency(&self) -> u32 {
    match *self {
        SystemClockHSI => 8_000_000,
        SystemClockHSE(_) => unsafe { abort() }, //TODO(kvark)
        SystemClockPLL(_) => unsafe { abort() }, //TODO(kvark)
    }
  }
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum McoSource {
  McoClockNone,
  McoClockSys,
  McoClockHSI,
  McoClockHSE,
  McoClockPLL,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ClockAhbPrescaler {
    AhbDivNone,
    AhbDiv2,
    AhbDiv4,
    AhbDiv8,
    AhbDiv16,
    AhbDiv64,
    AhbDiv128,
    AhbDiv256,
    AhbDiv512,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ClockApbPrescaler {
    ApbDivNone,
    ApbDiv2,
    ApbDiv4,
    ApbDiv8,
    ApbDiv16,
}

/// System clock configuration.
#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub struct ClockConfig {
  pub source : SystemClockSource,
  pub ahb_prescaler : ClockAhbPrescaler,
  pub apb1_prescaler : ClockApbPrescaler,
  pub apb2_prescaler : ClockApbPrescaler,
  pub mco : McoSource,
}

impl default::Default for ClockConfig {
  fn default() -> ClockConfig {
    ClockConfig {
      source: default::Default::default(),
      ahb_prescaler : AhbDivNone,
      apb1_prescaler : ApbDivNone,
      apb2_prescaler : ApbDivNone,
      mco: McoClockNone,
    }
  }
}

impl ClockConfig {
  /// Return the default clock configuration that hardware go to after reset.
  pub fn new_default() -> ClockConfig {
    default::Default::default()
  }

  /// Set this configuration on the hardware.
  pub fn setup(&self) {
    let r = &reg::RCC;

    let source_type = match self.source {
      SystemClockHSI => {
        r.cr.set_hsi_on(true);
        wait_for!(r.cr.hsi_ready());
        0b00
      },
      SystemClockHSE(_) => {
        r.cr.set_hse_on(true);
        wait_for!(r.cr.hse_ready());
        //TODO(kvark): HSE config
        0b01
      },
      SystemClockPLL(_pll_conf) => {
        r.cr.set_pll_on(true);
        wait_for!(r.cr.pll_ready());
        //TODO(blazewicz): PLL config
        0b10
      }
    };

    r.cfgr.set_system_clock(source_type);
    wait_for!(r.cfgr.system_clock_status() == source_type);

    let ahb_select = match self.ahb_prescaler {
        AhbDivNone => 0b0000u32,
        AhbDiv2    => 0b1000u32,
        AhbDiv4    => 0b1001u32,
        AhbDiv8    => 0b1010u32,
        AhbDiv16   => 0b1011u32,
        AhbDiv64   => 0b1100u32,
        AhbDiv128  => 0b1101u32,
        AhbDiv256  => 0b1110u32,
        AhbDiv512  => 0b1111u32,
    };
    r.cfgr.set_ahb_prescaler(ahb_select);

    let apb1_select = match self.apb1_prescaler {
        ApbDivNone => 0b000u32,
        ApbDiv2    => 0b100u32,
        ApbDiv4    => 0b101u32,
        ApbDiv8    => 0b110u32,
        ApbDiv16   => 0b111u32,
    };
    r.cfgr.set_apb1_prescaler(apb1_select);

    let apb2_select = match self.apb2_prescaler {
        ApbDivNone => 0b000u32,
        ApbDiv2    => 0b100u32,
        ApbDiv4    => 0b101u32,
        ApbDiv8    => 0b110u32,
        ApbDiv16   => 0b111u32,
    };
    r.cfgr.set_apb2_prescaler(apb2_select);

    let mco_select = match self.mco {
        McoClockNone => 0b000u32,
        McoClockSys  => 0b100u32,
        McoClockHSI  => 0b101u32,
        McoClockHSE  => 0b110u32,
        McoClockPLL  => 0b111u32,
    };
    r.cfgr.set_mco(mco_select);
  }

  /// Returns AHB clock frequency
  pub fn get_ahb_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }

  /// Returns APB1 clock frequency
  pub fn get_apb1_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }

  /// Returns APB2 clock frequency
  pub fn get_apb2_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }
}

// TODO(farcaller): this mod is pub as it's being used in peripheral_clock.rs.
//                  This is not the best design solution and a good reason to
//                  split RCC into distinct registers.
#[allow(missing_docs)]
pub mod reg {
  use volatile_cell::VolatileCell;
  use core::ops::Drop;

  ioregs!(RCC = {
    0x00 => reg32 cr {          // clock control
      0 => hsi_on : rw,
      1 => hsi_ready : ro,
      7..3 => hsi_trim : rw,
      15..8 => hsi_cal : rw,
      16 => hse_on : rw,
      17 => hse_ready : ro,
      18 => hse_bypass : rw,
      24 => pll_on : rw,
      25 => pll_ready : ro,
    },
    0x04 => reg32 cfgr {        // clock configuration
      1..0   => system_clock : rw,
      3..2   => system_clock_status: ro,
      7..4   => ahb_prescaler : rw,
      10..8  => apb1_prescaler : rw,
      13..11 => apb2_prescaler : rw,
      15..14 => adc_prescaler : rw,
      16     => pll_clock_source : rw,
      17     => pll_hse_divider : rw,
      21..18 => pll_mul_factor : rw,
      22     => usb_prescaler : rw,
      26..24 => mco : rw,
    },
    0x08 => reg32 cir {         // clock interrupt
      31..0 => clock_interrupt : rw,
    },
    0x0C => reg32 apb2rstr {    // APB2 peripheral reset
      31..0 => reset : rw,
    },
    0x10 => reg32 apb1rstr {    // APB1 peripheral reset
      31..0 => reset : rw,

    },
    0x14 => reg32 ahbenr {      // AHB peripheral clock enable
      31..0 => enable : rw,
    },
    0x18 => reg32 apb2enr {     // APB2 peripheral clock enable
      31..0 => enable : rw,
    },
    0x1C => reg32 apb1enr {     // ABB1 peripheral clock enable
      31..0 => enable : rw,
    },
    0x20 => reg32 bdcr {
      0    => lse_on : rw,
      1    => lse_ready : ro,
      2    => lse_bypass : rw,
      9..8 => rtc_source : rw,
      15   => rtc_on : rw,
      16   => backup_reset : rw,
    }
    0x24 => reg32 csr {         // control/status
      0 => lsi_on : rw, // internal low speed oscillator
      1 => lsi_ready : ro,
      24 => remove_reset : rw,
      26 => pin_reset : rw,
      27 => pop_pdr_reset : rw,
      28 => software_reset : rw,
      29 => independent_watchdog_reset : rw,
      30 => window_watchdog_reset : rw,
      31 => low_power_reset : rw,
    },
  });

  ioregs!(FLASH = {
    0x00 => reg32 acr {     // access control
      2..0 => latency : rw,
      3    => flash_half_cycle_on : rw,
      4    => prefetch_buf_on : rw,
      5    => prefetch_buf_status : ro,
    },
  });

  ioregs!(PWR = {
    0x0 => reg32 cr {   // power control
      31..0 => control : rw,
    },
    0x4 => reg32 csr {  // power control/status
      31..0 => status : rw,
    },
  });

  extern {
    #[link_name="stm32f1_iomem_RCC"] pub static RCC: RCC;
    #[link_name="stm32f1_iomem_FLASH"] pub static FLASH: FLASH;
    #[link_name="stm32f1_iomem_PWR"] pub static PWR: PWR;
  }
}
<commit_msg>stm32f1: working clock configuration<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Dzmitry "kvark" Malyshau <kvarkus@gmail.com>
//
// 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
//
//     http://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.

//! Routines for initialization of STM32F1.
//!
//! This module includes code for setting up the clock, flash, access time and
//! performing initial peripheral configuration.

//use hal::mem_init::init_data;
use core::default;

use self::SystemClockSource::*;
use self::PllClockSource::*;
use self::PllHsePrediv::*;
use self::PllUsbDiv::*;
use self::PllMult::*;
use self::ClockAhbPrescaler::*;
use self::ClockApbPrescaler::*;
use self::FlashLatency::*;
use self::McoSource::*;

#[path="../../util/wait_for.rs"]
#[macro_use] mod wait_for;

/// Phase-locked loop clock source.
#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllClockSource {
  /// Takes base clock from HSI/2.
  PllSourceHSIDiv2,
  /// Takes base clock from HSE.
  PllSourceHSE(u32),
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllMult {
  /*  0 = 0b0000 */ PllMul2,
  /*  1 = 0b0001 */ PllMul3,
  /*  2 = 0b0010 */ PllMul4,
  /*  3 = 0b0011 */ PllMul5,
  /*  4 = 0b0100 */ PllMul6,
  /*  5 = 0b0101 */ PllMul7,
  /*  6 = 0b0110 */ PllMul8,
  /*  7 = 0b0111 */ PllMul9,
  /*  8 = 0b1000 */ PllMul10,
  /*  9 = 0b1001 */ PllMul11,
  /* 10 = 0b1010 */ PllMul12,
  /* 11 = 0b1011 */ PllMul13,
  /* 12 = 0b1100 */ PllMul14,
  /* 13 = 0b1101 */ PllMul15,
  /* 14 = 0b1110 */ PllMul16,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllHsePrediv {
    PllHsePrediv1,
    PllHsePrediv2,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum PllUsbDiv {
    PllUsbDiv1,
    PllUsbDiv1p5,
}

#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub struct PllConf {
    pub source: PllClockSource,
    pub mult: PllMult,
    pub hse_prediv: PllHsePrediv,
    pub usb_prescaler: PllUsbDiv,
}

/// System clock source.
#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub enum SystemClockSource {
  /// High-speed internal oscillator, 8MHz.
  SystemClockHSI,
  /// High-speed external oscillator with configurable frequency.
  SystemClockHSE(u32),
  /// PLL.
  SystemClockPLL(PllConf),
}

impl default::Default for SystemClockSource {
  fn default() -> SystemClockSource {
    SystemClockHSI
  }
}

impl SystemClockSource {
  /// Returns the system clock frequency.
  pub fn frequency(&self) -> u32 {
    match *self {
        SystemClockHSI => 8_000_000,
        SystemClockHSE(frequency) => frequency,
        SystemClockPLL(pll_conf) => {
            let pll_in = match pll_conf.source {
                PllSourceHSIDiv2 => 4_000_000,
                PllSourceHSE(frequency) => match pll_conf.hse_prediv {
                    PllHsePrediv1 => frequency,
                    PllHsePrediv2 => frequency >> 1,
                },
            };
            let mul = pll_conf.mult as u32 + 2;
            pll_in * mul
        }
    }
  }
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum McoSource {
  McoClockNone,
  McoClockSys,
  McoClockHSI,
  McoClockHSE,
  McoClockPLL,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ClockAhbPrescaler {
    AhbDivNone,
    AhbDiv2,
    AhbDiv4,
    AhbDiv8,
    AhbDiv16,
    AhbDiv64,
    AhbDiv128,
    AhbDiv256,
    AhbDiv512,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ClockApbPrescaler {
    ApbDivNone,
    ApbDiv2,
    ApbDiv4,
    ApbDiv8,
    ApbDiv16,
}

#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum FlashLatency {
    FlashLatency0,
    FlashLatency1,
    FlashLatency2,
}

/// System clock configuration.
#[allow(missing_docs)]
#[derive(Clone, Copy)]
pub struct ClockConfig {
  pub source : SystemClockSource,
  pub ahb_prescaler : ClockAhbPrescaler,
  pub apb1_prescaler : ClockApbPrescaler,
  pub apb2_prescaler : ClockApbPrescaler,
  pub flash_latency : FlashLatency,
  pub mco : McoSource,
}

impl default::Default for ClockConfig {
  fn default() -> ClockConfig {
    ClockConfig {
      source: default::Default::default(),
      ahb_prescaler : AhbDivNone,
      apb1_prescaler : ApbDivNone,
      apb2_prescaler : ApbDivNone,
      flash_latency : FlashLatency0,
      mco: McoClockNone,
    }
  }
}

impl ClockConfig {
  /// Return the default clock configuration that hardware go to after reset.
  pub fn new_default() -> ClockConfig {
    default::Default::default()
  }

  /// Set this configuration on the hardware.
  pub fn setup(&self) {
    let rcc = &reg::RCC;
    let flash = &reg::FLASH;

    let source_type = match self.source {
      SystemClockHSI => {
        rcc.cr.set_hsi_on(true);
        wait_for!(rcc.cr.hsi_ready());
        0b00  // system_clock = HSI
      },
      SystemClockHSE(_) => {
        rcc.cr.set_hse_on(true);
        wait_for!(rcc.cr.hse_ready());
        0b01  // system_clock = HSE
      },
      SystemClockPLL(pll_conf) => {
        match rcc.cfgr.system_clock() {
            // if PLL is current clock source, temporarly switch it to HSI
            // because otherwise we cannot modify it
            // TODO(blazewicz): check if HSI is on
            0b10 => {
                rcc.cfgr.set_system_clock(0b00);
            },
            _ => ()
        };

        // disable PLL
        rcc.cr.set_pll_on(false);
        wait_for!(!rcc.cr.pll_ready());

        // set pll clock source
        let pll_clock_source = match pll_conf.source {
            PllSourceHSIDiv2 => {
                rcc.cr.set_hsi_on(true);
                wait_for!(rcc.cr.hsi_ready());
                false // pll_clock_source = HSI divided by 2
            },
            PllSourceHSE(_)  => {
                rcc.cr.set_hse_on(true);

                // set HSE divider for PLL entry
                let pll_hse_divider = match pll_conf.hse_prediv {
                    PllHsePrediv1 => false,
                    PllHsePrediv2 => true,
                };
                rcc.cfgr.set_pll_hse_divider(pll_hse_divider);

                wait_for!(rcc.cr.hse_ready());
                true // pll_clock_source = HSE
            },
        };
        rcc.cfgr.set_pll_clock_source(pll_clock_source);

        // set pll multiplication factor
        rcc.cfgr.set_pll_mul_factor(pll_conf.mult as u32);

        // set USB prescaler (max 48 MHz)
        let usb_prescaler = match pll_conf.usb_prescaler {
            PllUsbDiv1p5 => false,
            PllUsbDiv1   => true,
        };
        rcc.cfgr.set_usb_prescaler(usb_prescaler);

        // enable PLL
        rcc.cr.set_pll_on(true);
        wait_for!(rcc.cr.pll_ready());

        0b10 // system_clock = PLL
       }
    };

    /* TODO(blazewicz): configuring flash latency is straightforward
     * and could be done automatically:
     *       0 < SYSCLK <= 24 MHz => 0
     *  24 MHz < SYSCLK <= 48 MHz => 1
     *  48 MHz < SYSCLK <= 72 MHz => 2
     */
    flash.acr.set_latency(self.flash_latency as u32);

    rcc.cfgr.set_system_clock(source_type);
    wait_for!(rcc.cfgr.system_clock_status() == source_type);

    let ahb_select = match self.ahb_prescaler {
        AhbDivNone => 0b0000u32,
        AhbDiv2    => 0b1000u32,
        AhbDiv4    => 0b1001u32,
        AhbDiv8    => 0b1010u32,
        AhbDiv16   => 0b1011u32,
        //NOTE(blazewicz): there is no /32
        AhbDiv64   => 0b1100u32,
        AhbDiv128  => 0b1101u32,
        AhbDiv256  => 0b1110u32,
        AhbDiv512  => 0b1111u32,
    };
    rcc.cfgr.set_ahb_prescaler(ahb_select);

    // (max 36 MHz)
    let apb1_select = match self.apb1_prescaler {
        ApbDivNone => 0b000u32,
        ApbDiv2    => 0b100u32,
        ApbDiv4    => 0b101u32,
        ApbDiv8    => 0b110u32,
        ApbDiv16   => 0b111u32,
    };
    rcc.cfgr.set_apb1_prescaler(apb1_select);

    let apb2_select = match self.apb2_prescaler {
        ApbDivNone => 0b000u32,
        ApbDiv2    => 0b100u32,
        ApbDiv4    => 0b101u32,
        ApbDiv8    => 0b110u32,
        ApbDiv16   => 0b111u32,
    };
    rcc.cfgr.set_apb2_prescaler(apb2_select);

    let mco_select = match self.mco {
        McoClockNone => 0b000u32,
        McoClockSys  => 0b100u32,
        McoClockHSI  => 0b101u32,
        McoClockHSE  => 0b110u32,
        McoClockPLL  => 0b111u32,
    };
    rcc.cfgr.set_mco(mco_select);
  }

  /// Returns AHB clock frequency
  pub fn get_ahb_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }

  /// Returns APB1 clock frequency
  pub fn get_apb1_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }

  /// Returns APB2 clock frequency
  pub fn get_apb2_frequency(&self) -> u32 {
    0 //TODO(blazewicz)
  }
}

// TODO(farcaller): this mod is pub as it's being used in peripheral_clock.rs.
//                  This is not the best design solution and a good reason to
//                  split RCC into distinct registers.
#[allow(missing_docs)]
pub mod reg {
  use volatile_cell::VolatileCell;
  use core::ops::Drop;

  ioregs!(RCC = {
    0x00 => reg32 cr {          // clock control
      0 => hsi_on : rw,
      1 => hsi_ready : ro,
      7..3 => hsi_trim : rw,
      15..8 => hsi_cal : rw,
      16 => hse_on : rw,
      17 => hse_ready : ro,
      18 => hse_bypass : rw,
      19 => css_on : rw,
      24 => pll_on : rw,
      25 => pll_ready : ro,
    },
    0x04 => reg32 cfgr {        // clock configuration
      1..0   => system_clock : rw,
      3..2   => system_clock_status: ro,
      7..4   => ahb_prescaler : rw,
      10..8  => apb1_prescaler : rw,
      13..11 => apb2_prescaler : rw,
      15..14 => adc_prescaler : rw,
      16     => pll_clock_source : rw,
      17     => pll_hse_divider : rw,
      21..18 => pll_mul_factor : rw,
      22     => usb_prescaler : rw,
      26..24 => mco : rw,
    },
    0x08 => reg32 cir {         // clock interrupt
      31..0 => clock_interrupt : rw,
    },
    0x0C => reg32 apb2rstr {    // APB2 peripheral reset
      31..0 => reset : rw,
    },
    0x10 => reg32 apb1rstr {    // APB1 peripheral reset
      31..0 => reset : rw,
    },
    0x14 => reg32 ahbenr {      // AHB peripheral clock enable
      31..0 => enable : rw,
    },
    0x18 => reg32 apb2enr {     // APB2 peripheral clock enable
      31..0 => enable : rw,
    },
    0x1C => reg32 apb1enr {     // ABB1 peripheral clock enable
      31..0 => enable : rw,
    },
    0x20 => reg32 bdcr {
      0    => lse_on : rw,
      1    => lse_ready : ro,
      2    => lse_bypass : rw,
      9..8 => rtc_source : rw,
      15   => rtc_on : rw,
      16   => backup_reset : rw,
    }
    0x24 => reg32 csr {         // control/status
      0 => lsi_on : rw, // internal low speed oscillator
      1 => lsi_ready : ro,
      24 => remove_reset : rw,
      26 => pin_reset : rw,
      27 => pop_pdr_reset : rw,
      28 => software_reset : rw,
      29 => independent_watchdog_reset : rw,
      30 => window_watchdog_reset : rw,
      31 => low_power_reset : rw,
    },
  });

  ioregs!(FLASH = {
    0x00 => reg32 acr {     // access control
      2..0 => latency : rw,
      3    => flash_half_cycle_on : rw,
      4    => prefetch_buf_on : rw,
      5    => prefetch_buf_status : ro,
    },
  });

  ioregs!(PWR = {
    0x0 => reg32 cr {   // power control
      31..0 => control : rw,
    },
    0x4 => reg32 csr {  // power control/status
      31..0 => status : rw,
    },
  });

  extern {
    #[link_name="stm32f1_iomem_RCC"] pub static RCC: RCC;
    #[link_name="stm32f1_iomem_FLASH"] pub static FLASH: FLASH;
    #[link_name="stm32f1_iomem_PWR"] pub static PWR: PWR;
  }
}
<|endoftext|>


<commit_before>pub trait HammingDistancable<RHS = Self> {
    /// The output type of the hamming distance
    type Output;
    fn hamming_distance(self, other: RHS) -> Self::Output;
}

impl<'a, 'b, T> HammingDistancable<&'b Vec<T>> for &'a Vec<T>
    where T : Eq {
    type Output = Result<u32, &'static str>;
    fn hamming_distance(self, other: &'b Vec<T>) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Vectors do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl<'a, 'b, T> HammingDistancable<&'b [T]> for &'a [T]
    where T : Eq {
    type Output = Result<u32, &'static str>;
    fn hamming_distance(self, other: &'b [T]) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Slices do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b String> for &'a String {
    type Output = Result<u32, &'static str>;
     fn hamming_distance(self, other: &'b String) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b str> for &'a str {
    type Output = Result<u32, &'static str>;
     fn hamming_distance(self, other: &'b str) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

#[cfg(test)]
mod tests {
    use hamming_distance::HammingDistancable;

    #[test]
    fn string_hamming_distance() {
        let string1 = "Cat";
        let string2 = "Hat";

        assert!(string1.hamming_distance(string2).unwrap() == 1);
    }
}<commit_msg>Little more doc strings<commit_after>/// A trait for calculating hamming distance
pub trait HammingDistancable<RHS = Self> {
    /// The output type of the hamming distance
    type Output;
    fn hamming_distance(self, other: RHS) -> Self::Output;
}

impl<'a, 'b, T> HammingDistancable<&'b Vec<T>> for &'a Vec<T>
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between vectors
    fn hamming_distance(self, other: &'b Vec<T>) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Vectors do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl<'a, 'b, T> HammingDistancable<&'b [T]> for &'a [T]
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between slices
    fn hamming_distance(self, other: &'b [T]) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Slices do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b String> for &'a String {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between strings
     fn hamming_distance(self, other: &'b String) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b str> for &'a str {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between borrowed strings
     fn hamming_distance(self, other: &'b str) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

#[cfg(test)]
mod tests {
    use hamming_distance::HammingDistancable;

    #[test]
    fn string_hamming_distance() {
        let string1 = "Cat";
        let string2 = "Hat";

        assert!(string1.hamming_distance(string2).unwrap() == 1);
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fmt;
use std::path::Path;
use std::process::{Command, Stdio, Output};

use jobserver::Client;
use shell_escape::escape;

use util::{CargoResult, CargoResultExt, CargoError, process_error, read2};
use util::errors::CargoErrorKind;

#[derive(Clone, Debug)]
pub struct ProcessBuilder {
    program: OsString,
    args: Vec<OsString>,
    env: HashMap<String, Option<OsString>>,
    cwd: Option<OsString>,
    jobserver: Option<Client>,
}

impl fmt::Display for ProcessBuilder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "`{}", self.program.to_string_lossy())?;

        for arg in self.args.iter() {
            write!(f, " {}", escape(arg.to_string_lossy()))?;
        }

        write!(f, "`")
    }
}

impl ProcessBuilder {
    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
        self.args.push(arg.as_ref().to_os_string());
        self
    }

    pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args.extend(arguments.iter().map(|t| {
            t.as_ref().to_os_string()
        }));
        self
    }

    pub fn args_replace<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args = arguments.iter().map(|t| {
            t.as_ref().to_os_string()
        }).collect();
        self
    }

    pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {
        self.cwd = Some(path.as_ref().to_os_string());
        self
    }

    pub fn env<T: AsRef<OsStr>>(&mut self, key: &str,
                                val: T) -> &mut ProcessBuilder {
        self.env.insert(key.to_string(), Some(val.as_ref().to_os_string()));
        self
    }

    pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {
        self.env.insert(key.to_string(), None);
        self
    }

    pub fn get_program(&self) -> &OsString {
        &self.program
    }

    pub fn get_args(&self) -> &[OsString] {
        &self.args
    }

    pub fn get_cwd(&self) -> Option<&Path> {
        self.cwd.as_ref().map(Path::new)
    }

    pub fn get_env(&self, var: &str) -> Option<OsString> {
        self.env.get(var).cloned().or_else(|| Some(env::var_os(var)))
            .and_then(|s| s)
    }

    pub fn get_envs(&self) -> &HashMap<String, Option<OsString>> { &self.env }

    pub fn inherit_jobserver(&mut self, jobserver: &Client) -> &mut Self {
        self.jobserver = Some(jobserver.clone());
        self
    }

    pub fn exec(&self) -> CargoResult<()> {
        let mut command = self.build_command();
        let exit = command.status().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(&format!("could not execute process `{}`",
                                   self.debug_string()), None, None))
        })?;

        if exit.success() {
            Ok(())
        } else {
            Err(CargoErrorKind::ProcessErrorKind(process_error(
                &format!("process didn't exit successfully: `{}`", self.debug_string()),
                Some(&exit), None)).into())
        }
    }

    #[cfg(unix)]
    pub fn exec_replace(&self) -> CargoResult<()> {
        use std::os::unix::process::CommandExt;

        let mut command = self.build_command();
        let error = command.exec();
        Err(CargoError::with_chain(error,
            CargoErrorKind::ProcessErrorKind(process_error(
                &format!("could not execute process `{}`", self.debug_string()), None, None))))
    }

    #[cfg(windows)]
    pub fn exec_replace(&self) -> CargoResult<()> {
        self.exec()
    }

    pub fn exec_with_output(&self) -> CargoResult<Output> {
        let mut command = self.build_command();

        let output = command.output().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(
                    &format!("could not execute process `{}`", self.debug_string()),
                          None, None))
        })?;

        if output.status.success() {
            Ok(output)
        } else {
            Err(CargoErrorKind::ProcessErrorKind(process_error(
                &format!("process didn't exit successfully: `{}`", self.debug_string()),
                Some(&output.status), Some(&output))).into())
        }
    }

    pub fn exec_with_streaming(&self,
                               on_stdout_line: &mut FnMut(&str) -> CargoResult<()>,
                               on_stderr_line: &mut FnMut(&str) -> CargoResult<()>,
                               print_output: bool)
                               -> CargoResult<Output> {
        let mut stdout = Vec::new();
        let mut stderr = Vec::new();

        let mut cmd = self.build_command();
        cmd.stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .stdin(Stdio::null());

        let mut callback_error = None;
        let status = (|| {
            let mut child = cmd.spawn()?;
            let out = child.stdout.take().unwrap();
            let err = child.stderr.take().unwrap();
            read2(out, err, &mut |is_out, data, eof| {
                let idx = if eof {
                    data.len()
                } else {
                    match data.iter().rposition(|b| *b == b'\n') {
                        Some(i) => i + 1,
                        None => return,
                    }
                };
                let data = data.drain(..idx);
                let dst = if is_out {&mut stdout} else {&mut stderr};
                let start = dst.len();
                dst.extend(data);
                for line in String::from_utf8_lossy(&dst[start..]).lines() {
                    if callback_error.is_some() { break }
                    let callback_result = if is_out {
                        on_stdout_line(line)
                    } else {
                        on_stderr_line(line)
                    };
                    if let Err(e) = callback_result {
                        callback_error = Some(e);
                    }
                }
            })?;
            child.wait()
        })().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(&format!("could not execute process `{}`",
                    self.debug_string()),
                None, None))
        })?;
        let output = Output {
            stdout: stdout,
            stderr: stderr,
            status: status,
        };

        {
            let to_print = if print_output {
                Some(&output)
            } else {
                None
            };
            if !output.status.success() {
                return Err(CargoErrorKind::ProcessErrorKind(process_error(
                            &format!("process didn't exit successfully: `{}`", self.debug_string()),
                            Some(&output.status), to_print)).into())
            } else if let Some(e) = callback_error {
                return Err(CargoError::with_chain(e,
                        CargoErrorKind::ProcessErrorKind(process_error(
                                &format!("failed to parse process output: `{}`", self.debug_string()),
                                Some(&output.status), to_print))))
            }
        }

        Ok(output)
    }

    pub fn build_command(&self) -> Command {
        let mut command = Command::new(&self.program);
        if let Some(cwd) = self.get_cwd() {
            command.current_dir(cwd);
        }
        for arg in self.args.iter() {
            command.arg(arg);
        }
        for (k, v) in self.env.iter() {
            match *v {
                Some(ref v) => { command.env(k, v); }
                None => { command.env_remove(k); }
            }
        }
        if let Some(ref c) = self.jobserver {
            c.configure(&mut command);
        }
        command
    }

    fn debug_string(&self) -> String {
        let mut program = format!("{}", self.program.to_string_lossy());
        for arg in self.args.iter() {
            program.push(' ');
            program.push_str(&format!("{}", arg.to_string_lossy()));
        }
        program
    }
}

pub fn process<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
    ProcessBuilder {
        program: cmd.as_ref().to_os_string(),
        args: Vec::new(),
        cwd: None,
        env: HashMap::new(),
        jobserver: None,
    }
}
<commit_msg>Auto merge of #4442 - Xanewok:process-builder-program, r=alexcrichton<commit_after>use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fmt;
use std::path::Path;
use std::process::{Command, Stdio, Output};

use jobserver::Client;
use shell_escape::escape;

use util::{CargoResult, CargoResultExt, CargoError, process_error, read2};
use util::errors::CargoErrorKind;

#[derive(Clone, Debug)]
pub struct ProcessBuilder {
    program: OsString,
    args: Vec<OsString>,
    env: HashMap<String, Option<OsString>>,
    cwd: Option<OsString>,
    jobserver: Option<Client>,
}

impl fmt::Display for ProcessBuilder {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "`{}", self.program.to_string_lossy())?;

        for arg in self.args.iter() {
            write!(f, " {}", escape(arg.to_string_lossy()))?;
        }

        write!(f, "`")
    }
}

impl ProcessBuilder {
    pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
        self.program = program.as_ref().to_os_string();
        self
    }

    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
        self.args.push(arg.as_ref().to_os_string());
        self
    }

    pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args.extend(arguments.iter().map(|t| {
            t.as_ref().to_os_string()
        }));
        self
    }

    pub fn args_replace<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args = arguments.iter().map(|t| {
            t.as_ref().to_os_string()
        }).collect();
        self
    }

    pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {
        self.cwd = Some(path.as_ref().to_os_string());
        self
    }

    pub fn env<T: AsRef<OsStr>>(&mut self, key: &str,
                                val: T) -> &mut ProcessBuilder {
        self.env.insert(key.to_string(), Some(val.as_ref().to_os_string()));
        self
    }

    pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {
        self.env.insert(key.to_string(), None);
        self
    }

    pub fn get_program(&self) -> &OsString {
        &self.program
    }

    pub fn get_args(&self) -> &[OsString] {
        &self.args
    }

    pub fn get_cwd(&self) -> Option<&Path> {
        self.cwd.as_ref().map(Path::new)
    }

    pub fn get_env(&self, var: &str) -> Option<OsString> {
        self.env.get(var).cloned().or_else(|| Some(env::var_os(var)))
            .and_then(|s| s)
    }

    pub fn get_envs(&self) -> &HashMap<String, Option<OsString>> { &self.env }

    pub fn inherit_jobserver(&mut self, jobserver: &Client) -> &mut Self {
        self.jobserver = Some(jobserver.clone());
        self
    }

    pub fn exec(&self) -> CargoResult<()> {
        let mut command = self.build_command();
        let exit = command.status().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(&format!("could not execute process `{}`",
                                   self.debug_string()), None, None))
        })?;

        if exit.success() {
            Ok(())
        } else {
            Err(CargoErrorKind::ProcessErrorKind(process_error(
                &format!("process didn't exit successfully: `{}`", self.debug_string()),
                Some(&exit), None)).into())
        }
    }

    #[cfg(unix)]
    pub fn exec_replace(&self) -> CargoResult<()> {
        use std::os::unix::process::CommandExt;

        let mut command = self.build_command();
        let error = command.exec();
        Err(CargoError::with_chain(error,
            CargoErrorKind::ProcessErrorKind(process_error(
                &format!("could not execute process `{}`", self.debug_string()), None, None))))
    }

    #[cfg(windows)]
    pub fn exec_replace(&self) -> CargoResult<()> {
        self.exec()
    }

    pub fn exec_with_output(&self) -> CargoResult<Output> {
        let mut command = self.build_command();

        let output = command.output().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(
                    &format!("could not execute process `{}`", self.debug_string()),
                          None, None))
        })?;

        if output.status.success() {
            Ok(output)
        } else {
            Err(CargoErrorKind::ProcessErrorKind(process_error(
                &format!("process didn't exit successfully: `{}`", self.debug_string()),
                Some(&output.status), Some(&output))).into())
        }
    }

    pub fn exec_with_streaming(&self,
                               on_stdout_line: &mut FnMut(&str) -> CargoResult<()>,
                               on_stderr_line: &mut FnMut(&str) -> CargoResult<()>,
                               print_output: bool)
                               -> CargoResult<Output> {
        let mut stdout = Vec::new();
        let mut stderr = Vec::new();

        let mut cmd = self.build_command();
        cmd.stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .stdin(Stdio::null());

        let mut callback_error = None;
        let status = (|| {
            let mut child = cmd.spawn()?;
            let out = child.stdout.take().unwrap();
            let err = child.stderr.take().unwrap();
            read2(out, err, &mut |is_out, data, eof| {
                let idx = if eof {
                    data.len()
                } else {
                    match data.iter().rposition(|b| *b == b'\n') {
                        Some(i) => i + 1,
                        None => return,
                    }
                };
                let data = data.drain(..idx);
                let dst = if is_out {&mut stdout} else {&mut stderr};
                let start = dst.len();
                dst.extend(data);
                for line in String::from_utf8_lossy(&dst[start..]).lines() {
                    if callback_error.is_some() { break }
                    let callback_result = if is_out {
                        on_stdout_line(line)
                    } else {
                        on_stderr_line(line)
                    };
                    if let Err(e) = callback_result {
                        callback_error = Some(e);
                    }
                }
            })?;
            child.wait()
        })().chain_err(|| {
            CargoErrorKind::ProcessErrorKind(
                process_error(&format!("could not execute process `{}`",
                    self.debug_string()),
                None, None))
        })?;
        let output = Output {
            stdout: stdout,
            stderr: stderr,
            status: status,
        };

        {
            let to_print = if print_output {
                Some(&output)
            } else {
                None
            };
            if !output.status.success() {
                return Err(CargoErrorKind::ProcessErrorKind(process_error(
                            &format!("process didn't exit successfully: `{}`", self.debug_string()),
                            Some(&output.status), to_print)).into())
            } else if let Some(e) = callback_error {
                return Err(CargoError::with_chain(e,
                        CargoErrorKind::ProcessErrorKind(process_error(
                                &format!("failed to parse process output: `{}`", self.debug_string()),
                                Some(&output.status), to_print))))
            }
        }

        Ok(output)
    }

    pub fn build_command(&self) -> Command {
        let mut command = Command::new(&self.program);
        if let Some(cwd) = self.get_cwd() {
            command.current_dir(cwd);
        }
        for arg in self.args.iter() {
            command.arg(arg);
        }
        for (k, v) in self.env.iter() {
            match *v {
                Some(ref v) => { command.env(k, v); }
                None => { command.env_remove(k); }
            }
        }
        if let Some(ref c) = self.jobserver {
            c.configure(&mut command);
        }
        command
    }

    fn debug_string(&self) -> String {
        let mut program = format!("{}", self.program.to_string_lossy());
        for arg in self.args.iter() {
            program.push(' ');
            program.push_str(&format!("{}", arg.to_string_lossy()));
        }
        program
    }
}

pub fn process<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
    ProcessBuilder {
        program: cmd.as_ref().to_os_string(),
        args: Vec::new(),
        cwd: None,
        env: HashMap::new(),
        jobserver: None,
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-pretty-expanded FIXME #15189
// ignore-android FIXME #17520
// compile-flags:-g

use std::env;
use std::process::{Command, Stdio};
use std::str;

#[inline(never)]
fn foo() {
    let _v = vec![1, 2, 3];
    if env::var_os("IS_TEST").is_some() {
        panic!()
    }
}

#[inline(never)]
fn double() {
    struct Double;

    impl Drop for Double {
        fn drop(&mut self) { panic!("twice") }
    }

    let _d = Double;

    panic!("once");
}

fn template(me: &str) -> Command {
    let mut m = Command::new(me);
    m.env("IS_TEST", "1")
     .stdout(Stdio::piped())
     .stderr(Stdio::piped());
    return m;
}

fn expected(fn_name: &str) -> String {
    // FIXME(#32481)
    //
    // On windows, we read the function name from debuginfo using some
    // system APIs. For whatever reason, these APIs seem to use the
    // "name" field, which is only the "relative" name, not the full
    // name with namespace info, so we just see `foo` and not
    // `backtrace::foo` as we see on linux (which uses the linkage
    // name).
    if cfg!(windows) && cfg!(target_env = "msvc") {
        format!(" - {}", fn_name)
    } else {
        format!(" - backtrace::{}", fn_name)
    }
}

fn runtest(me: &str) {
    // Make sure that the stack trace is printed
    let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(s.contains("stack backtrace") && s.contains(&expected("foo")),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    // (Remove RUST_BACKTRACE from our own environment, in case developer
    // is running `make check` with it on.)
    let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(&expected("foo")),
            "bad output2: {}", s);

    // Make sure the stack trace is *not* printed
    // (RUST_BACKTRACE=0 acts as if it were unset from our own environment,
    // in case developer is running `make check` with it set.)
    let p = template(me).arg("fail").env("RUST_BACKTRACE","0").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(" - foo"),
            "bad output3: {}", s);

    // Make sure a stack trace is printed
    let p = template(me).arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    // loosened the following from double::h to double:: due to
    // spurious failures on mac, 32bit, optimized
    assert!(s.contains("stack backtrace") && s.contains(&expected("double")),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template(me).arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    let mut i = 0;
    for _ in 0..2 {
        i += s[i + 10..].find("stack backtrace").unwrap() + 10;
    }
    assert!(s[i + 10..].find("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    if cfg!(windows) && cfg!(target_env = "gnu") {
        return
    }

    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 && args[1] == "fail" {
        foo();
    } else if args.len() >= 2 && args[1] == "double-fail" {
        double();
    } else {
        runtest(&args[0]);
    }
}
<commit_msg>test: Fix a test on MSVC<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-pretty-expanded FIXME #15189
// ignore-android FIXME #17520
// compile-flags:-g

use std::env;
use std::process::{Command, Stdio};
use std::str;

#[inline(never)]
fn foo() {
    let _v = vec![1, 2, 3];
    if env::var_os("IS_TEST").is_some() {
        panic!()
    }
}

#[inline(never)]
fn double() {
    struct Double;

    impl Drop for Double {
        fn drop(&mut self) { panic!("twice") }
    }

    let _d = Double;

    panic!("once");
}

fn template(me: &str) -> Command {
    let mut m = Command::new(me);
    m.env("IS_TEST", "1")
     .stdout(Stdio::piped())
     .stderr(Stdio::piped());
    return m;
}

fn expected(fn_name: &str) -> String {
    format!(" - backtrace::{}", fn_name)
}

fn runtest(me: &str) {
    // Make sure that the stack trace is printed
    let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(s.contains("stack backtrace") && s.contains(&expected("foo")),
            "bad output: {}", s);

    // Make sure the stack trace is *not* printed
    // (Remove RUST_BACKTRACE from our own environment, in case developer
    // is running `make check` with it on.)
    let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(&expected("foo")),
            "bad output2: {}", s);

    // Make sure the stack trace is *not* printed
    // (RUST_BACKTRACE=0 acts as if it were unset from our own environment,
    // in case developer is running `make check` with it set.)
    let p = template(me).arg("fail").env("RUST_BACKTRACE","0").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    assert!(!s.contains("stack backtrace") && !s.contains(" - foo"),
            "bad output3: {}", s);

    // Make sure a stack trace is printed
    let p = template(me).arg("double-fail").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    // loosened the following from double::h to double:: due to
    // spurious failures on mac, 32bit, optimized
    assert!(s.contains("stack backtrace") && s.contains(&expected("double")),
            "bad output3: {}", s);

    // Make sure a stack trace isn't printed too many times
    let p = template(me).arg("double-fail")
                                .env("RUST_BACKTRACE", "1").spawn().unwrap();
    let out = p.wait_with_output().unwrap();
    assert!(!out.status.success());
    let s = str::from_utf8(&out.stderr).unwrap();
    let mut i = 0;
    for _ in 0..2 {
        i += s[i + 10..].find("stack backtrace").unwrap() + 10;
    }
    assert!(s[i + 10..].find("stack backtrace").is_none(),
            "bad output4: {}", s);
}

fn main() {
    if cfg!(windows) && cfg!(target_env = "gnu") {
        return
    }

    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 && args[1] == "fail" {
        foo();
    } else if args.len() >= 2 && args[1] == "double-fail" {
        double();
    } else {
        runtest(&args[0]);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::get_with_proof::{
    RequestItem, ResponseItem, UpdateToLatestLedgerRequest, UpdateToLatestLedgerResponse,
};
use proptest::prelude::*;
use proto_conv::test_helper::assert_protobuf_encode_decode;

proptest! {
    #[test]
    fn test_update_to_latest_ledger_request(
        request in any::<UpdateToLatestLedgerRequest>()
    ) {
        assert_protobuf_encode_decode(&request);
    }

    #[test]
    fn test_request_item_conversion(item in any::<RequestItem>()) {
        assert_protobuf_encode_decode(&item);
    }
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(20))]

    #[test]
    fn test_response_item(item in any::<ResponseItem>()) {
        assert_protobuf_encode_decode(&item);
    }

    #[test]
    fn test_update_to_latest_ledger_response(
        response in any::<UpdateToLatestLedgerResponse>()
    ) {
        assert_protobuf_encode_decode(&response);
    }
}
<commit_msg>[types] add unit tests for converting RequestItem and ResponseItem<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    get_with_proof::{
        RequestItem, ResponseItem, UpdateToLatestLedgerRequest, UpdateToLatestLedgerResponse,
    },
    proto,
};
use proptest::prelude::*;
use proto_conv::{test_helper::assert_protobuf_encode_decode, FromProto};

proptest! {
    #[test]
    fn test_update_to_latest_ledger_request(
        request in any::<UpdateToLatestLedgerRequest>()
    ) {
        assert_protobuf_encode_decode(&request);
    }

    #[test]
    fn test_request_item_conversion(item in any::<RequestItem>()) {
        assert_protobuf_encode_decode(&item);
    }
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(20))]

    #[test]
    fn test_response_item(item in any::<ResponseItem>()) {
        assert_protobuf_encode_decode(&item);
    }

    #[test]
    fn test_update_to_latest_ledger_response(
        response in any::<UpdateToLatestLedgerResponse>()
    ) {
        assert_protobuf_encode_decode(&response);
    }
}

#[test]
fn request_item_is_none() {
    let proto = proto::get_with_proof::RequestItem::default();

    let maybe_request_item = RequestItem::from_proto(proto);
    assert!(maybe_request_item.is_err());
}

#[test]
fn response_item_is_none() {
    let proto = proto::get_with_proof::ResponseItem::default();

    let maybe_response_item = ResponseItem::from_proto(proto);
    assert!(maybe_response_item.is_err());
}
<|endoftext|>


<commit_before>use std::env;
use std::path::Path;
use std::process::{Command, Output};

fn check_html_file(file: &Path) -> usize {
    let to_mute = &[
        // "disabled" on <link> or "autocomplete" on <select> emit this warning
        "PROPRIETARY_ATTRIBUTE",
        // It complains when multiple in the same page link to the same anchor for some reason...
        "ANCHOR_NOT_UNIQUE",
        // If a  contains only HTML elements and no text, it complains about it.
        "TRIM_EMPTY_ELEMENT",
        // FIXME: the three next warnings are about
 elements which are not supposed to
        //        contain HTML. The solution here would be to replace them with a

        "MISSING_ENDTAG_BEFORE",
        "INSERTING_TAG",
        "DISCARDING_UNEXPECTED",
        // This error is caused by nesting the Notable Traits tooltip within an
 tag.
        // The solution is to avoid doing that, but we need to have the
 tags for accessibility
        // reasons, and we need the Notable Traits tooltip to help everyone understand the Iterator
        // combinators
        "TAG_NOT_ALLOWED_IN",
    ];
    let to_mute_s = to_mute.join(",");
    let mut command = Command::new("tidy");
    command
        .arg("-errors")
        .arg("-quiet")
        .arg("--mute-id") // this option is useful in case we want to mute more warnings
        .arg("yes")
        .arg("--mute")
        .arg(&to_mute_s)
        .arg(file);

    let Output { status, stderr, .. } = command.output().expect("failed to run tidy command");
    if status.success() {
        0
    } else {
        let stderr = String::from_utf8(stderr).expect("String::from_utf8 failed...");
        if stderr.is_empty() && status.code() != Some(2) {
            0
        } else {
            eprintln!(
                "=> Errors for `{}` (error code: {}) <=",
                file.display(),
                status.code().unwrap_or(-1)
            );
            eprintln!("{}", stderr);
            stderr.lines().count()
        }
    }
}

const DOCS_TO_CHECK: &[&str] =
    &["alloc", "core", "proc_macro", "implementors", "src", "std", "test"];

// Returns the number of files read and the number of errors.
fn find_all_html_files(dir: &Path) -> (usize, usize) {
    let mut files_read = 0;
    let mut errors = 0;

    for entry in walkdir::WalkDir::new(dir).into_iter().filter_entry(|e| {
        e.depth() != 1
            || e.file_name()
                .to_str()
                .map(|s| DOCS_TO_CHECK.into_iter().any(|d| *d == s))
                .unwrap_or(false)
    }) {
        let entry = entry.expect("failed to read file");
        if !entry.file_type().is_file() {
            continue;
        }
        let entry = entry.path();
        if entry.extension().and_then(|s| s.to_str()) == Some("html") {
            errors += check_html_file(&entry);
            files_read += 1;
        }
    }
    (files_read, errors)
}

fn main() -> Result<(), String> {
    let args = env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        return Err(format!("Usage: {} <doc folder>", args[0]));
    }

    println!("Running HTML checker...");

    let (files_read, errors) = find_all_html_files(&Path::new(&args[1]));
    println!("Done! Read {} files...", files_read);
    if errors > 0 {
        Err(format!("HTML check failed: {} errors", errors))
    } else {
        println!("No error found!");
        Ok(())
    }
}
<commit_msg>Support early stopping too old pre-installed `tidy` command for macOS in the HTML checker<commit_after>use std::env;
use std::path::Path;
use std::process::{Command, Output};

fn check_html_file(file: &Path) -> usize {
    let to_mute = &[
        // "disabled" on <link> or "autocomplete" on <select> emit this warning
        "PROPRIETARY_ATTRIBUTE",
        // It complains when multiple in the same page link to the same anchor for some reason...
        "ANCHOR_NOT_UNIQUE",
        // If a  contains only HTML elements and no text, it complains about it.
        "TRIM_EMPTY_ELEMENT",
        // FIXME: the three next warnings are about
 elements which are not supposed to
        //        contain HTML. The solution here would be to replace them with a

        "MISSING_ENDTAG_BEFORE",
        "INSERTING_TAG",
        "DISCARDING_UNEXPECTED",
        // This error is caused by nesting the Notable Traits tooltip within an
 tag.
        // The solution is to avoid doing that, but we need to have the
 tags for accessibility
        // reasons, and we need the Notable Traits tooltip to help everyone understand the Iterator
        // combinators
        "TAG_NOT_ALLOWED_IN",
    ];
    let to_mute_s = to_mute.join(",");
    let mut command = Command::new("tidy");
    command
        .arg("-errors")
        .arg("-quiet")
        .arg("--mute-id") // this option is useful in case we want to mute more warnings
        .arg("yes")
        .arg("--mute")
        .arg(&to_mute_s)
        .arg(file);

    let Output { status, stderr, .. } = command.output().expect("failed to run tidy command");
    if status.success() {
        0
    } else {
        let stderr = String::from_utf8(stderr).expect("String::from_utf8 failed...");
        if stderr.is_empty() && status.code() != Some(2) {
            0
        } else {
            eprintln!(
                "=> Errors for `{}` (error code: {}) <=",
                file.display(),
                status.code().unwrap_or(-1)
            );
            eprintln!("{}", stderr);
            stderr.lines().count()
        }
    }
}

const DOCS_TO_CHECK: &[&str] =
    &["alloc", "core", "proc_macro", "implementors", "src", "std", "test"];

// Returns the number of files read and the number of errors.
fn find_all_html_files(dir: &Path) -> (usize, usize) {
    let mut files_read = 0;
    let mut errors = 0;

    for entry in walkdir::WalkDir::new(dir).into_iter().filter_entry(|e| {
        e.depth() != 1
            || e.file_name()
                .to_str()
                .map(|s| DOCS_TO_CHECK.into_iter().any(|d| *d == s))
                .unwrap_or(false)
    }) {
        let entry = entry.expect("failed to read file");
        if !entry.file_type().is_file() {
            continue;
        }
        let entry = entry.path();
        if entry.extension().and_then(|s| s.to_str()) == Some("html") {
            errors += check_html_file(&entry);
            files_read += 1;
        }
    }
    (files_read, errors)
}

/// Default `tidy` command for macOS is too old that it does not have `mute-id` and `mute` options.
/// `tidy` on macOS Monterey was released on 31 October 2006, and the same date can be seen seven
/// years ago at <https://stackoverflow.com/questions/22283382/overwrite-osx-tidy>. Accordingly,
/// the macOS environment using pre-installed `tidy` should immediately suspend HTML checker process
/// and show a hint to install a newer one.
#[cfg(target_os = "macos")]
fn check_tidy_version() -> Result<(), String> {
    let output = Command::new("tidy").arg("-v").output().expect("failed to run tidy command");
    let version = String::from_utf8(output.stdout).expect("failed to read version of tidy command");
    if version.contains("HTML Tidy for Mac OS X released on 31 October 2006") {
        eprintln!("The pre-installed HTML Tidy for macOS is not supported.");
        eprintln!("Consider installing a newer one and re-running.");
        eprintln!("If you're using Homebrew, you can install it by the following command:");
        eprintln!("    brew install tidy-html5");
        eprintln!();
        Err("HTML check failed: 1 error".to_string())
    } else {
        Ok(())
    }
}

fn main() -> Result<(), String> {
    let args = env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        return Err(format!("Usage: {} <doc folder>", args[0]));
    }
    #[cfg(target_os = "macos")]
    check_tidy_version()?;

    println!("Running HTML checker...");

    let (files_read, errors) = find_all_html_files(&Path::new(&args[1]));
    println!("Done! Read {} files...", files_read);
    if errors > 0 {
        Err(format!("HTML check failed: {} errors", errors))
    } else {
        println!("No error found!");
        Ok(())
    }
}
<|endoftext|>