<commit_before>use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float};
use std::cmp::PartialEq;
use math::linalg::Metric;
use math::utils::dot;

pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T: Zero + One + Copy> Vector<T> {
    pub fn new(data: Vec<T>) -> Vector<T> {

    	let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }

    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {
	pub fn dot(&self, v: &Vector<T>) -> T {
    	dot(&self.data, &v.data)
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());

        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = self.data.iter().enumerate().map(|(i,s)| *s + v.data[i]).collect();

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = self.data.iter().enumerate().map(|(i,s)| *s - v.data[i]).collect();

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);

		&self.data[idx]
	}
}

impl<T: Float> Metric<T> for Vector<T> {
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<commit_msg>Operation bug fixes.<commit_after>use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float};
use std::cmp::PartialEq;
use math::linalg::Metric;
use math::utils::dot;

pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T: Zero + One + Copy> Vector<T> {
    pub fn new(data: Vec<T>) -> Vector<T> {

    	let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }

    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {
	pub fn dot(&self, v: &Vector<T>) -> T {
    	dot(&self.data, &v.data)
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) / (&f)
    }
}

impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self / (&f)
    }
}

impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) / f
    }
}

impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());
        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) + (&f)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self + (&f)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) + f
    }
}

impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = self.data.iter().enumerate().map(|(i,s)| *s + v.data[i]).collect();

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = self.data.iter().enumerate().map(|(i,s)| *s - v.data[i]).collect();

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);

		&self.data[idx]
	}
}

impl<T: Float> Metric<T> for Vector<T> {
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<|endoftext|>


<commit_before>use crate::utils::{match_def_path, paths, span_lint_and_note};
use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::GeneratorInteriorTypeCause;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for calls to await while holding a
    /// non-async-aware MutexGuard.
    ///
    /// **Why is this bad?** The Mutex types found in syd::sync and parking_lot
    /// are not designed to operate in an async context across await points.
    ///
    /// There are two potential solutions. One is to use an asynx-aware Mutex
    /// type. Many asynchronous foundation crates provide such a Mutex type. The
    /// other solution is to ensure the mutex is unlocked before calling await,
    /// either by introducing a scope or an explicit call to Drop::drop.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// use std::sync::Mutex;
    ///
    /// async fn foo(x: &Mutex<u32>) {
    ///   let guard = x.lock().unwrap();
    ///   *guard += 1;
    ///   bar.await;
    /// }
    /// ```
    ///
    /// Use instead:
    /// ```rust,ignore
    /// use std::sync::Mutex;
    ///
    /// async fn foo(x: &Mutex<u32>) {
    ///   {
    ///     let guard = x.lock().unwrap();
    ///     *guard += 1;
    ///   }
    ///   bar.await;
    /// }
    /// ```
    pub AWAIT_HOLDING_LOCK,
    pedantic,
    "Inside an async function, holding a MutexGuard while calling await"
}

declare_lint_pass!(AwaitHoldingLock => [AWAIT_HOLDING_LOCK]);

impl LateLintPass<'_> for AwaitHoldingLock {
    fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
        use AsyncGeneratorKind::{Block, Closure, Fn};
        if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {
            let body_id = BodyId {
                hir_id: body.value.hir_id,
            };
            let def_id = cx.tcx.hir().body_owner_def_id(body_id);
            let typeck_results = cx.tcx.typeck(def_id);
            check_interior_types(cx, &typeck_results.generator_interior_types, body.value.span);
        }
    }
}

fn check_interior_types(cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) {
    for ty_cause in ty_causes {
        if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
            if is_mutex_guard(cx, adt.did) {
                span_lint_and_note(
                    cx,
                    AWAIT_HOLDING_LOCK,
                    ty_cause.span,
                    "this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await.",
                    ty_cause.scope_span.or(Some(span)),
                    "these are all the await points this lock is held through",
                );
            }
        }
    }
}

fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
    match_def_path(cx, def_id, &paths::MUTEX_GUARD)
        || match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
        || match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
}
<commit_msg>Auto merge of #6028 - giraffate:fix_typo, r=flip1995<commit_after>use crate::utils::{match_def_path, paths, span_lint_and_note};
use rustc_hir::def_id::DefId;
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::GeneratorInteriorTypeCause;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for calls to await while holding a
    /// non-async-aware MutexGuard.
    ///
    /// **Why is this bad?** The Mutex types found in std::sync and parking_lot
    /// are not designed to operate in an async context across await points.
    ///
    /// There are two potential solutions. One is to use an asynx-aware Mutex
    /// type. Many asynchronous foundation crates provide such a Mutex type. The
    /// other solution is to ensure the mutex is unlocked before calling await,
    /// either by introducing a scope or an explicit call to Drop::drop.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust,ignore
    /// use std::sync::Mutex;
    ///
    /// async fn foo(x: &Mutex<u32>) {
    ///   let guard = x.lock().unwrap();
    ///   *guard += 1;
    ///   bar.await;
    /// }
    /// ```
    ///
    /// Use instead:
    /// ```rust,ignore
    /// use std::sync::Mutex;
    ///
    /// async fn foo(x: &Mutex<u32>) {
    ///   {
    ///     let guard = x.lock().unwrap();
    ///     *guard += 1;
    ///   }
    ///   bar.await;
    /// }
    /// ```
    pub AWAIT_HOLDING_LOCK,
    pedantic,
    "Inside an async function, holding a MutexGuard while calling await"
}

declare_lint_pass!(AwaitHoldingLock => [AWAIT_HOLDING_LOCK]);

impl LateLintPass<'_> for AwaitHoldingLock {
    fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
        use AsyncGeneratorKind::{Block, Closure, Fn};
        if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {
            let body_id = BodyId {
                hir_id: body.value.hir_id,
            };
            let def_id = cx.tcx.hir().body_owner_def_id(body_id);
            let typeck_results = cx.tcx.typeck(def_id);
            check_interior_types(cx, &typeck_results.generator_interior_types, body.value.span);
        }
    }
}

fn check_interior_types(cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) {
    for ty_cause in ty_causes {
        if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
            if is_mutex_guard(cx, adt.did) {
                span_lint_and_note(
                    cx,
                    AWAIT_HOLDING_LOCK,
                    ty_cause.span,
                    "this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await.",
                    ty_cause.scope_span.or(Some(span)),
                    "these are all the await points this lock is held through",
                );
            }
        }
    }
}

fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
    match_def_path(cx, def_id, &paths::MUTEX_GUARD)
        || match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
        || match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
        || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
}
<|endoftext|>


<commit_before>//! lint when there is a large size difference between variants on an enum

use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir::*;
use crate::utils::{snippet_opt, span_lint_and_then};
use crate::rustc::ty::layout::LayoutOf;
use crate::rustc_errors::Applicability;

/// **What it does:** Checks for large size differences between variants on
/// `enum`s.
///
/// **Why is this bad?** Enum size is bounded by the largest variant. Having a
/// large variant
/// can penalize the memory layout of that enum.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {
///    A(i32),
///    B([i32; 8000]),
/// }
/// ```
declare_clippy_lint! {
    pub LARGE_ENUM_VARIANT,
    perf,
    "large size difference between variants on an enum"
}

#[derive(Copy, Clone)]
pub struct LargeEnumVariant {
    maximum_size_difference_allowed: u64,
}

impl LargeEnumVariant {
    pub fn new(maximum_size_difference_allowed: u64) -> Self {
        Self {
            maximum_size_difference_allowed,
        }
    }
}

impl LintPass for LargeEnumVariant {
    fn get_lints(&self) -> LintArray {
        lint_array!(LARGE_ENUM_VARIANT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) {
        let did = cx.tcx.hir.local_def_id(item.id);
        if let ItemKind::Enum(ref def, _) = item.node {
            let ty = cx.tcx.type_of(did);
            let adt = ty.ty_adt_def()
                .expect("already checked whether this is an enum");

            let mut smallest_variant: Option<(_, _)> = None;
            let mut largest_variant: Option<(_, _)> = None;

            for (i, variant) in adt.variants.iter().enumerate() {
                let size: u64 = variant
                    .fields
                    .iter()
                    .filter_map(|f| {
                        let ty = cx.tcx.type_of(f.did);
                        // don't count generics by filtering out everything
                        // that does not have a layout
                        cx.layout_of(ty).ok().map(|l| l.size.bytes())
                    })
                    .sum();

                let grouped = (size, (i, variant));

                update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0);
                update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0);
            }

            if let (Some(smallest), Some(largest)) = (smallest_variant, largest_variant) {
                let difference = largest.0 - smallest.0;

                if difference > self.maximum_size_difference_allowed {
                    let (i, variant) = largest.1;

                    span_lint_and_then(
                        cx,
                        LARGE_ENUM_VARIANT,
                        def.variants[i].span,
                        "large size difference between variants",
                        |db| {
                            if variant.fields.len() == 1 {
                                let span = match def.variants[i].node.data {
                                    VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => {
                                        fields[0].ty.span
                                    },
                                    VariantData::Unit(_) => unreachable!(),
                                };
                                if let Some(snip) = snippet_opt(cx, span) {
                                    db.span_suggestion_with_applicability(
                                        span,
                                        "consider boxing the large fields to reduce the total size of the \
                                         enum",
                                        format!("Box<{}>", snip),
                                        Applicability::Unspecified,
                                    );
                                    return;
                                }
                            }
                            db.span_help(
                                def.variants[i].span,
                                "consider boxing the large fields to reduce the total size of the enum",
                            );
                        },
                    );
                }
            }
        }
    }
}

fn update_if<T, F>(old: &mut Option<T>, new: T, f: F)
where
    F: Fn(&T, &T) -> bool,
{
    if let Some(ref mut val) = *old {
        if f(val, &new) {
            *val = new;
        }
    } else {
        *old = Some(new);
    }
}
<commit_msg>Another Applicability adjustment<commit_after>//! lint when there is a large size difference between variants on an enum

use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc::hir::*;
use crate::utils::{snippet_opt, span_lint_and_then};
use crate::rustc::ty::layout::LayoutOf;
use crate::rustc_errors::Applicability;

/// **What it does:** Checks for large size differences between variants on
/// `enum`s.
///
/// **Why is this bad?** Enum size is bounded by the largest variant. Having a
/// large variant
/// can penalize the memory layout of that enum.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {
///    A(i32),
///    B([i32; 8000]),
/// }
/// ```
declare_clippy_lint! {
    pub LARGE_ENUM_VARIANT,
    perf,
    "large size difference between variants on an enum"
}

#[derive(Copy, Clone)]
pub struct LargeEnumVariant {
    maximum_size_difference_allowed: u64,
}

impl LargeEnumVariant {
    pub fn new(maximum_size_difference_allowed: u64) -> Self {
        Self {
            maximum_size_difference_allowed,
        }
    }
}

impl LintPass for LargeEnumVariant {
    fn get_lints(&self) -> LintArray {
        lint_array!(LARGE_ENUM_VARIANT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
    fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item) {
        let did = cx.tcx.hir.local_def_id(item.id);
        if let ItemKind::Enum(ref def, _) = item.node {
            let ty = cx.tcx.type_of(did);
            let adt = ty.ty_adt_def()
                .expect("already checked whether this is an enum");

            let mut smallest_variant: Option<(_, _)> = None;
            let mut largest_variant: Option<(_, _)> = None;

            for (i, variant) in adt.variants.iter().enumerate() {
                let size: u64 = variant
                    .fields
                    .iter()
                    .filter_map(|f| {
                        let ty = cx.tcx.type_of(f.did);
                        // don't count generics by filtering out everything
                        // that does not have a layout
                        cx.layout_of(ty).ok().map(|l| l.size.bytes())
                    })
                    .sum();

                let grouped = (size, (i, variant));

                update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0);
                update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0);
            }

            if let (Some(smallest), Some(largest)) = (smallest_variant, largest_variant) {
                let difference = largest.0 - smallest.0;

                if difference > self.maximum_size_difference_allowed {
                    let (i, variant) = largest.1;

                    span_lint_and_then(
                        cx,
                        LARGE_ENUM_VARIANT,
                        def.variants[i].span,
                        "large size difference between variants",
                        |db| {
                            if variant.fields.len() == 1 {
                                let span = match def.variants[i].node.data {
                                    VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => {
                                        fields[0].ty.span
                                    },
                                    VariantData::Unit(_) => unreachable!(),
                                };
                                if let Some(snip) = snippet_opt(cx, span) {
                                    db.span_suggestion_with_applicability(
                                        span,
                                        "consider boxing the large fields to reduce the total size of the \
                                         enum",
                                        format!("Box<{}>", snip),
                                        Applicability::MaybeIncorrect,
                                    );
                                    return;
                                }
                            }
                            db.span_help(
                                def.variants[i].span,
                                "consider boxing the large fields to reduce the total size of the enum",
                            );
                        },
                    );
                }
            }
        }
    }
}

fn update_if<T, F>(old: &mut Option<T>, new: T, f: F)
where
    F: Fn(&T, &T) -> bool,
{
    if let Some(ref mut val) = *old {
        if f(val, &new) {
            *val = new;
        }
    } else {
        *old = Some(new);
    }
}
<|endoftext|>


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

use crate::{
    metadata::{view::MetadataView, Metadata},
    metrics::metadata::{NUM_META_DOWNLOAD, NUM_META_FILES, NUM_META_MISS},
    storage::{BackupStorage, FileHandle},
    utils::{error_notes::ErrorNotes, stream::StreamX},
};
use anyhow::{anyhow, Result};
use aptos_logger::prelude::*;
use aptos_temppath::TempPath;
use async_trait::async_trait;
use clap::Parser;
use futures::stream::poll_fn;
use once_cell::sync::Lazy;
use std::{
    collections::{HashMap, HashSet},
    path::PathBuf,
    sync::Arc,
    time::Instant,
};
use tokio::{
    fs::{create_dir_all, read_dir, remove_file, OpenOptions},
    io::{AsyncRead, AsyncReadExt},
};
use tokio_stream::StreamExt;

static TEMP_METADATA_CACHE_DIR: Lazy<TempPath> = Lazy::new(|| {
    let dir = TempPath::new();
    dir.create_as_dir()
        .expect("Temp metadata dir should create.");
    dir
});

#[derive(Parser)]
pub struct MetadataCacheOpt {
    #[clap(
        long = "metadata-cache-dir",
        parse(from_os_str),
        help = "Metadata cache dir. If specified and shared across runs, \
        metadata files in cache won't be downloaded again from backup source, speeding up tool \
        boot up significantly. Cache content can be messed up if used across the devnet, the testnet\
        and the mainnet, hence it [Defaults to temporary dir]."
    )]
    dir: Option<PathBuf>,
}

impl MetadataCacheOpt {
    // in cache we save things other than the cached files.
    const SUB_DIR: &'static str = "cache";

    fn cache_dir(&self) -> PathBuf {
        self.dir
            .clone()
            .unwrap_or_else(|| TEMP_METADATA_CACHE_DIR.path().to_path_buf())
            .join(Self::SUB_DIR)
    }
}

/// Sync local cache folder with remote storage, and load all metadata entries from the cache.
pub async fn sync_and_load(
    opt: &MetadataCacheOpt,
    storage: Arc<dyn BackupStorage>,
    concurrent_downloads: usize,
) -> Result<MetadataView> {
    let timer = Instant::now();
    let cache_dir = opt.cache_dir();
    create_dir_all(&cache_dir).await.err_notes(&cache_dir)?; // create if not present already

    // List cached metadata files.
    let mut dir = read_dir(&cache_dir).await.err_notes(&cache_dir)?;
    let local_entries = poll_fn(|ctx| {
        ::std::task::Poll::Ready(match futures::ready!(dir.poll_next_entry(ctx)) {
            Ok(Some(entry)) => Some(Ok(entry)),
            Ok(None) => None,
            Err(err) => Some(Err(err)),
        })
    })
    .collect::<tokio::io::Result<Vec<_>>>()
    .await?;
    let local_hashes = local_entries
        .iter()
        .map(|e| {
            e.file_name()
                .into_string()
                .map_err(|s| anyhow!("into_string() failed for file name {:?}", s))
        })
        .collect::<Result<HashSet<_>>>()?;

    // List remote metadata files.
    let remote_file_handles = storage.list_metadata_files().await?;
    let remote_file_handle_by_hash: HashMap<_, _> = remote_file_handles
        .into_iter()
        .map(|file_handle| (file_handle.file_handle_hash(), file_handle))
        .collect();
    let remote_hashes: HashSet<_> = remote_file_handle_by_hash.keys().cloned().collect();
    info!("Metadata files listed.");
    NUM_META_FILES.set(remote_hashes.len() as i64);

    // Sync local cache with remote metadata files.
    let stale_local_hashes = local_hashes.difference(&remote_hashes);
    let new_remote_hashes = remote_hashes.difference(&local_hashes).collect::<Vec<_>>();
    let up_to_date_local_hashes = local_hashes.intersection(&remote_hashes);

    for h in stale_local_hashes {
        let file = cache_dir.join(h);
        remove_file(&file).await.err_notes(&file)?;
    }
    info!("Deleted stale metadata files in cache.");

    let num_new_files = new_remote_hashes.len();
    NUM_META_MISS.set(num_new_files as i64);
    NUM_META_DOWNLOAD.set(0);
    let futs = new_remote_hashes.iter().enumerate().map(|(i, h)| {
        let fh_by_h_ref = &remote_file_handle_by_hash;
        let storage_ref = &storage;
        let cache_dir_ref = &cache_dir;

        async move {
            let file_handle = fh_by_h_ref.get(*h).expect("In map.");
            let local_file = cache_dir_ref.join(*h);
            let local_tmp_file = cache_dir_ref.join(format!(".{}", *h));
            // download to tmp file ".xxxxxx"
            tokio::io::copy(
                &mut storage_ref
                    .open_for_read(file_handle)
                    .await
                    .err_notes(file_handle)?,
                &mut OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&local_tmp_file)
                    .await
                    .err_notes(&local_file)?,
            )
            .await?;
            // rename to target file only if successful; stale tmp file caused by failure will be
            // reclaimed on next run
            tokio::fs::rename(local_tmp_file, local_file).await?;
            info!(
                file_handle = file_handle,
                processed = i + 1,
                total = num_new_files,
                "Metadata file downloaded."
            );
            NUM_META_DOWNLOAD.inc();
            Ok(())
        }
    });
    futures::stream::iter(futs)
        .buffered_x(
            concurrent_downloads * 2, /* buffer size */
            concurrent_downloads,     /* concurrency */
        )
        .collect::<Result<Vec<_>>>()
        .await?;

    info!("Loading all metadata files to memory.");
    // Load metadata from synced cache files.
    let mut metadata_vec = Vec::new();
    for h in new_remote_hashes.into_iter().chain(up_to_date_local_hashes) {
        let cached_file = cache_dir.join(h);
        metadata_vec.extend(
            OpenOptions::new()
                .read(true)
                .open(&cached_file)
                .await
                .err_notes(&cached_file)?
                .load_metadata_lines()
                .await
                .err_notes(&cached_file)?
                .into_iter(),
        )
    }
    info!(
        total_time = timer.elapsed().as_secs(),
        "Metadata cache loaded.",
    );
    Ok(metadata_vec.into())
}

trait FileHandleHash {
    fn file_handle_hash(&self) -> String;
}

impl FileHandleHash for FileHandle {
    fn file_handle_hash(&self) -> String {
        use std::hash::{Hash, Hasher};

        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        self.hash(&mut hasher);
        format!("{:x}", hasher.finish())
    }
}

#[async_trait]
trait LoadMetadataLines {
    async fn load_metadata_lines(&mut self) -> Result<Vec<Metadata>>;
}

#[async_trait]
impl<R: AsyncRead + Send + Unpin> LoadMetadataLines for R {
    async fn load_metadata_lines(&mut self) -> Result<Vec<Metadata>> {
        let mut buf = String::new();
        self.read_to_string(&mut buf)
            .await
            .err_notes((file!(), line!(), &buf))?;
        Ok(buf
            .lines()
            .map(serde_json::from_str::<Metadata>)
            .collect::<Result<_, serde_json::error::Error>>()?)
    }
}
<commit_msg>trivial: move a log line<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    metadata::{view::MetadataView, Metadata},
    metrics::metadata::{NUM_META_DOWNLOAD, NUM_META_FILES, NUM_META_MISS},
    storage::{BackupStorage, FileHandle},
    utils::{error_notes::ErrorNotes, stream::StreamX},
};
use anyhow::{anyhow, Result};
use aptos_logger::prelude::*;
use aptos_temppath::TempPath;
use async_trait::async_trait;
use clap::Parser;
use futures::stream::poll_fn;
use once_cell::sync::Lazy;
use std::{
    collections::{HashMap, HashSet},
    path::PathBuf,
    sync::Arc,
    time::Instant,
};
use tokio::{
    fs::{create_dir_all, read_dir, remove_file, OpenOptions},
    io::{AsyncRead, AsyncReadExt},
};
use tokio_stream::StreamExt;

static TEMP_METADATA_CACHE_DIR: Lazy<TempPath> = Lazy::new(|| {
    let dir = TempPath::new();
    dir.create_as_dir()
        .expect("Temp metadata dir should create.");
    dir
});

#[derive(Parser)]
pub struct MetadataCacheOpt {
    #[clap(
        long = "metadata-cache-dir",
        parse(from_os_str),
        help = "Metadata cache dir. If specified and shared across runs, \
        metadata files in cache won't be downloaded again from backup source, speeding up tool \
        boot up significantly. Cache content can be messed up if used across the devnet, the testnet\
        and the mainnet, hence it [Defaults to temporary dir]."
    )]
    dir: Option<PathBuf>,
}

impl MetadataCacheOpt {
    // in cache we save things other than the cached files.
    const SUB_DIR: &'static str = "cache";

    fn cache_dir(&self) -> PathBuf {
        self.dir
            .clone()
            .unwrap_or_else(|| TEMP_METADATA_CACHE_DIR.path().to_path_buf())
            .join(Self::SUB_DIR)
    }
}

/// Sync local cache folder with remote storage, and load all metadata entries from the cache.
pub async fn sync_and_load(
    opt: &MetadataCacheOpt,
    storage: Arc<dyn BackupStorage>,
    concurrent_downloads: usize,
) -> Result<MetadataView> {
    let timer = Instant::now();
    let cache_dir = opt.cache_dir();
    create_dir_all(&cache_dir).await.err_notes(&cache_dir)?; // create if not present already

    // List cached metadata files.
    let mut dir = read_dir(&cache_dir).await.err_notes(&cache_dir)?;
    let local_entries = poll_fn(|ctx| {
        ::std::task::Poll::Ready(match futures::ready!(dir.poll_next_entry(ctx)) {
            Ok(Some(entry)) => Some(Ok(entry)),
            Ok(None) => None,
            Err(err) => Some(Err(err)),
        })
    })
    .collect::<tokio::io::Result<Vec<_>>>()
    .await?;
    let local_hashes = local_entries
        .iter()
        .map(|e| {
            e.file_name()
                .into_string()
                .map_err(|s| anyhow!("into_string() failed for file name {:?}", s))
        })
        .collect::<Result<HashSet<_>>>()?;

    // List remote metadata files.
    let remote_file_handles = storage.list_metadata_files().await?;
    let remote_file_handle_by_hash: HashMap<_, _> = remote_file_handles
        .into_iter()
        .map(|file_handle| (file_handle.file_handle_hash(), file_handle))
        .collect();
    let remote_hashes: HashSet<_> = remote_file_handle_by_hash.keys().cloned().collect();
    info!("Metadata files listed.");
    NUM_META_FILES.set(remote_hashes.len() as i64);

    // Sync local cache with remote metadata files.
    let stale_local_hashes = local_hashes.difference(&remote_hashes);
    let new_remote_hashes = remote_hashes.difference(&local_hashes).collect::<Vec<_>>();
    let up_to_date_local_hashes = local_hashes.intersection(&remote_hashes);

    for h in stale_local_hashes {
        let file = cache_dir.join(h);
        remove_file(&file).await.err_notes(&file)?;
        info!("Deleted stale metadata files in cache.");
    }

    let num_new_files = new_remote_hashes.len();
    NUM_META_MISS.set(num_new_files as i64);
    NUM_META_DOWNLOAD.set(0);
    let futs = new_remote_hashes.iter().enumerate().map(|(i, h)| {
        let fh_by_h_ref = &remote_file_handle_by_hash;
        let storage_ref = &storage;
        let cache_dir_ref = &cache_dir;

        async move {
            let file_handle = fh_by_h_ref.get(*h).expect("In map.");
            let local_file = cache_dir_ref.join(*h);
            let local_tmp_file = cache_dir_ref.join(format!(".{}", *h));
            // download to tmp file ".xxxxxx"
            tokio::io::copy(
                &mut storage_ref
                    .open_for_read(file_handle)
                    .await
                    .err_notes(file_handle)?,
                &mut OpenOptions::new()
                    .write(true)
                    .create_new(true)
                    .open(&local_tmp_file)
                    .await
                    .err_notes(&local_file)?,
            )
            .await?;
            // rename to target file only if successful; stale tmp file caused by failure will be
            // reclaimed on next run
            tokio::fs::rename(local_tmp_file, local_file).await?;
            info!(
                file_handle = file_handle,
                processed = i + 1,
                total = num_new_files,
                "Metadata file downloaded."
            );
            NUM_META_DOWNLOAD.inc();
            Ok(())
        }
    });
    futures::stream::iter(futs)
        .buffered_x(
            concurrent_downloads * 2, /* buffer size */
            concurrent_downloads,     /* concurrency */
        )
        .collect::<Result<Vec<_>>>()
        .await?;

    info!("Loading all metadata files to memory.");
    // Load metadata from synced cache files.
    let mut metadata_vec = Vec::new();
    for h in new_remote_hashes.into_iter().chain(up_to_date_local_hashes) {
        let cached_file = cache_dir.join(h);
        metadata_vec.extend(
            OpenOptions::new()
                .read(true)
                .open(&cached_file)
                .await
                .err_notes(&cached_file)?
                .load_metadata_lines()
                .await
                .err_notes(&cached_file)?
                .into_iter(),
        )
    }
    info!(
        total_time = timer.elapsed().as_secs(),
        "Metadata cache loaded.",
    );
    Ok(metadata_vec.into())
}

trait FileHandleHash {
    fn file_handle_hash(&self) -> String;
}

impl FileHandleHash for FileHandle {
    fn file_handle_hash(&self) -> String {
        use std::hash::{Hash, Hasher};

        let mut hasher = std::collections::hash_map::DefaultHasher::new();
        self.hash(&mut hasher);
        format!("{:x}", hasher.finish())
    }
}

#[async_trait]
trait LoadMetadataLines {
    async fn load_metadata_lines(&mut self) -> Result<Vec<Metadata>>;
}

#[async_trait]
impl<R: AsyncRead + Send + Unpin> LoadMetadataLines for R {
    async fn load_metadata_lines(&mut self) -> Result<Vec<Metadata>> {
        let mut buf = String::new();
        self.read_to_string(&mut buf)
            .await
            .err_notes((file!(), line!(), &buf))?;
        Ok(buf
            .lines()
            .map(serde_json::from_str::<Metadata>)
            .collect::<Result<_, serde_json::error::Error>>()?)
    }
}
<|endoftext|>


<commit_before>extern crate difference;
use difference::Changeset;
use std::fs::File;
use std::io::prelude::*;
use std::env;

fn main() {
    let tab: Vec<_> = env::args().collect();

    println!("{:?}", &tab[1..]);

    assert_ne!(tab.len(), 2);

    let mut f = File::open(&tab[0]).unwrap();
    let mut buffer = String::new();
    f.read_to_string(&mut buffer).unwrap();
    let mut f2 = File::open(&tab[1]).unwrap();
    let mut buffer2 = String::new();
    f2.read_to_string(&mut buffer2).unwrap();

    let changeset = Changeset::new(buffer.as_ref(), buffer2.as_ref(), "");

    println!("{}", changeset);
}
<commit_msg>add error handling and correct print<commit_after>extern crate difference;
use difference::{Difference, Changeset};
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::env;

fn main() {
    let tab: Vec<_> = env::args().collect();

    println!("{:?}", &tab[1..]);

    assert_ne!(tab.len(), 2);

    let mut f = File::open(&tab[0]).unwrap();
    let mut buffer = String::new();
    match f.read_to_string(&mut buffer) {
        Err(why) => panic!("Couldn't read {}: {}", &tab[0], why.description()),
        Ok(_) => println!("File {} read!", &tab[0]),
    }
    let mut f2 = File::open(&tab[1]).unwrap();
    let mut buffer2 = String::new();
    match f2.read_to_string(&mut buffer2) {
        Err(why) => panic!("Couldn't read {}: {}", &tab[1], why.description()),
        Ok(_) => println!("File {} read!", &tab[1]),
    };

    let Changeset { diffs, .. } = Changeset::new(buffer.as_ref(), buffer2.as_ref(), " ");

    for i in 0..diffs.len() {
        match diffs[i] {
            Difference::Same(ref x) => {
                println!("{}", x);
            }
            Difference::Add(ref x) => {
                println!("+{}", x);
            }
            Difference::Rem(ref x) => {
                println!("-{}", x);
            }
        }
    }
}
<|endoftext|>


<commit_before>use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::env;
use std::error::Error;
use std::fs;
use std::path::Path;
use std::process;

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongData {
  path: String,
  text: String,
  meta: SongMeta,
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongMeta {
  #[serde(skip_serializing_if = "Option::is_none")]
  title: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  poet: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  composer: Option<String>,
  #[serde(skip_serializing_if = "Vec::is_empty")]
  index: Vec<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  margin: Option<SongMargins>,
  paths: SongPaths,
}

impl SongMeta {
  fn ensure_margin(&mut self) -> &mut SongMargins {
    self.margin.get_or_insert(SongMargins::default())
  }
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongPaths {
  lyrics: String,
  #[serde(skip_serializing_if = "Option::is_none")]
  music: Option<String>,
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongMargins {
  #[serde(skip_serializing_if = "Option::is_none")]
  verse: Option<MarginData>,
  #[serde(skip_serializing_if = "Option::is_none")]
  refrain: Option<MarginData>,
}

impl SongMargins {
  fn ensure_verse(&mut self) -> &mut MarginData {
    self.verse.get_or_insert(MarginData::default())
  }

  fn ensure_refrain(&mut self) -> &mut MarginData {
    self.refrain.get_or_insert(MarginData::default())
  }
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct MarginData {
  #[serde(skip_serializing_if = "Option::is_none")]
  l: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  r: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct NoteData {
  path: String,
  text: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Song {
  song_data: SongData,
  note_data: Option<NoteData>,
}

#[derive(Debug)]
struct Config {
  input_file: String,
  output_path: String,
}

fn main() {
  // Get execution config.
  let args: Vec<String> = env::args().collect();
  let config = Config::new(&args).unwrap_or_else(|err| {
    println!("Problem parsing arguments: {}", err);
    process::exit(1);
  });

  // Parse metadata.
  let song = Song::new(&config).unwrap_or_else(|err| {
    println!("Problem parsing song: {}", err);
    process::exit(1);
  });

  // Write output.
  if let Err(err) = song.output(config) {
    println!("Problem writing output: {}", err);
    process::exit(1);
  }
}

impl Config {
  fn new(args: &[String]) -> Result<Config, &str> {
    if args.len() < 3 {
      return Err("not enough arguments");
    }
    let input_file = args[1].clone();
    let output_path = args[2].clone();
    Ok(Config {
      input_file,
      output_path,
    })
  }
}

impl Song {
  fn new(config: &Config) -> Result<Song, Box<dyn Error>> {
    let note_data = NoteData::new(&config.input_file)?;
    let song_data = SongData::new(&config.input_file, note_data.as_ref())?;
    Ok(Song {
      song_data,
      note_data,
    })
  }

  fn output(&self, config: Config) -> Result<(), Box<dyn Error>> {
    let yaml = serde_yaml::to_string(&self.song_data.meta)?;
    let out_path = Path::new(&config.output_path);

    // Lyrics
    let tex_path = out_path.join(&self.song_data.meta.paths.lyrics);
    fs::write(tex_path, &self.song_data.text)?;

    // Yaml
    let yml_path = out_path
      .join(&self.song_data.meta.paths.lyrics)
      .with_extension("yml");
    fs::write(yml_path, yaml.replacen("---", "--- !Laul", 1))?;

    // Notes
    match (&self.song_data.meta.paths.music, &self.note_data) {
      (Some(music_path), Some(note_data)) => {
        let ly_path = out_path.join(music_path).with_extension("ly");
        fs::write(ly_path, &note_data.text)?;
      }
      _ => (),
    }
    Ok(())
  }
}

impl NoteData {
  fn new(path: &String) -> Result<Option<NoteData>, Box<dyn Error>> {
    let input_path = Path::new(path);
    let notes_input_path = input_path
      .parent()
      .unwrap()
      .parent()
      .unwrap()
      .join("notes")
      .join(input_path.with_extension("ly").file_name().unwrap());
    println!("{:?}", notes_input_path);
    let note_data = match notes_input_path.is_file() {
      true => Some(NoteData {
        text: fs::read_to_string(&notes_input_path)?,
        path: notes_input_path.to_string_lossy().to_string(),
      }),
      false => None,
    };
    Ok(note_data)
  }
}

impl SongData {
  fn new(path: &String, note_data: Option<&NoteData>) -> Result<SongData, Box<dyn Error>> {
    let input_path = Path::new(path);
    let song_contents = fs::read_to_string(&path)?;
    let mut song_data = SongData {
      path: path.clone(),
      meta: SongMeta {
        paths: SongPaths {
          lyrics: input_path
            .with_extension("tex")
            .file_name()
            .unwrap()
            .to_string_lossy()
            .to_string(),
          music: note_data.map(|d| {
            Path::new(&d.path)
              .file_name()
              .unwrap()
              .to_string_lossy()
              .to_string()
          }),
        },
        ..SongMeta::default()
      },
      ..SongData::default()
    };
    let mut output = Vec::<String>::new();
    for (prefix, text) in song_contents.lines().map(|l| SongData::parse_line(l)) {
      match (prefix, text) {
        (None, Some(t)) => output.push(t.to_string()),
        (Some("TITLE"), Some(t)) => song_data.meta.title = Some(t.to_string()),
        (Some("POET"), Some(t)) => song_data.meta.poet = Some(t.to_string()),
        (Some("COMPOSER"), Some(t)) => song_data.meta.composer = Some(t.to_string()),
        (Some("ADDLINDEX"), Some(t)) => song_data.meta.index.push(t.to_string()),
        (Some("LMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_verse().l = Some(t.to_string())
        }
        (Some("RMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_verse().r = Some(t.to_string())
        }
        (Some("REFLMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_refrain().l = Some(t.to_string())
        }
        (Some("REFRMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_refrain().r = Some(t.to_string())
        }
        _ => {}
      }
    }
    song_data.text = output.join("\n");
    Ok(song_data)
  }

  fn parse_line(line: &str) -> (Option<&str>, Option<&str>) {
    lazy_static! {
      static ref RE: Regex = Regex::new(r"^(%(.*)=)?(.*)$").unwrap();
    }
    let cap = RE.captures(line).unwrap();
    let prefix = cap.get(2).map(|p| p.as_str());
    let text = cap.get(3).map(|t| t.as_str());
    (prefix, text)
  }
}
<commit_msg>Remove output<commit_after>use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::env;
use std::error::Error;
use std::fs;
use std::path::Path;
use std::process;

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongData {
  path: String,
  text: String,
  meta: SongMeta,
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongMeta {
  #[serde(skip_serializing_if = "Option::is_none")]
  title: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  poet: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  composer: Option<String>,
  #[serde(skip_serializing_if = "Vec::is_empty")]
  index: Vec<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  margin: Option<SongMargins>,
  paths: SongPaths,
}

impl SongMeta {
  fn ensure_margin(&mut self) -> &mut SongMargins {
    self.margin.get_or_insert(SongMargins::default())
  }
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongPaths {
  lyrics: String,
  #[serde(skip_serializing_if = "Option::is_none")]
  music: Option<String>,
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct SongMargins {
  #[serde(skip_serializing_if = "Option::is_none")]
  verse: Option<MarginData>,
  #[serde(skip_serializing_if = "Option::is_none")]
  refrain: Option<MarginData>,
}

impl SongMargins {
  fn ensure_verse(&mut self) -> &mut MarginData {
    self.verse.get_or_insert(MarginData::default())
  }

  fn ensure_refrain(&mut self) -> &mut MarginData {
    self.refrain.get_or_insert(MarginData::default())
  }
}

#[derive(Default, Debug, Serialize, Deserialize)]
struct MarginData {
  #[serde(skip_serializing_if = "Option::is_none")]
  l: Option<String>,
  #[serde(skip_serializing_if = "Option::is_none")]
  r: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct NoteData {
  path: String,
  text: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Song {
  song_data: SongData,
  note_data: Option<NoteData>,
}

#[derive(Debug)]
struct Config {
  input_file: String,
  output_path: String,
}

fn main() {
  // Get execution config.
  let args: Vec<String> = env::args().collect();
  let config = Config::new(&args).unwrap_or_else(|err| {
    println!("Problem parsing arguments: {}", err);
    process::exit(1);
  });

  // Parse metadata.
  let song = Song::new(&config).unwrap_or_else(|err| {
    println!("Problem parsing song: {}", err);
    process::exit(1);
  });

  // Write output.
  if let Err(err) = song.output(config) {
    println!("Problem writing output: {}", err);
    process::exit(1);
  }
}

impl Config {
  fn new(args: &[String]) -> Result<Config, &str> {
    if args.len() < 3 {
      return Err("not enough arguments");
    }
    let input_file = args[1].clone();
    let output_path = args[2].clone();
    Ok(Config {
      input_file,
      output_path,
    })
  }
}

impl Song {
  fn new(config: &Config) -> Result<Song, Box<dyn Error>> {
    let note_data = NoteData::new(&config.input_file)?;
    let song_data = SongData::new(&config.input_file, note_data.as_ref())?;
    Ok(Song {
      song_data,
      note_data,
    })
  }

  fn output(&self, config: Config) -> Result<(), Box<dyn Error>> {
    let yaml = serde_yaml::to_string(&self.song_data.meta)?;
    let out_path = Path::new(&config.output_path);

    // Lyrics
    let tex_path = out_path.join(&self.song_data.meta.paths.lyrics);
    fs::write(tex_path, &self.song_data.text)?;

    // Yaml
    let yml_path = out_path
      .join(&self.song_data.meta.paths.lyrics)
      .with_extension("yml");
    fs::write(yml_path, yaml.replacen("---", "--- !Laul", 1))?;

    // Notes
    match (&self.song_data.meta.paths.music, &self.note_data) {
      (Some(music_path), Some(note_data)) => {
        let ly_path = out_path.join(music_path).with_extension("ly");
        fs::write(ly_path, &note_data.text)?;
      }
      _ => (),
    }
    Ok(())
  }
}

impl NoteData {
  fn new(path: &String) -> Result<Option<NoteData>, Box<dyn Error>> {
    let input_path = Path::new(path);
    let notes_input_path = input_path
      .parent()
      .unwrap()
      .parent()
      .unwrap()
      .join("notes")
      .join(input_path.with_extension("ly").file_name().unwrap());
    let note_data = match notes_input_path.is_file() {
      true => Some(NoteData {
        text: fs::read_to_string(&notes_input_path)?,
        path: notes_input_path.to_string_lossy().to_string(),
      }),
      false => None,
    };
    Ok(note_data)
  }
}

impl SongData {
  fn new(path: &String, note_data: Option<&NoteData>) -> Result<SongData, Box<dyn Error>> {
    let input_path = Path::new(path);
    let song_contents = fs::read_to_string(&path)?;
    let mut song_data = SongData {
      path: path.clone(),
      meta: SongMeta {
        paths: SongPaths {
          lyrics: input_path
            .with_extension("tex")
            .file_name()
            .unwrap()
            .to_string_lossy()
            .to_string(),
          music: note_data.map(|d| {
            Path::new(&d.path)
              .file_name()
              .unwrap()
              .to_string_lossy()
              .to_string()
          }),
        },
        ..SongMeta::default()
      },
      ..SongData::default()
    };
    let mut output = Vec::<String>::new();
    for (prefix, text) in song_contents.lines().map(|l| SongData::parse_line(l)) {
      match (prefix, text) {
        (None, Some(t)) => output.push(t.to_string()),
        (Some("TITLE"), Some(t)) => song_data.meta.title = Some(t.to_string()),
        (Some("POET"), Some(t)) => song_data.meta.poet = Some(t.to_string()),
        (Some("COMPOSER"), Some(t)) => song_data.meta.composer = Some(t.to_string()),
        (Some("ADDLINDEX"), Some(t)) => song_data.meta.index.push(t.to_string()),
        (Some("LMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_verse().l = Some(t.to_string())
        }
        (Some("RMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_verse().r = Some(t.to_string())
        }
        (Some("REFLMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_refrain().l = Some(t.to_string())
        }
        (Some("REFRMARGIN"), Some(t)) => {
          song_data.meta.ensure_margin().ensure_refrain().r = Some(t.to_string())
        }
        _ => {}
      }
    }
    song_data.text = output.join("\n");
    Ok(song_data)
  }

  fn parse_line(line: &str) -> (Option<&str>, Option<&str>) {
    lazy_static! {
      static ref RE: Regex = Regex::new(r"^(%(.*)=)?(.*)$").unwrap();
    }
    let cap = RE.captures(line).unwrap();
    let prefix = cap.get(2).map(|p| p.as_str());
    let text = cap.get(3).map(|t| t.as_str());
    (prefix, text)
  }
}
<|endoftext|>


<commit_before>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// contributed by TeXitoi

#![feature(os, core, std_misc, env)]

#![allow(non_snake_case)]

use std::iter::{repeat, AdditiveIterator};
use std::thread::Thread;
use std::mem;
use std::num::Float;
use std::os;
use std::raw::Repr;
use std::simd::f64x2;

fn main() {
    let n = std::env::args_os().nth(1)
        .and_then(|s| s.into_string().ok())
        .and_then(|n| n.parse().ok())
        .unwrap_or(100);
    let answer = spectralnorm(n);
    println!("{:.9}", answer);
}

fn spectralnorm(n: usize) -> f64 {
    assert!(n % 2 == 0, "only even lengths are accepted");
    let mut u = repeat(1.0).take(n).collect::<Vec<_>>();
    let mut v = u.clone();
    let mut tmp = v.clone();
    for _ in 0..10 {
        mult_AtAv(&*u, v.as_mut_slice(), tmp.as_mut_slice());
        mult_AtAv(&*v, u.as_mut_slice(), tmp.as_mut_slice());
    }
    (dot(&*u, &*v) / dot(&*v, &*v)).sqrt()
}

fn mult_AtAv(v: &[f64], out: &mut [f64], tmp: &mut [f64]) {
    mult_Av(v, tmp);
    mult_Atv(tmp, out);
}

fn mult_Av(v: &[f64], out: &mut [f64]) {
    parallel(out, |start, out| mult(v, out, start, |i, j| A(i, j)));
}

fn mult_Atv(v: &[f64], out: &mut [f64]) {
    parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i)));
}

fn mult<F>(v: &[f64], out: &mut [f64], start: usize, a: F)
           where F: Fn(usize, usize) -> f64 {
    for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) {
        let mut sum = f64x2(0.0, 0.0);
        for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) {
            let top = f64x2(chunk[0], chunk[1]);
            let bot = f64x2(a(i, j), a(i, j + 1));
            sum += top / bot;
        }
        let f64x2(a, b) = sum;
        *slot = a + b;
    }
}

fn A(i: usize, j: usize) -> f64 {
    ((i + j) * (i + j + 1) / 2 + i + 1) as f64
}

fn dot(v: &[f64], u: &[f64]) -> f64 {
    v.iter().zip(u.iter()).map(|(a, b)| *a * *b).sum()
}

struct Racy<T>(T);

unsafe impl<T: 'static> Send for Racy<T> {}

// Executes a closure in parallel over the given mutable slice. The closure `f`
// is run in parallel and yielded the starting index within `v` as well as a
// sub-slice of `v`.
fn parallel<T, F>(v: &mut [T], f: F)
                  where T: Send + Sync,
                        F: Fn(usize, &mut [T]) + Sync {
    let size = v.len() / os::num_cpus() + 1;

    v.chunks_mut(size).enumerate().map(|(i, chunk)| {
        // Need to convert `f` and `chunk` to something that can cross the task
        // boundary.
        let f = Racy(&f as *const _ as *const usize);
        let raw = Racy(chunk.repr());
        Thread::scoped(move|| {
            let f = f.0 as *const F;
            unsafe { (*f)(i * size, mem::transmute(raw.0)) }
        })
    }).collect::<Vec<_>>();
}
<commit_msg>update from rust repo<commit_after>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers
// contributed by TeXitoi

#![feature(os, core, env)]

#![allow(non_snake_case)]

use std::iter::{repeat, AdditiveIterator};
use std::thread;
use std::num::Float;
use std::os;
use std::simd::f64x2;

fn main() {
    let n = std::env::args_os().nth(1)
        .and_then(|s| s.into_string().ok())
        .and_then(|n| n.parse().ok())
        .unwrap_or(100);
    let answer = spectralnorm(n);
    println!("{:.9}", answer);
}

fn spectralnorm(n: usize) -> f64 {
    assert!(n % 2 == 0, "only even lengths are accepted");
    let mut u = repeat(1.0).take(n).collect::<Vec<_>>();
    let mut v = u.clone();
    let mut tmp = v.clone();
    for _ in 0..10 {
        mult_AtAv(&u, &mut v, &mut tmp);
        mult_AtAv(&v, &mut u, &mut tmp);
    }
    (dot(&u, &v) / dot(&v, &v)).sqrt()
}

fn mult_AtAv(v: &[f64], out: &mut [f64], tmp: &mut [f64]) {
    mult_Av(v, tmp);
    mult_Atv(tmp, out);
}

fn mult_Av(v: &[f64], out: &mut [f64]) {
    parallel(out, |start, out| mult(v, out, start, |i, j| A(i, j)));
}

fn mult_Atv(v: &[f64], out: &mut [f64]) {
    parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i)));
}

fn mult<F>(v: &[f64], out: &mut [f64], start: usize, a: F)
           where F: Fn(usize, usize) -> f64 {
    for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) {
        let mut sum = f64x2(0.0, 0.0);
        for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) {
            let top = f64x2(chunk[0], chunk[1]);
            let bot = f64x2(a(i, j), a(i, j + 1));
            sum += top / bot;
        }
        let f64x2(a, b) = sum;
        *slot = a + b;
    }
}

fn A(i: usize, j: usize) -> f64 {
    ((i + j) * (i + j + 1) / 2 + i + 1) as f64
}

fn dot(v: &[f64], u: &[f64]) -> f64 {
    v.iter().zip(u.iter()).map(|(a, b)| *a * *b).sum()
}

// Executes a closure in parallel over the given mutable slice. The closure `f`
// is run in parallel and yielded the starting index within `v` as well as a
// sub-slice of `v`.
fn parallel<'a,T, F>(v: &mut [T], ref f: F)
                  where T: Send + Sync + 'a,
                        F: Fn(usize, &mut [T]) + Sync + 'a {
    let size = v.len() / os::num_cpus() + 1;
    v.chunks_mut(size).enumerate().map(|(i, chunk)| {
        thread::scoped(move|| {
            f(i * size, chunk)
        })
    }).collect::<Vec<_>>();
}
<|endoftext|>


<commit_before>//! Calls `chalk-solve` to solve a `ty::Predicate`
//!
//! In order to call `chalk-solve`, this file must convert a `CanonicalChalkEnvironmentAndGoal` into
//! a Chalk uncanonical goal. It then calls Chalk, and converts the answer back into rustc solution.

crate mod db;
crate mod lowering;

use rustc_data_structures::fx::FxHashMap;

use rustc_index::vec::IndexVec;

use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
use rustc_middle::traits::ChalkRustInterner;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable};

use rustc_infer::infer::canonical::{
    Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
};
use rustc_infer::traits::{self, CanonicalChalkEnvironmentAndGoal};

use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase;
use crate::chalk::lowering::{
    LowerInto, ParamsSubstitutor, PlaceholdersCollector, RegionsSubstitutor,
};

use chalk_solve::Solution;

crate fn provide(p: &mut Providers) {
    *p = Providers { evaluate_goal, ..*p };
}

crate fn evaluate_goal<'tcx>(
    tcx: TyCtxt<'tcx>,
    obligation: CanonicalChalkEnvironmentAndGoal<'tcx>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> {
    let interner = ChalkRustInterner { tcx };

    // Chalk doesn't have a notion of `Params`, so instead we use placeholders.
    let mut placeholders_collector = PlaceholdersCollector::new();
    obligation.visit_with(&mut placeholders_collector);

    let reempty_placeholder = tcx.mk_region(ty::RegionKind::RePlaceholder(ty::Placeholder {
        universe: ty::UniverseIndex::ROOT,
        name: ty::BoundRegionKind::BrAnon(placeholders_collector.next_anon_region_placeholder + 1),
    }));

    let mut params_substitutor =
        ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
    let obligation = obligation.fold_with(&mut params_substitutor);
    // FIXME(chalk): we really should be substituting these back in the solution
    let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;

    let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder);
    let obligation = obligation.fold_with(&mut regions_substitutor);

    let max_universe = obligation.max_universe.index();

    let lowered_goal: chalk_ir::UCanonical<
        chalk_ir::InEnvironment<chalk_ir::Goal<ChalkRustInterner<'tcx>>>,
    > = chalk_ir::UCanonical {
        canonical: chalk_ir::Canonical {
            binders: chalk_ir::CanonicalVarKinds::from_iter(
                &interner,
                obligation.variables.iter().map(|v| match v.kind {
                    CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(),
                    CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(),
                    CanonicalVarKind::Ty(ty) => match ty {
                        CanonicalTyVarKind::General(ui) => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
                            chalk_ir::UniverseIndex { counter: ui.index() },
                        ),
                        CanonicalTyVarKind::Int => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Integer),
                            chalk_ir::UniverseIndex::root(),
                        ),
                        CanonicalTyVarKind::Float => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Float),
                            chalk_ir::UniverseIndex::root(),
                        ),
                    },
                    CanonicalVarKind::Region(ui) => chalk_ir::WithKind::new(
                        chalk_ir::VariableKind::Lifetime,
                        chalk_ir::UniverseIndex { counter: ui.index() },
                    ),
                    CanonicalVarKind::Const(_ui) => unimplemented!(),
                    CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(),
                }),
            ),
            value: obligation.value.lower_into(&interner),
        },
        universes: max_universe + 1,
    };

    use chalk_solve::Solver;
    let mut solver = chalk_engine::solve::SLGSolver::new(32, None);
    let db = ChalkRustIrDatabase { interner, reempty_placeholder };
    let solution = solver.solve(&db, &lowered_goal);
    debug!(?obligation, ?solution, "evaluatate goal");

    // Ideally, the code to convert *back* to rustc types would live close to
    // the code to convert *from* rustc types. Right now though, we don't
    // really need this and so it's really minimal.
    // Right now, we also treat a `Unique` solution the same as
    // `Ambig(Definite)`. This really isn't right.
    let make_solution = |subst: chalk_ir::Substitution<_>| {
        let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
        subst.as_slice(&interner).iter().for_each(|p| {
            var_values.push(p.lower_into(&interner));
        });
        let sol = Canonical {
            max_universe: ty::UniverseIndex::from_usize(0),
            variables: obligation.variables.clone(),
            value: QueryResponse {
                var_values: CanonicalVarValues { var_values },
                region_constraints: QueryRegionConstraints::default(),
                certainty: Certainty::Proven,
                value: (),
            },
        };
        tcx.arena.alloc(sol)
    };
    solution
        .map(|s| match s {
            Solution::Unique(subst) => {
                // FIXME(chalk): handle constraints
                make_solution(subst.value.subst)
            }
            Solution::Ambig(guidance) => {
                match guidance {
                    chalk_solve::Guidance::Definite(subst) => make_solution(subst.value),
                    chalk_solve::Guidance::Suggested(_) => unimplemented!(),
                    chalk_solve::Guidance::Unknown => {
                        // chalk_fulfill doesn't use the var_values here, so
                        // let's just ignore that
                        let sol = Canonical {
                            max_universe: ty::UniverseIndex::from_usize(0),
                            variables: obligation.variables.clone(),
                            value: QueryResponse {
                                var_values: CanonicalVarValues { var_values: IndexVec::new() }
                                    .make_identity(tcx),
                                region_constraints: QueryRegionConstraints::default(),
                                certainty: Certainty::Ambiguous,
                                value: (),
                            },
                        };
                        &*tcx.arena.alloc(sol)
                    }
                }
            }
        })
        .ok_or(traits::query::NoSolution)
}
<commit_msg>Rollup merge of #80403 - 0xflotus:patch-1, r=jyn514<commit_after>//! Calls `chalk-solve` to solve a `ty::Predicate`
//!
//! In order to call `chalk-solve`, this file must convert a `CanonicalChalkEnvironmentAndGoal` into
//! a Chalk uncanonical goal. It then calls Chalk, and converts the answer back into rustc solution.

crate mod db;
crate mod lowering;

use rustc_data_structures::fx::FxHashMap;

use rustc_index::vec::IndexVec;

use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
use rustc_middle::traits::ChalkRustInterner;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable};

use rustc_infer::infer::canonical::{
    Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
};
use rustc_infer::traits::{self, CanonicalChalkEnvironmentAndGoal};

use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase;
use crate::chalk::lowering::{
    LowerInto, ParamsSubstitutor, PlaceholdersCollector, RegionsSubstitutor,
};

use chalk_solve::Solution;

crate fn provide(p: &mut Providers) {
    *p = Providers { evaluate_goal, ..*p };
}

crate fn evaluate_goal<'tcx>(
    tcx: TyCtxt<'tcx>,
    obligation: CanonicalChalkEnvironmentAndGoal<'tcx>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> {
    let interner = ChalkRustInterner { tcx };

    // Chalk doesn't have a notion of `Params`, so instead we use placeholders.
    let mut placeholders_collector = PlaceholdersCollector::new();
    obligation.visit_with(&mut placeholders_collector);

    let reempty_placeholder = tcx.mk_region(ty::RegionKind::RePlaceholder(ty::Placeholder {
        universe: ty::UniverseIndex::ROOT,
        name: ty::BoundRegionKind::BrAnon(placeholders_collector.next_anon_region_placeholder + 1),
    }));

    let mut params_substitutor =
        ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
    let obligation = obligation.fold_with(&mut params_substitutor);
    // FIXME(chalk): we really should be substituting these back in the solution
    let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;

    let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder);
    let obligation = obligation.fold_with(&mut regions_substitutor);

    let max_universe = obligation.max_universe.index();

    let lowered_goal: chalk_ir::UCanonical<
        chalk_ir::InEnvironment<chalk_ir::Goal<ChalkRustInterner<'tcx>>>,
    > = chalk_ir::UCanonical {
        canonical: chalk_ir::Canonical {
            binders: chalk_ir::CanonicalVarKinds::from_iter(
                &interner,
                obligation.variables.iter().map(|v| match v.kind {
                    CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(),
                    CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(),
                    CanonicalVarKind::Ty(ty) => match ty {
                        CanonicalTyVarKind::General(ui) => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
                            chalk_ir::UniverseIndex { counter: ui.index() },
                        ),
                        CanonicalTyVarKind::Int => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Integer),
                            chalk_ir::UniverseIndex::root(),
                        ),
                        CanonicalTyVarKind::Float => chalk_ir::WithKind::new(
                            chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::Float),
                            chalk_ir::UniverseIndex::root(),
                        ),
                    },
                    CanonicalVarKind::Region(ui) => chalk_ir::WithKind::new(
                        chalk_ir::VariableKind::Lifetime,
                        chalk_ir::UniverseIndex { counter: ui.index() },
                    ),
                    CanonicalVarKind::Const(_ui) => unimplemented!(),
                    CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(),
                }),
            ),
            value: obligation.value.lower_into(&interner),
        },
        universes: max_universe + 1,
    };

    use chalk_solve::Solver;
    let mut solver = chalk_engine::solve::SLGSolver::new(32, None);
    let db = ChalkRustIrDatabase { interner, reempty_placeholder };
    let solution = solver.solve(&db, &lowered_goal);
    debug!(?obligation, ?solution, "evaluate goal");

    // Ideally, the code to convert *back* to rustc types would live close to
    // the code to convert *from* rustc types. Right now though, we don't
    // really need this and so it's really minimal.
    // Right now, we also treat a `Unique` solution the same as
    // `Ambig(Definite)`. This really isn't right.
    let make_solution = |subst: chalk_ir::Substitution<_>| {
        let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
        subst.as_slice(&interner).iter().for_each(|p| {
            var_values.push(p.lower_into(&interner));
        });
        let sol = Canonical {
            max_universe: ty::UniverseIndex::from_usize(0),
            variables: obligation.variables.clone(),
            value: QueryResponse {
                var_values: CanonicalVarValues { var_values },
                region_constraints: QueryRegionConstraints::default(),
                certainty: Certainty::Proven,
                value: (),
            },
        };
        tcx.arena.alloc(sol)
    };
    solution
        .map(|s| match s {
            Solution::Unique(subst) => {
                // FIXME(chalk): handle constraints
                make_solution(subst.value.subst)
            }
            Solution::Ambig(guidance) => {
                match guidance {
                    chalk_solve::Guidance::Definite(subst) => make_solution(subst.value),
                    chalk_solve::Guidance::Suggested(_) => unimplemented!(),
                    chalk_solve::Guidance::Unknown => {
                        // chalk_fulfill doesn't use the var_values here, so
                        // let's just ignore that
                        let sol = Canonical {
                            max_universe: ty::UniverseIndex::from_usize(0),
                            variables: obligation.variables.clone(),
                            value: QueryResponse {
                                var_values: CanonicalVarValues { var_values: IndexVec::new() }
                                    .make_identity(tcx),
                                region_constraints: QueryRegionConstraints::default(),
                                certainty: Certainty::Ambiguous,
                                value: (),
                            },
                        };
                        &*tcx.arena.alloc(sol)
                    }
                }
            }
        })
        .ok_or(traits::query::NoSolution)
}
<|endoftext|>


<commit_before>extern crate time;
extern crate http_event_store as hes;
extern crate uuid;

use hes::event::Event;
use hes::error::ApiError::*;
use hes::expected_version::ExpectedVersion;

#[macro_use]
mod support;

#[test]
fn should_return_stream_not_found_error_attempting_to_read_nonexistent_stream() {
    let client = hes::client::Client::default();
    let nonexistent_stream_name = "some-nonexistent";
    let result = client.read_stream_events_forward(&nonexistent_stream_name, 0, 1, true);

    assert_error!(StreamNotFound(..), result.unwrap_err());
}

#[test]
fn should_return_stream_deleted_error_attempting_to_read_deleted_stream() {
    let events: Vec<Event> = vec![Event { event_id: Some(uuid::Uuid::new_v4()),
                                          event_type: "created".to_string(),
                                          data: Some("{a:1}".to_string()) }];

    let client = hes::client::Client::default();
    let stream_name = format!("stream-{}", uuid::Uuid::new_v4().simple());
    client.append_to_stream(&stream_name, ExpectedVersion::NoStream, events).unwrap();

    assert!(client.read_stream_events_forward(&stream_name, 0, 1, true).is_ok());
    assert!(client.hard_delete_stream(&stream_name, ExpectedVersion::Any).is_ok());

    let result = client.read_stream_events_forward(&stream_name, 0, 1, true);
    assert_error!(StreamDeleted(..), result.unwrap_err());
}
<commit_msg>Do minor refactoring<commit_after>extern crate time;
extern crate http_event_store as hes;
extern crate uuid;

use hes::client::Client;
use hes::event::Event;
use hes::error::ApiError::*;
use hes::expected_version::ExpectedVersion;

#[macro_use]
mod support;

#[test]
fn should_return_stream_not_found_error_attempting_to_read_nonexistent_stream() {
    let client = Client::default();
    let nonexistent_stream_name = "some-nonexistent";
    let result = client.read_stream_events_forward(&nonexistent_stream_name, 0, 1, true);

    assert_error!(StreamNotFound(..), result.unwrap_err());
}

#[test]
fn should_return_stream_deleted_error_attempting_to_read_deleted_stream() {
    let events: Vec<Event> = vec![Event { event_id: Some(uuid::Uuid::new_v4()),
                                          event_type: "created".to_string(),
                                          data: Some("{a:1}".to_string()) }];

    let client = Client::default();
    let stream_name = format!("stream-{}", uuid::Uuid::new_v4().simple());
    client.append_to_stream(&stream_name, ExpectedVersion::NoStream, events).unwrap();

    assert!(client.read_stream_events_forward(&stream_name, 0, 1, true).is_ok());
    assert!(client.hard_delete_stream(&stream_name, ExpectedVersion::Any).is_ok());

    let result = client.read_stream_events_forward(&stream_name, 0, 1, true);
    assert_error!(StreamDeleted(..), result.unwrap_err());
}
<|endoftext|>


<commit_before>use super::*;
use codemap::CodeMap;

#[test]
fn parse_quarks() {
  assert_eq!(3, 3);
}
<commit_msg>tests.parser: Add basic quarks test<commit_after>use super::*;
use super::super::lexer;
use codemap::CodeMap;

#[test]
fn parse_quarks() {
  let mut map = CodeMap::new();
  let file = map.add_file(String::from("_test"), String::from("null true false 1.3 0.3 2 3 name table"));
  let tokens = lexer::lex(&file);
  let mut it = tokens.iter().peekable();
  assert_eq!(parse_quark(&mut it), Ok(Node::Null));
  assert_eq!(parse_quark(&mut it), Ok(Node::Bool(true)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Bool(false)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Float(1.3)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Float(0.3)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Int(2)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Int(3)));
  assert_eq!(parse_quark(&mut it), Ok(Node::Name(String::from("name"))));
  assert_eq!(parse_quark(&mut it), Ok(Node::Table));
  assert_eq!(parse_quark(&mut it), Err(UnexpectedToken(lexer::Token::End)));
  it.next();
  assert_eq!(parse_quark(&mut it), Err(UnexpectedToken(lexer::Token::EOF)));
  it.next();
  assert_eq!(parse_quark(&mut it), Err(UnexpectedEOF));
}
<|endoftext|>


<commit_before>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search_executor::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: SearchExecutor<ReportData = Vec<Variation>>>: SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_executor` is a mutable reference to the search
    ///   executor that performs the search. The time manager should
    ///   be careful when calling methods on the search executor, so
    ///   as not to disturb its normal working. In particular,
    ///   `start_search`, `terminate_search`, and `try_recv_report`
    ///   methods must not be called.
    ///
    /// * `report`, when supplied, gives a reference to the next
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_executor: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<commit_msg>fix outdated doc<commit_after>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search_executor::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: SearchExecutor<ReportData = Vec<Variation>>>: SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_executor` is a mutable reference to the search
    ///   executor that performs the search. The time manager should
    ///   be careful when calling methods on the search executor, so
    ///   as not to disturb its normal working. In particular,
    ///   `start_search` and `try_recv_report` methods must not be
    ///   called, and a `"TERMINATE"` message must not be sent.
    ///
    /// * `report`, when supplied, gives a reference to the next
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_executor: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

//! # Serde code generator
//!
//! '''bash
//! cargo run --bin serdegen -- --help
//! '''

use serde_generate::{
    cpp, golang, java, python3, rust, typescript, CodeGeneratorConfig, Encoding, SourceInstaller,
};
use serde_reflection::Registry;
use std::path::PathBuf;
use structopt::{clap::arg_enum, StructOpt};

arg_enum! {
#[derive(Debug, StructOpt)]
enum Language {
    Python3,
    Cpp,
    Rust,
    Java,
    Go,
    TypeScript,
}
}

arg_enum! {
#[derive(Debug, StructOpt, PartialEq, Eq, PartialOrd, Ord)]
enum Runtime {
    Serde,
    Bincode,
    Lcs,
}
}

#[derive(Debug, StructOpt)]
#[structopt(
    name = "Serde code generator",
    about = "Generate code for Serde containers"
)]
struct Options {
    /// Path to the YAML-encoded Serde formats.
    #[structopt(parse(from_os_str))]
    input: Option<PathBuf>,

    /// Language for code generation.
    #[structopt(long, possible_values = &Language::variants(), case_insensitive = true, default_value = "Python3")]
    language: Language,

    /// Directory where to write generated modules (otherwise print code on stdout).
    #[structopt(long)]
    target_source_dir: Option<PathBuf>,

    /// Optional runtimes to install in the `target_source_dir` (if applicable).
    /// Also triggers the generation of specialized methods for each runtime.
    #[structopt(long, possible_values = &Runtime::variants(), case_insensitive = true)]
    with_runtimes: Vec<Runtime>,

    /// Module name for the Serde formats installed in the `target_source_dir`.
    /// Rust crates may contain a version number separated with a colon, e.g. "test:1.2.0".
    /// (By default, the installer will use version "0.1.0".)
    #[structopt(long)]
    module_name: Option<String>,

    /// Optional package name (Python) or module path (Go) where to find Serde runtime dependencies.
    #[structopt(long)]
    serde_package_name: Option<String>,
}

fn get_codegen_config<'a, I>(name: String, runtimes: I) -> CodeGeneratorConfig
where
    I: IntoIterator<Item = &'a Runtime>,
{
    let mut encodings = Vec::new();
    for runtime in runtimes {
        match runtime {
            Runtime::Bincode => {
                encodings.push(Encoding::Bincode);
            }
            Runtime::Lcs => {
                encodings.push(Encoding::Lcs);
            }
            _ => (),
        }
    }
    CodeGeneratorConfig::new(name).with_encodings(encodings)
}

fn main() {
    let options = Options::from_args();
    let serde_package_name_opt = options.serde_package_name.clone();
    let named_registry_opt = match &options.input {
        None => None,
        Some(input) => {
            let name = options.module_name.clone().unwrap_or_else(|| {
                input
                    .file_stem()
                    .expect("failed to deduce module name from input path")
                    .to_string_lossy()
                    .into_owned()
            });
            let content = std::fs::read_to_string(input).expect("input file must be readable");
            let registry = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
            Some((registry, name))
        }
    };
    let runtimes: std::collections::BTreeSet<_> = options.with_runtimes.into_iter().collect();

    match options.target_source_dir {
        None => {
            if let Some((registry, name)) = named_registry_opt {
                let config = get_codegen_config(name, &runtimes);

                let stdout = std::io::stdout();
                let mut out = stdout.lock();
                match options.language {
                    Language::Python3 => python3::CodeGenerator::new(&config)
                        .with_serde_package_name(serde_package_name_opt)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Rust => rust::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Cpp => cpp::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Go => golang::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Java => panic!("Code generation in Java requires `--install-dir`"),
                    Language::TypeScript => typescript::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                }
            }
        }

        Some(install_dir) => {
            let installer: Box<dyn SourceInstaller<Error = Box<dyn std::error::Error>>> =
                match options.language {
                    Language::Python3 => {
                        Box::new(python3::Installer::new(install_dir, serde_package_name_opt))
                    }
                    Language::Rust => Box::new(rust::Installer::new(install_dir)),
                    Language::Cpp => Box::new(cpp::Installer::new(install_dir)),
                    Language::Java => Box::new(java::Installer::new(install_dir)),
                    Language::Go => {
                        Box::new(golang::Installer::new(install_dir, serde_package_name_opt))
                    }
                    Language::TypeScript => Box::new(typescript::Installer::new(install_dir)),
                };

            if let Some((registry, name)) = named_registry_opt {
                let config = get_codegen_config(name, &runtimes);
                installer.install_module(&config, &registry).unwrap();
            }

            for runtime in runtimes {
                match runtime {
                    Runtime::Serde => installer.install_serde_runtime().unwrap(),
                    Runtime::Bincode => installer.install_bincode_runtime().unwrap(),
                    Runtime::Lcs => installer.install_lcs_runtime().unwrap(),
                }
            }
        }
    }
}
<commit_msg>Add C# support to serdegen<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

//! # Serde code generator
//!
//! '''bash
//! cargo run --bin serdegen -- --help
//! '''

use serde_generate::{
    cpp, csharp, golang, java, python3, rust, typescript, CodeGeneratorConfig, Encoding,
    SourceInstaller,
};
use serde_reflection::Registry;
use std::path::PathBuf;
use structopt::{clap::arg_enum, StructOpt};

arg_enum! {
#[derive(Debug, StructOpt)]
enum Language {
    Python3,
    Cpp,
    Rust,
    Java,
    Go,
    TypeScript,
    CSharp,
}
}

arg_enum! {
#[derive(Debug, StructOpt, PartialEq, Eq, PartialOrd, Ord)]
enum Runtime {
    Serde,
    Bincode,
    Lcs,
}
}

#[derive(Debug, StructOpt)]
#[structopt(
    name = "Serde code generator",
    about = "Generate code for Serde containers"
)]
struct Options {
    /// Path to the YAML-encoded Serde formats.
    #[structopt(parse(from_os_str))]
    input: Option<PathBuf>,

    /// Language for code generation.
    #[structopt(long, possible_values = &Language::variants(), case_insensitive = true, default_value = "Python3")]
    language: Language,

    /// Directory where to write generated modules (otherwise print code on stdout).
    #[structopt(long)]
    target_source_dir: Option<PathBuf>,

    /// Optional runtimes to install in the `target_source_dir` (if applicable).
    /// Also triggers the generation of specialized methods for each runtime.
    #[structopt(long, possible_values = &Runtime::variants(), case_insensitive = true)]
    with_runtimes: Vec<Runtime>,

    /// Module name for the Serde formats installed in the `target_source_dir`.
    /// Rust crates may contain a version number separated with a colon, e.g. "test:1.2.0".
    /// (By default, the installer will use version "0.1.0".)
    #[structopt(long)]
    module_name: Option<String>,

    /// Optional package name (Python) or module path (Go) where to find Serde runtime dependencies.
    #[structopt(long)]
    serde_package_name: Option<String>,
}

fn get_codegen_config<'a, I>(name: String, runtimes: I) -> CodeGeneratorConfig
where
    I: IntoIterator<Item = &'a Runtime>,
{
    let mut encodings = Vec::new();
    for runtime in runtimes {
        match runtime {
            Runtime::Bincode => {
                encodings.push(Encoding::Bincode);
            }
            Runtime::Lcs => {
                encodings.push(Encoding::Lcs);
            }
            _ => (),
        }
    }
    CodeGeneratorConfig::new(name).with_encodings(encodings)
}

fn main() {
    let options = Options::from_args();
    let serde_package_name_opt = options.serde_package_name.clone();
    let named_registry_opt = match &options.input {
        None => None,
        Some(input) => {
            let name = options.module_name.clone().unwrap_or_else(|| {
                input
                    .file_stem()
                    .expect("failed to deduce module name from input path")
                    .to_string_lossy()
                    .into_owned()
            });
            let content = std::fs::read_to_string(input).expect("input file must be readable");
            let registry = serde_yaml::from_str::<Registry>(content.as_str()).unwrap();
            Some((registry, name))
        }
    };
    let runtimes: std::collections::BTreeSet<_> = options.with_runtimes.into_iter().collect();

    match options.target_source_dir {
        None => {
            if let Some((registry, name)) = named_registry_opt {
                let config = get_codegen_config(name, &runtimes);

                let stdout = std::io::stdout();
                let mut out = stdout.lock();
                match options.language {
                    Language::Python3 => python3::CodeGenerator::new(&config)
                        .with_serde_package_name(serde_package_name_opt)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Rust => rust::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Cpp => cpp::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Go => golang::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::Java => panic!("Code generation in Java requires `--install-dir`"),
                    Language::TypeScript => typescript::CodeGenerator::new(&config)
                        .output(&mut out, &registry)
                        .unwrap(),
                    Language::CSharp => panic!("Code generation in C# requires `--install-dir`"),
                }
            }
        }

        Some(install_dir) => {
            let installer: Box<dyn SourceInstaller<Error = Box<dyn std::error::Error>>> =
                match options.language {
                    Language::Python3 => {
                        Box::new(python3::Installer::new(install_dir, serde_package_name_opt))
                    }
                    Language::Rust => Box::new(rust::Installer::new(install_dir)),
                    Language::Cpp => Box::new(cpp::Installer::new(install_dir)),
                    Language::Java => Box::new(java::Installer::new(install_dir)),
                    Language::Go => {
                        Box::new(golang::Installer::new(install_dir, serde_package_name_opt))
                    }
                    Language::TypeScript => Box::new(typescript::Installer::new(install_dir)),
                    Language::CSharp => Box::new(csharp::Installer::new(install_dir)),
                };

            if let Some((registry, name)) = named_registry_opt {
                let config = get_codegen_config(name, &runtimes);
                installer.install_module(&config, &registry).unwrap();
            }

            for runtime in runtimes {
                match runtime {
                    Runtime::Serde => installer.install_serde_runtime().unwrap(),
                    Runtime::Bincode => installer.install_bincode_runtime().unwrap(),
                    Runtime::Lcs => installer.install_lcs_runtime().unwrap(),
                }
            }
        }
    }
}
<|endoftext|>