<commit_before>/// Number of ticks.
const N: usize = 8;
/// Ticks used for the sparkline.
static TICKS: [char; N] = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];

/// Render a sparkline of `data` into `buffer`.
pub fn render_u64(data: &[u64], buffer: &mut String) {
    match data.len() {
        0 => {
            return;
        },
        1 => {
            if data[0] == 0 {
                buffer.push(TICKS[0]);
            } else {
                buffer.push(TICKS[N - 1]);
            }
            return;
        },
        _ => {},
    }
    let max = data.iter().max().unwrap();
    let min = data.iter().min().unwrap();
    let scale = ((N - 1) as f64) / ((max - min) as f64);
    for i in data {
        let tick = (((i - min) as f64) * scale) as usize;
        buffer.push(TICKS[tick]);
    }
}

/// Calculate the required capacity for the sparkline, given the length of the
/// input data.
pub fn required_capacity(len: usize) -> usize {
    len * TICKS[0].len_utf8()
}

/// Render a sparkline of `data` into a newly allocated string.
pub fn render_u64_as_string(data: &[u64]) -> String {
    let cap = required_capacity(data.len());
    let mut s = String::with_capacity(cap);
    render_u64(data, &mut s);
    debug_assert_eq!(s.capacity(), cap);
    s
}

/// Render a sparkline of `data` into `buffer`.
pub fn render_f64(data: &[f64], buffer: &mut String) {
    match data.len() {
        0 => {
            return;
        },
        1 => {
            if data[0] == 0. {
                buffer.push(TICKS[0]);
            } else {
                buffer.push(TICKS[N - 1]);
            }
            return;
        },
        _ => {},
    }
    for x in data {
        assert!(x.is_finite(), "can only render finite values");
    }
    let max = data.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
    let min = data.iter().fold(f64::INFINITY, |a, &b| a.min(b));
    let scale = ((N - 1) as f64) / (max - min);
    for x in data {
        let tick = ((x - min) * scale) as usize;
        buffer.push(TICKS[tick]);
    }
}

/// Render a sparkline of `data` into a newly allocated string.
pub fn render_f64_as_string(data: &[f64]) -> String {
    let cap = required_capacity(data.len());
    let mut s = String::with_capacity(cap);
    render_f64(data, &mut s);
    debug_assert_eq!(s.capacity(), cap);
    s
}

#[cfg(test)]
mod tests {
    #[test]
    fn render_u64() {
        let data = [2, 250, 670, 890, 2, 430, 11, 908, 123, 57];
        let mut s = String::with_capacity(super::required_capacity(data.len()));
        super::render_u64(&data, &mut s);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_u64_as_string() {
        let data = [2, 250, 670, 890, 2, 430, 11, 908, 123, 57];
        let s = super::render_u64_as_string(&data);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_f64() {
        let data = [2., 250., 670., 890., 2., 430., 11., 908., 123., 57.];
        let mut s = String::with_capacity(super::required_capacity(data.len()));
        super::render_f64(&data, &mut s);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_f64_as_string() {
        let data = [2., 250., 670., 890., 2., 430., 11., 908., 123., 57.];
        let s = super::render_f64_as_string(&data);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }
}
<commit_msg>More fixes for old Rust versions<commit_after>/// Number of ticks.
const N: usize = 8;
/// Ticks used for the sparkline.
static TICKS: [char; N] = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];

/// Render a sparkline of `data` into `buffer`.
pub fn render_u64(data: &[u64], buffer: &mut String) {
    match data.len() {
        0 => {
            return;
        },
        1 => {
            if data[0] == 0 {
                buffer.push(TICKS[0]);
            } else {
                buffer.push(TICKS[N - 1]);
            }
            return;
        },
        _ => {},
    }
    let max = data.iter().max().unwrap();
    let min = data.iter().min().unwrap();
    let scale = ((N - 1) as f64) / ((max - min) as f64);
    for i in data {
        let tick = (((i - min) as f64) * scale) as usize;
        buffer.push(TICKS[tick]);
    }
}

/// Calculate the required capacity for the sparkline, given the length of the
/// input data.
pub fn required_capacity(len: usize) -> usize {
    len * TICKS[0].len_utf8()
}

/// Render a sparkline of `data` into a newly allocated string.
pub fn render_u64_as_string(data: &[u64]) -> String {
    let cap = required_capacity(data.len());
    let mut s = String::with_capacity(cap);
    render_u64(data, &mut s);
    debug_assert_eq!(s.capacity(), cap);
    s
}

/// Render a sparkline of `data` into `buffer`.
pub fn render_f64(data: &[f64], buffer: &mut String) {
    match data.len() {
        0 => {
            return;
        },
        1 => {
            if data[0] == 0. {
                buffer.push(TICKS[0]);
            } else {
                buffer.push(TICKS[N - 1]);
            }
            return;
        },
        _ => {},
    }
    for x in data {
        assert!(x.is_finite(), "can only render finite values");
    }
    let max = data.iter().fold(
        core::f64::NEG_INFINITY, |a, &b| a.max(b));
    let min = data.iter().fold(
        core::f64::INFINITY, |a, &b| a.min(b));
    let scale = ((N - 1) as f64) / (max - min);
    for x in data {
        let tick = ((x - min) * scale) as usize;
        buffer.push(TICKS[tick]);
    }
}

/// Render a sparkline of `data` into a newly allocated string.
pub fn render_f64_as_string(data: &[f64]) -> String {
    let cap = required_capacity(data.len());
    let mut s = String::with_capacity(cap);
    render_f64(data, &mut s);
    debug_assert_eq!(s.capacity(), cap);
    s
}

#[cfg(test)]
mod tests {
    #[test]
    fn render_u64() {
        let data = [2, 250, 670, 890, 2, 430, 11, 908, 123, 57];
        let mut s = String::with_capacity(super::required_capacity(data.len()));
        super::render_u64(&data, &mut s);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_u64_as_string() {
        let data = [2, 250, 670, 890, 2, 430, 11, 908, 123, 57];
        let s = super::render_u64_as_string(&data);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_f64() {
        let data = [2., 250., 670., 890., 2., 430., 11., 908., 123., 57.];
        let mut s = String::with_capacity(super::required_capacity(data.len()));
        super::render_f64(&data, &mut s);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }

    #[test]
    fn render_f64_as_string() {
        let data = [2., 250., 670., 890., 2., 430., 11., 908., 123., 57.];
        let s = super::render_f64_as_string(&data);
        println!("{}", s);
        assert_eq!("▁▂▆▇▁▄▁█▁▁", &s);
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;

#[macro_use]
extern crate torchrs;

use torchrs::autograd::{Variable, BackwardArgs};
use torchrs::tensor::Tensor;
use torchrs::optim;

use torchrs::macros::*;
use torchrs::nn;
use torchrs::nn::{ModuleStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;

use getopts::Options;
use std::env;

fn MNIST() -> D::Dataset<D::Batch<f32, i64>> {
    panic!("just a stub")
}

#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let cmd_args: Vec<String> = env::args().collect();
    let mut args = NetArgs::default();
    let mut opts = Options::new();
    /*
    	* XXX do parsey stuff
    	*/
    args
}

#[derive(ModParse)]
struct Net<T: Default> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: Default> Net<T> {
    pub fn new() -> Net<T> {
        let mut t = Net {
            delegate: nn::Module::new(),
            conv1: nn::Conv2d::build(1, 10, 5).done(),
            conv2: nn::Conv2d::build(10, 20, 5).done(),
            fc1: nn::Linear::build(320, 50).done(),
            fc2: nn::Linear::build(50, 10).done(),
        };
        t.init_module();
        t
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net<f32> {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = F::MaxPool2dArgs::default();
        let dropout_val = F::DropoutArgs::default();
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        let mut x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                           (2, 2),
                                           &pool_val));
        let mut x = x.view(&[-1, 320]);
        let x = F::relu(&self.fc1.f(&mut x));
        let mut x = F::dropout(&x, &dropout_val);
        let x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward(&BackwardArgs::default());
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>, epoch: u32) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let (mut data, mut target) = if args.cuda {
            (Variable::new_volatile(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().reduce_max(1).1;
        correct += pred.tensor_eq(target.data()).cpu().sum();
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder
    let train_loader: D::BatchLoader<f32, i64> = D::DataLoader::new(MNIST(),
                                                                    D::DataLoaderArgs::default());
    let test_loader: D::BatchLoader<f32, i64> = D::DataLoader::new(MNIST(),
                                                                   D::DataLoaderArgs::default());
    let args = parse_args();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader, epoch);
    }
}
<commit_msg>update for latest interfaces<commit_after>extern crate getopts;
#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;

#[macro_use]
extern crate torchrs;

use torchrs::autograd::{Variable, BackwardArgs};
use torchrs::tensor::Tensor;
use torchrs::optim;

use torchrs::macros::*;
use torchrs::nn;
use torchrs::nn::{ModuleStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;

use getopts::Options;
use std::env;

fn MNIST() -> D::Dataset<D::Batch<f32, i64>> {
    panic!("just a stub")
}

#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="true")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let cmd_args: Vec<String> = env::args().collect();
    let mut args = NetArgs::default();
    let mut opts = Options::new();
    /*
    	* XXX do parsey stuff
    	*/
    args
}

#[derive(ModParse)]
struct Net<T: Default> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: Default> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

// The forward operations could take on one of two implementations.
// The first supporting a near verbatim version of the python
// implementation, and the second supporting a slightly more
// idiomatic to Rust method chaining.

// a) as a near verbatim implementation of the python version
impl ModIntf<f32> for Net<f32> {
    fn forward(&mut self, args: &mut Variable<f32>) -> Variable<f32> {
        let training = self.delegate.training;
        let pool_val = F::MaxPool2dArgs::default();
        let dropout_val = F::DropoutArgs::default();
        let mut x = F::relu(&F::max_pool2d(&self.conv1.f(args), (2, 2), &pool_val));
        let mut x = F::relu(&F::max_pool2d(&F::dropout2d(&self.conv2.f(&mut x), &dropout_val),
                                           (2, 2),
                                           &pool_val));
        let mut x = x.view(&[-1, 320]);
        let x = F::relu(&self.fc1.f(&mut x));
        let mut x = F::dropout(&x, &dropout_val);
        let x = self.fc2.f(&mut x);
        F::log_softmax(&x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad();
        let output = model.f(&mut data);
        let mut loss = F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        loss.backward(&BackwardArgs::default());
        optimizer.step();
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>, epoch: u32) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let (mut data, mut target) = if args.cuda {
            (Variable::new_volatile(data.cuda().clone()), Variable::new(target.cuda().clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        let mut output = model.f(&mut data);
        test_loss += F::nll_loss(&output, &target, &F::NLLLossArgs::default());
        let pred = output.data().reduce_max(1).1;
        correct += pred.tensor_eq(target.data()).cpu().sum();
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    // no data loaders yet so demonstrate with Vec placeholder
    let train_loader: D::BatchLoader<f32, i64> = D::DataLoader::new(MNIST(),
                                                                    D::DataLoaderArgs::default());
    let test_loader: D::BatchLoader<f32, i64> = D::DataLoader::new(MNIST(),
                                                                   D::DataLoaderArgs::default());
    let args = parse_args();
    let mut optimizer = optim::SGD::new();

    let mut model = Net::new();
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader, epoch);
    }
}
<|endoftext|>


<commit_before>//! Performs various peephole optimizations.

use crate::transform::MirPass;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::Mutability;
use rustc_index::vec::Idx;
use rustc_middle::mir::{
    visit::PlaceContext,
    visit::{MutVisitor, Visitor},
    Statement,
};
use rustc_middle::mir::{
    BinOp, Body, BorrowKind, Constant, Local, Location, Operand, Place, PlaceRef, ProjectionElem,
    Rvalue,
};
use rustc_middle::ty::{self, TyCtxt};
use std::mem;

pub struct InstCombine;

impl<'tcx> MirPass<'tcx> for InstCombine {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        // First, find optimization opportunities. This is done in a pre-pass to keep the MIR
        // read-only so that we can do global analyses on the MIR in the process (e.g.
        // `Place::ty()`).
        let optimizations = {
            let mut optimization_finder = OptimizationFinder::new(body, tcx);
            optimization_finder.visit_body(body);
            optimization_finder.optimizations
        };

        // Then carry out those optimizations.
        MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body);
    }
}

pub struct InstCombineVisitor<'tcx> {
    optimizations: OptimizationList<'tcx>,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> InstCombineVisitor<'tcx> {
    fn should_combine(&self, rvalue: &Rvalue<'tcx>, location: Location) -> bool {
        self.tcx.consider_optimizing(|| {
            format!("InstCombine - Rvalue: {:?} Location: {:?}", rvalue, location)
        })
    }
}

impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
        if self.optimizations.and_stars.remove(&location) && self.should_combine(rvalue, location) {
            debug!("replacing `&*`: {:?}", rvalue);
            let new_place = match rvalue {
                Rvalue::Ref(_, _, place) => {
                    if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
                        place.projection = self.tcx().intern_place_elems(&[proj_r]);

                        Place {
                            // Replace with dummy
                            local: mem::replace(&mut place.local, Local::new(0)),
                            projection: self.tcx().intern_place_elems(proj_l),
                        }
                    } else {
                        unreachable!();
                    }
                }
                _ => bug!("Detected `&*` but didn't find `&*`!"),
            };
            *rvalue = Rvalue::Use(Operand::Copy(new_place))
        }

        if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("replacing `Len([_; N])`: {:?}", rvalue);
                *rvalue = Rvalue::Use(Operand::Constant(box constant));
            }
        }

        if let Some(operand) = self.optimizations.unneeded_equality_comparison.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("replacing {:?} with {:?}", rvalue, operand);
                *rvalue = Rvalue::Use(operand);
            }
        }

        if let Some(place) = self.optimizations.unneeded_deref.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place);
                *rvalue = Rvalue::Use(Operand::Copy(place));
            }
        }

        self.super_rvalue(rvalue, location)
    }
}

struct MutatingUseVisitor {
    has_mutating_use: bool,
    local_to_look_for: Local,
}

impl MutatingUseVisitor {
    fn has_mutating_use_in_stmt(local: Local, stmt: &Statement<'tcx>, location: Location) -> bool {
        let mut _self = Self { has_mutating_use: false, local_to_look_for: local };
        _self.visit_statement(stmt, location);
        _self.has_mutating_use
    }
}

impl<'tcx> Visitor<'tcx> for MutatingUseVisitor {
    fn visit_local(&mut self, local: &Local, context: PlaceContext, _: Location) {
        if *local == self.local_to_look_for {
            self.has_mutating_use |= context.is_mutating_use();
        }
    }
}

/// Finds optimization opportunities on the MIR.
struct OptimizationFinder<'b, 'tcx> {
    body: &'b Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    optimizations: OptimizationList<'tcx>,
}

impl OptimizationFinder<'b, 'tcx> {
    fn new(body: &'b Body<'tcx>, tcx: TyCtxt<'tcx>) -> OptimizationFinder<'b, 'tcx> {
        OptimizationFinder { body, tcx, optimizations: OptimizationList::default() }
    }

    fn find_deref_of_address(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> {
        // FIXME(#78192): This optimization can result in unsoundness.
        if !self.tcx.sess.opts.debugging_opts.unsound_mir_opts {
            return None;
        }

        // Look for the sequence
        //
        // _2 = &_1;
        // ...
        // _5 = (*_2);
        //
        // which we can replace the last statement with `_5 = _1;` to avoid the load of `_2`.
        if let Rvalue::Use(op) = rvalue {
            let local_being_derefed = match op.place()?.as_ref() {
                PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
                _ => None,
            }?;

            let mut dead_locals_seen = vec![];

            let stmt_index = location.statement_index;
            // Look behind for statement that assigns the local from a address of operator.
            // 6 is chosen as a heuristic determined by seeing the number of times
            // the optimization kicked in compiling rust std.
            let lower_index = stmt_index.saturating_sub(6);
            let statements_to_look_in = self.body.basic_blocks()[location.block].statements
                [lower_index..stmt_index]
                .iter()
                .rev();
            for stmt in statements_to_look_in {
                match &stmt.kind {
                    // Exhaustive match on statements to detect conditions that warrant we bail out of the optimization.
                    rustc_middle::mir::StatementKind::Assign(box (l, r))
                        if l.local == local_being_derefed =>
                    {
                        match r {
                            // Looking for immutable reference e.g _local_being_deref = &_1;
                            Rvalue::Ref(
                                _,
                                // Only apply the optimization if it is an immutable borrow.
                                BorrowKind::Shared,
                                place_taken_address_of,
                            ) => {
                                // Make sure that the place has not been marked dead
                                if dead_locals_seen.contains(&place_taken_address_of.local) {
                                    return None;
                                }

                                self.optimizations
                                    .unneeded_deref
                                    .insert(location, *place_taken_address_of);
                                return Some(());
                            }

                            // We found an assignment of `local_being_deref` that is not an immutable ref, e.g the following sequence
                            // _2 = &_1;
                            // _3 = &5
                            // _2 = _3;  <-- this means it is no longer valid to replace the last statement with `_5 = _1;`
                            // _5 = (*_2);
                            _ => return None,
                        }
                    }

                    // Inline asm can do anything, so bail out of the optimization.
                    rustc_middle::mir::StatementKind::LlvmInlineAsm(_) => return None,

                    // Remember `StorageDead`s, as the local being marked dead could be the
                    // place RHS we are looking for, in which case we need to abort to avoid UB
                    // using an uninitialized place
                    rustc_middle::mir::StatementKind::StorageDead(dead) => {
                        dead_locals_seen.push(*dead)
                    }

                    // Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization.
                    rustc_middle::mir::StatementKind::Assign(box (_, _))
                    | rustc_middle::mir::StatementKind::Coverage(_)
                    | rustc_middle::mir::StatementKind::Nop
                    | rustc_middle::mir::StatementKind::FakeRead(_, _)
                    | rustc_middle::mir::StatementKind::StorageLive(_)
                    | rustc_middle::mir::StatementKind::Retag(_, _)
                    | rustc_middle::mir::StatementKind::AscribeUserType(_, _)
                    | rustc_middle::mir::StatementKind::SetDiscriminant { .. } => {
                        if MutatingUseVisitor::has_mutating_use_in_stmt(
                            local_being_derefed,
                            stmt,
                            location,
                        ) {
                            return None;
                        }
                    }
                }
            }
        }
        Some(())
    }

    fn find_unneeded_equality_comparison(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        // find Ne(_place, false) or Ne(false, _place)
        // or   Eq(_place, true) or Eq(true, _place)
        if let Rvalue::BinaryOp(op, l, r) = rvalue {
            let const_to_find = if *op == BinOp::Ne {
                false
            } else if *op == BinOp::Eq {
                true
            } else {
                return;
            };
            // (const, _place)
            if let Some(o) = self.find_operand_in_equality_comparison_pattern(l, r, const_to_find) {
                self.optimizations.unneeded_equality_comparison.insert(location, o.clone());
            }
            // (_place, const)
            else if let Some(o) =
                self.find_operand_in_equality_comparison_pattern(r, l, const_to_find)
            {
                self.optimizations.unneeded_equality_comparison.insert(location, o.clone());
            }
        }
    }

    fn find_operand_in_equality_comparison_pattern(
        &self,
        l: &Operand<'tcx>,
        r: &'a Operand<'tcx>,
        const_to_find: bool,
    ) -> Option<&'a Operand<'tcx>> {
        let const_ = l.constant()?;
        if const_.literal.ty == self.tcx.types.bool
            && const_.literal.val.try_to_bool() == Some(const_to_find)
        {
            if r.place().is_some() {
                return Some(r);
            }
        }

        None
    }
}

impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        if let Rvalue::Ref(_, _, place) = rvalue {
            if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
                place.as_ref()
            {
                // The dereferenced place must have type `&_`.
                let ty = Place::ty_from(local, proj_base, self.body, self.tcx).ty;
                if let ty::Ref(_, _, Mutability::Not) = ty.kind() {
                    self.optimizations.and_stars.insert(location);
                }
            }
        }

        if let Rvalue::Len(ref place) = *rvalue {
            let place_ty = place.ty(&self.body.local_decls, self.tcx).ty;
            if let ty::Array(_, len) = place_ty.kind() {
                let span = self.body.source_info(location).span;
                let constant = Constant { span, literal: len, user_ty: None };
                self.optimizations.arrays_lengths.insert(location, constant);
            }
        }

        let _ = self.find_deref_of_address(rvalue, location);

        self.find_unneeded_equality_comparison(rvalue, location);

        self.super_rvalue(rvalue, location)
    }
}

#[derive(Default)]
struct OptimizationList<'tcx> {
    and_stars: FxHashSet<Location>,
    arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
    unneeded_equality_comparison: FxHashMap<Location, Operand<'tcx>>,
    unneeded_deref: FxHashMap<Location, Place<'tcx>>,
}
<commit_msg>Auto merge of #79084 - simonvandel:instcombine-perf, r=oli-obk<commit_after>//! Performs various peephole optimizations.

use crate::transform::MirPass;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::Mutability;
use rustc_index::vec::Idx;
use rustc_middle::mir::{
    visit::PlaceContext,
    visit::{MutVisitor, Visitor},
    Statement,
};
use rustc_middle::mir::{
    BinOp, Body, BorrowKind, Constant, Local, Location, Operand, Place, PlaceRef, ProjectionElem,
    Rvalue,
};
use rustc_middle::ty::{self, TyCtxt};
use std::mem;

pub struct InstCombine;

impl<'tcx> MirPass<'tcx> for InstCombine {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        // First, find optimization opportunities. This is done in a pre-pass to keep the MIR
        // read-only so that we can do global analyses on the MIR in the process (e.g.
        // `Place::ty()`).
        let optimizations = {
            let mut optimization_finder = OptimizationFinder::new(body, tcx);
            optimization_finder.visit_body(body);
            optimization_finder.optimizations
        };

        if !optimizations.is_empty() {
            // Then carry out those optimizations.
            MutVisitor::visit_body(&mut InstCombineVisitor { optimizations, tcx }, body);
        }
    }
}

pub struct InstCombineVisitor<'tcx> {
    optimizations: OptimizationList<'tcx>,
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> InstCombineVisitor<'tcx> {
    fn should_combine(&self, rvalue: &Rvalue<'tcx>, location: Location) -> bool {
        self.tcx.consider_optimizing(|| {
            format!("InstCombine - Rvalue: {:?} Location: {:?}", rvalue, location)
        })
    }
}

impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
        if self.optimizations.and_stars.remove(&location) && self.should_combine(rvalue, location) {
            debug!("replacing `&*`: {:?}", rvalue);
            let new_place = match rvalue {
                Rvalue::Ref(_, _, place) => {
                    if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
                        place.projection = self.tcx().intern_place_elems(&[proj_r]);

                        Place {
                            // Replace with dummy
                            local: mem::replace(&mut place.local, Local::new(0)),
                            projection: self.tcx().intern_place_elems(proj_l),
                        }
                    } else {
                        unreachable!();
                    }
                }
                _ => bug!("Detected `&*` but didn't find `&*`!"),
            };
            *rvalue = Rvalue::Use(Operand::Copy(new_place))
        }

        if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("replacing `Len([_; N])`: {:?}", rvalue);
                *rvalue = Rvalue::Use(Operand::Constant(box constant));
            }
        }

        if let Some(operand) = self.optimizations.unneeded_equality_comparison.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("replacing {:?} with {:?}", rvalue, operand);
                *rvalue = Rvalue::Use(operand);
            }
        }

        if let Some(place) = self.optimizations.unneeded_deref.remove(&location) {
            if self.should_combine(rvalue, location) {
                debug!("unneeded_deref: replacing {:?} with {:?}", rvalue, place);
                *rvalue = Rvalue::Use(Operand::Copy(place));
            }
        }

        // We do not call super_rvalue as we are not interested in any other parts of the tree
    }
}

struct MutatingUseVisitor {
    has_mutating_use: bool,
    local_to_look_for: Local,
}

impl MutatingUseVisitor {
    fn has_mutating_use_in_stmt(local: Local, stmt: &Statement<'tcx>, location: Location) -> bool {
        let mut _self = Self { has_mutating_use: false, local_to_look_for: local };
        _self.visit_statement(stmt, location);
        _self.has_mutating_use
    }
}

impl<'tcx> Visitor<'tcx> for MutatingUseVisitor {
    fn visit_local(&mut self, local: &Local, context: PlaceContext, _: Location) {
        if *local == self.local_to_look_for {
            self.has_mutating_use |= context.is_mutating_use();
        }
    }
}

/// Finds optimization opportunities on the MIR.
struct OptimizationFinder<'b, 'tcx> {
    body: &'b Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    optimizations: OptimizationList<'tcx>,
}

impl OptimizationFinder<'b, 'tcx> {
    fn new(body: &'b Body<'tcx>, tcx: TyCtxt<'tcx>) -> OptimizationFinder<'b, 'tcx> {
        OptimizationFinder { body, tcx, optimizations: OptimizationList::default() }
    }

    fn find_deref_of_address(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> {
        // FIXME(#78192): This optimization can result in unsoundness.
        if !self.tcx.sess.opts.debugging_opts.unsound_mir_opts {
            return None;
        }

        // Look for the sequence
        //
        // _2 = &_1;
        // ...
        // _5 = (*_2);
        //
        // which we can replace the last statement with `_5 = _1;` to avoid the load of `_2`.
        if let Rvalue::Use(op) = rvalue {
            let local_being_derefed = match op.place()?.as_ref() {
                PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
                _ => None,
            }?;

            let mut dead_locals_seen = vec![];

            let stmt_index = location.statement_index;
            // Look behind for statement that assigns the local from a address of operator.
            // 6 is chosen as a heuristic determined by seeing the number of times
            // the optimization kicked in compiling rust std.
            let lower_index = stmt_index.saturating_sub(6);
            let statements_to_look_in = self.body.basic_blocks()[location.block].statements
                [lower_index..stmt_index]
                .iter()
                .rev();
            for stmt in statements_to_look_in {
                match &stmt.kind {
                    // Exhaustive match on statements to detect conditions that warrant we bail out of the optimization.
                    rustc_middle::mir::StatementKind::Assign(box (l, r))
                        if l.local == local_being_derefed =>
                    {
                        match r {
                            // Looking for immutable reference e.g _local_being_deref = &_1;
                            Rvalue::Ref(
                                _,
                                // Only apply the optimization if it is an immutable borrow.
                                BorrowKind::Shared,
                                place_taken_address_of,
                            ) => {
                                // Make sure that the place has not been marked dead
                                if dead_locals_seen.contains(&place_taken_address_of.local) {
                                    return None;
                                }

                                self.optimizations
                                    .unneeded_deref
                                    .insert(location, *place_taken_address_of);
                                return Some(());
                            }

                            // We found an assignment of `local_being_deref` that is not an immutable ref, e.g the following sequence
                            // _2 = &_1;
                            // _3 = &5
                            // _2 = _3;  <-- this means it is no longer valid to replace the last statement with `_5 = _1;`
                            // _5 = (*_2);
                            _ => return None,
                        }
                    }

                    // Inline asm can do anything, so bail out of the optimization.
                    rustc_middle::mir::StatementKind::LlvmInlineAsm(_) => return None,

                    // Remember `StorageDead`s, as the local being marked dead could be the
                    // place RHS we are looking for, in which case we need to abort to avoid UB
                    // using an uninitialized place
                    rustc_middle::mir::StatementKind::StorageDead(dead) => {
                        dead_locals_seen.push(*dead)
                    }

                    // Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization.
                    rustc_middle::mir::StatementKind::Assign(box (_, _))
                    | rustc_middle::mir::StatementKind::Coverage(_)
                    | rustc_middle::mir::StatementKind::Nop
                    | rustc_middle::mir::StatementKind::FakeRead(_, _)
                    | rustc_middle::mir::StatementKind::StorageLive(_)
                    | rustc_middle::mir::StatementKind::Retag(_, _)
                    | rustc_middle::mir::StatementKind::AscribeUserType(_, _)
                    | rustc_middle::mir::StatementKind::SetDiscriminant { .. } => {
                        if MutatingUseVisitor::has_mutating_use_in_stmt(
                            local_being_derefed,
                            stmt,
                            location,
                        ) {
                            return None;
                        }
                    }
                }
            }
        }
        Some(())
    }

    fn find_unneeded_equality_comparison(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        // find Ne(_place, false) or Ne(false, _place)
        // or   Eq(_place, true) or Eq(true, _place)
        if let Rvalue::BinaryOp(op, l, r) = rvalue {
            let const_to_find = if *op == BinOp::Ne {
                false
            } else if *op == BinOp::Eq {
                true
            } else {
                return;
            };
            // (const, _place)
            if let Some(o) = self.find_operand_in_equality_comparison_pattern(l, r, const_to_find) {
                self.optimizations.unneeded_equality_comparison.insert(location, o.clone());
            }
            // (_place, const)
            else if let Some(o) =
                self.find_operand_in_equality_comparison_pattern(r, l, const_to_find)
            {
                self.optimizations.unneeded_equality_comparison.insert(location, o.clone());
            }
        }
    }

    fn find_operand_in_equality_comparison_pattern(
        &self,
        l: &Operand<'tcx>,
        r: &'a Operand<'tcx>,
        const_to_find: bool,
    ) -> Option<&'a Operand<'tcx>> {
        let const_ = l.constant()?;
        if const_.literal.ty == self.tcx.types.bool
            && const_.literal.val.try_to_bool() == Some(const_to_find)
        {
            if r.place().is_some() {
                return Some(r);
            }
        }

        None
    }
}

impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        if let Rvalue::Ref(_, _, place) = rvalue {
            if let PlaceRef { local, projection: &[ref proj_base @ .., ProjectionElem::Deref] } =
                place.as_ref()
            {
                // The dereferenced place must have type `&_`.
                let ty = Place::ty_from(local, proj_base, self.body, self.tcx).ty;
                if let ty::Ref(_, _, Mutability::Not) = ty.kind() {
                    self.optimizations.and_stars.insert(location);
                }
            }
        }

        if let Rvalue::Len(ref place) = *rvalue {
            let place_ty = place.ty(&self.body.local_decls, self.tcx).ty;
            if let ty::Array(_, len) = place_ty.kind() {
                let span = self.body.source_info(location).span;
                let constant = Constant { span, literal: len, user_ty: None };
                self.optimizations.arrays_lengths.insert(location, constant);
            }
        }

        let _ = self.find_deref_of_address(rvalue, location);

        self.find_unneeded_equality_comparison(rvalue, location);

        // We do not call super_rvalue as we are not interested in any other parts of the tree
    }
}

#[derive(Default)]
struct OptimizationList<'tcx> {
    and_stars: FxHashSet<Location>,
    arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
    unneeded_equality_comparison: FxHashMap<Location, Operand<'tcx>>,
    unneeded_deref: FxHashMap<Location, Place<'tcx>>,
}

impl<'tcx> OptimizationList<'tcx> {
    fn is_empty(&self) -> bool {
        match self {
            OptimizationList {
                and_stars,
                arrays_lengths,
                unneeded_equality_comparison,
                unneeded_deref,
            } => {
                and_stars.is_empty()
                    && arrays_lengths.is_empty()
                    && unneeded_equality_comparison.is_empty()
                    && unneeded_deref.is_empty()
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate blip_buf;

use blip_buf::BlipBuf;

const CLOCK_RATE : f64 = 1000000.0;
const SAMPLE_RATE : u32 = 48000;

fn main() {
    let mut blip = BlipBuf::new(SAMPLE_RATE / 10);
    blip.set_rates(CLOCK_RATE, SAMPLE_RATE as f64 );

    let mut time  = 0;      // number of clocks until next wave delta
    let mut delta = 10000;  // amplitude of next delta
    let mut period = 400;   // clocks between deltas

    for _n in 0..60 {
        // Slowly lower pitch every frame
        period = period + 3;

        // Generate 1/60 second of input clocks. We could generate
        // any number of clocks here, all the way down to 1.
        let clocks = CLOCK_RATE as i32 / 60;
        while time < clocks
        {
            blip.add_delta( time as u32, delta );
            delta = -delta; // square wave deltas alternate sign
            time = time + period;
        }

        // Add those clocks to buffer and adjust time for next frame
        time = time - clocks;
        blip.end_frame( clocks as u32 );

        // Read and play any output samples now available
        while blip.samples_avail() > 0
        {
            let mut temp = &mut [0i16; 1024];
            let count = blip.read_samples( temp, false );
            play_samples( &temp[..count] );
        }
    }

    // wait until the sound finishes
    std::thread::sleep_ms(1000);
}

fn play_samples(_buf: &[i16]) {
    // play contents of _buf
}
<commit_msg>Update example to new sleep api<commit_after>extern crate blip_buf;

use std::time::Duration;
use blip_buf::BlipBuf;

const CLOCK_RATE : f64 = 1000000.0;
const SAMPLE_RATE : u32 = 48000;

fn main() {
    let mut blip = BlipBuf::new(SAMPLE_RATE / 10);
    blip.set_rates(CLOCK_RATE, SAMPLE_RATE as f64 );

    let mut time  = 0;      // number of clocks until next wave delta
    let mut delta = 10000;  // amplitude of next delta
    let mut period = 400;   // clocks between deltas

    for _n in 0..60 {
        // Slowly lower pitch every frame
        period = period + 3;

        // Generate 1/60 second of input clocks. We could generate
        // any number of clocks here, all the way down to 1.
        let clocks = CLOCK_RATE as i32 / 60;
        while time < clocks
        {
            blip.add_delta( time as u32, delta );
            delta = -delta; // square wave deltas alternate sign
            time = time + period;
        }

        // Add those clocks to buffer and adjust time for next frame
        time = time - clocks;
        blip.end_frame( clocks as u32 );

        // Read and play any output samples now available
        while blip.samples_avail() > 0
        {
            let mut temp = &mut [0i16; 1024];
            let count = blip.read_samples( temp, false );
            play_samples( &temp[..count] );
        }
    }

    // wait until the sound finishes
    std::thread::sleep(Duration::from_secs(1));
}

fn play_samples(_buf: &[i16]) {
    // play contents of _buf
}
<|endoftext|>


<commit_before>use serde_json::{json, Value};

/// Sourced from:
///
/// https://notes.ethereum.org/rmVErCfCRPKGqGkUe89-Kg
pub fn geth_genesis_json() -> Value {
    json!({
        "config": {
            "chainId":1,
            "homesteadBlock":0,
            "eip150Block":0,
            "eip155Block":0,
            "eip158Block":0,
            "byzantiumBlock":0,
            "constantinopleBlock":0,
            "petersburgBlock":0,
            "istanbulBlock":0,
            "muirGlacierBlock":0,
            "berlinBlock":0,
            "londonBlock":0,
            "clique": {
                "period": 5,
                "epoch": 30000
            },
            "terminalTotalDifficulty":0
        },
        "nonce":"0x42",
        "timestamp":"0x0",
        "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "gasLimit":"0x1C9C380",
        "difficulty":"0x400000000",
        "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "coinbase":"0x0000000000000000000000000000000000000000",
        "alloc":{
            "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}
        },
        "number":"0x0",
        "gasUsed":"0x0",
        "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "baseFeePerGas":"0x7"
    })
}

/// Sourced from:
///
/// https://github.com/NethermindEth/nethermind/blob/themerge_kintsugi/src/Nethermind/Chains/themerge_kintsugi_m2.json
pub fn nethermind_genesis_json() -> Value {
    json!({
        "name": "TheMerge_Devnet",
        "engine": {
            "clique": {
                "params": {
                    "period": 5,
                    "epoch": 30000
                }
            }
      },
      "params": {
        "gasLimitBoundDivisor": "0x400",
        "accountStartNonce": "0x0",
        "maximumExtraDataSize": "0x20",
        "minGasLimit": "0x1388",
        "networkID": 1,
        "eip150Transition": "0x0",
        "eip155Transition": "0x0",
        "eip158Transition": "0x0",
        "eip160Transition": "0x0",
        "eip161abcTransition": "0x0",
        "eip161dTransition": "0x0",
        "eip140Transition": "0x0",
        "eip211Transition": "0x0",
        "eip214Transition": "0x0",
        "eip658Transition": "0x0",
        "eip145Transition": "0x0",
        "eip1014Transition": "0x0",
        "eip1052Transition": "0x0",
        "eip1283Transition": "0x0",
        "eip1283DisableTransition": "0x0",
        "eip152Transition": "0x0",
        "eip1108Transition": "0x0",
        "eip1344Transition": "0x0",
        "eip1884Transition": "0x0",
        "eip2028Transition": "0x0",
        "eip2200Transition": "0x0",
        "eip2565Transition": "0x0",
        "eip2929Transition": "0x0",
        "eip2930Transition": "0x0",
        "eip1559Transition": "0x0",
        "eip3198Transition": "0x0",
        "eip3529Transition": "0x0",
        "eip3541Transition": "0x0"
      },
      "genesis": {
          "seal": {
              "ethereum": {
                  "nonce": "0x42",
                  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
              }
          },
          "difficulty": "0x000000000",
          "author": "0x0000000000000000000000000000000000000000",
          "timestamp": "0x0",
          "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
          "gasLimit":"0x1C9C380",
          "author": "0x0000000000000000000000000000000000000000",
          "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
          "baseFeePerGas":"0x7"
      },
      "accounts": {
          "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
              "balance":"0x6d6172697573766477000000"
          }
      }
    })
}
<commit_msg>Fix Execution Engine integration tests (#3163)<commit_after>use serde_json::{json, Value};

/// Sourced from:
///
/// https://notes.ethereum.org/rmVErCfCRPKGqGkUe89-Kg
pub fn geth_genesis_json() -> Value {
    json!({
        "config": {
            "chainId":1,
            "homesteadBlock":0,
            "eip150Block":0,
            "eip155Block":0,
            "eip158Block":0,
            "byzantiumBlock":0,
            "constantinopleBlock":0,
            "petersburgBlock":0,
            "istanbulBlock":0,
            "muirGlacierBlock":0,
            "berlinBlock":0,
            "londonBlock":0,
            "clique": {
                "period": 5,
                "epoch": 30000
            },
            "terminalTotalDifficulty":0
        },
        "nonce":"0x42",
        "timestamp":"0x0",
        "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "gasLimit":"0x1C9C380",
        "difficulty":"0x400000000",
        "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "coinbase":"0x0000000000000000000000000000000000000000",
        "alloc":{
            "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}
        },
        "number":"0x0",
        "gasUsed":"0x0",
        "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "baseFeePerGas":"0x7"
    })
}

/// Sourced from:
///
/// https://github.com/NethermindEth/nethermind/blob/kiln/src/Nethermind/Chains/themerge_kiln_testvectors.json
pub fn nethermind_genesis_json() -> Value {
    json!({
        "name": "TheMerge_Devnet",
        "engine": {
            "clique": {
                "params": {
                    "period": 5,
                    "epoch": 30000
                }
            }
        },
        "params": {
            "gasLimitBoundDivisor": "0x400",
            "accountStartNonce": "0x0",
            "maximumExtraDataSize": "0x20",
            "minGasLimit": "0x1388",
            "networkID": 1,
            "eip150Transition": "0x0",
            "eip155Transition": "0x0",
            "eip158Transition": "0x0",
            "eip160Transition": "0x0",
            "eip161abcTransition": "0x0",
            "eip161dTransition": "0x0",
            "eip140Transition": "0x0",
            "eip211Transition": "0x0",
            "eip214Transition": "0x0",
            "eip658Transition": "0x0",
            "eip145Transition": "0x0",
            "eip1014Transition": "0x0",
            "eip1052Transition": "0x0",
            "eip1283Transition": "0x0",
            "eip1283DisableTransition": "0x0",
            "eip152Transition": "0x0",
            "eip1108Transition": "0x0",
            "eip1344Transition": "0x0",
            "eip1884Transition": "0x0",
            "eip2028Transition": "0x0",
            "eip2200Transition": "0x0",
            "eip2565Transition": "0x0",
            "eip2929Transition": "0x0",
            "eip2930Transition": "0x0",
            "eip1559Transition": "0x0",
            "eip3198Transition": "0x0",
            "eip3529Transition": "0x0",
            "eip3541Transition": "0x0"
        },
        "genesis": {
            "seal": {
                "ethereum": {
                    "nonce": "0x42",
                    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
                }
            },
            "difficulty": "0x400000000",
            "author": "0x0000000000000000000000000000000000000000",
            "timestamp": "0x0",
            "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
            "extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "gasLimit":"0x1C9C380",
            "author": "0x0000000000000000000000000000000000000000",
            "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
            "baseFeePerGas":"0x7"
        },
        "accounts": {
            "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
                "balance":"0x6d6172697573766477000000"
            }
        }
    })
}
<|endoftext|>


<commit_before>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::vec;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    debug!("Stack {:?} {:?}", stack[0].borrow(), stack[1].borrow());
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb_ptr) => {
                            let comb = comb_ptr;
                            for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                stack[j] = match stack[j].borrow() {
                                    &Application(_, ref arg) => arg.clone(),
                                    _ => fail!("Expected Application")
                                };
                            }
                            let mut newStack = ~[];
                            for i in range(0, comb.arity as uint) {
                                let index = stack.len() - comb.arity as uint + i - 1;
                                newStack.push(stack[index].clone());
                            }
                            self.execute(&mut newStack, comb.instructions);
                            assert_eq!(newStack.len(), 1);
                            for _ in range(0, comb.arity + 1) {
                                stack.pop();
                            }
                            stack.push(newStack.pop());
                        }
                        Indirection(node) => stack[stack.len() - 1] = node,
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(size) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let l = stack.pop();
    let r = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);

            let mut parser = Parser::new(contents.chars());
            let module = parser.module();

            let mut compiler = Compiler::new();
            let mut vm = VM::new();
            vm.assembly = compiler.compileModule(&module);
            let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
            match x {
                Some(&(_, ref sc)) => {
                    assert!(sc.arity == 0);
                    let result = vm.evaluate(sc.instructions);
                    println!("{:?}", result);
                }
                None => ()
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[test]
fn test()
{
    format!("{:?}", main);
}
<commit_msg>Fixed arguments for primitives being in the wrong order<commit_after>#[crate_id = "vm#0.0"];
#[crate_type = "bin"];
#[feature(managed_boxes, macro_rules, globs)];
extern mod extra;
use std::hashmap::HashMap;
use std::rc::Rc;
use std::path::Path;
use std::vec;
use std::io::File;
use std::str::{from_utf8};
use typecheck::TypeEnvironment;
use compiler::{Compiler, Assembly,
    Instruction, Add, Sub, Multiply, Divide, Remainder, Push, PushGlobal, PushInt, Mkap, Eval, Unwind, Update, Pop, Slide, Split, Pack, CaseJump, Jump,
    SuperCombinator};
use parser::Parser;

mod compiler;
mod typecheck;
mod lexer;
mod parser;
mod module;
mod graph;

struct Scope<'a, T> {
    variables: HashMap<~str, T>,
    parent: Option<&'a Scope<'a, T>>
}

impl <'a, T> Scope<'a, T> {

    fn new() -> Scope<T> {
        Scope { variables : HashMap::new(), parent : None }
    }

    fn insert(&mut self, identifier : ~str, value : T) {
        self.variables.insert(identifier, value);
    }

    fn find(&'a self, identifier : &str) -> Option<&'a T> {
       match self.variables.find_equiv(&identifier) {
            Some(var) => Some(var),
            None => match self.parent {
                Some(parent) => parent.find(identifier),
                None => None
            }
       }
    }

    fn child(&'a self) -> Scope<'a, T> {
        Scope { variables : HashMap::new(), parent : Some(self) }
    }
}

#[deriving(Clone)]
enum Node<'a> {
    Application(Rc<Node<'a>>, Rc<Node<'a>>),
    Int(int),
    Combinator(&'a SuperCombinator),
    Indirection(Rc<Node<'a>>),
    Constructor(u16, ~[Rc<Node<'a>>])
}

struct VM<'a> {
    assembly : Assembly,
    heap : ~[Node<'a>]
}

impl <'a> VM<'a> {
    fn new() -> VM {
        VM { assembly : Assembly { superCombinators : ~[] }, heap : ~[] }
    }

    fn evaluate(&'a self, code: &[Instruction]) -> Node<'a> {
        let mut stack = ~[];
        self.execute(&mut stack, code);
        static evalCode : &'static [Instruction] = &[Eval];
        self.execute(&mut stack, evalCode);
        assert_eq!(stack.len(), 1);
        stack[0].borrow().clone()
    }

    fn execute(&'a self, stack : &mut ~[Rc<Node<'a>>], code : &[Instruction]) {
        debug!("----------------------------");
        debug!("Entering frame with stack");
        for x in stack.iter() {
            debug!("{:?}", x.borrow());
        }
        let mut i = 0;
        while i < code.len() {
            debug!("Executing instruction : {:?}", code[i]);
            match &code[i] {
                &Add => primitive(stack, |l, r| { l + r }),
                &Sub => primitive(stack, |l, r| { l - r }),
                &Multiply => primitive(stack, |l, r| { l * r }),
                &Divide => primitive(stack, |l, r| { l / r }),
                &Remainder => primitive(stack, |l, r| { l % r }),
                &PushInt(value) => { stack.push(Rc::new(Int(value))); }
                &Push(index) => {
                    let x = stack[index].clone();
                    debug!("Pushed {:?}", x.borrow());
                    debug!("Stack {:?} {:?}", stack[0].borrow(), stack[1].borrow());
                    stack.push(x);
                }
                &PushGlobal(index) => {
                    match &self.assembly.superCombinators[index] {
                        &(_, ref sc) => stack.push(Rc::new(Combinator(sc)))
                    }
                }
                &Mkap => {
                    let func = stack.pop();
                    let arg = stack.pop();
                    debug!("Mkap {:?} {:?}", func.borrow(), arg.borrow());
                    stack.push(Rc::new(Application(func, arg)));
                }
                &Eval => {
                    static unwindCode : &'static [Instruction] = &[Unwind];
                    let mut newStack = ~[stack.pop()];
                    self.execute(&mut newStack, unwindCode);
                    assert_eq!(newStack.len(), 1);
                    stack.push(newStack.pop());
                }
                &Pop(num) => {
                    for _ in range(0, num) {
                        stack.pop();
                    }
                }
                &Update(index) => {
                    stack[index] = Rc::new(Indirection(stack[stack.len() - 1].clone()));
                }
                &Unwind => {
                    match (*stack[stack.len() - 1].borrow()).clone() {
                        Application(func, _) => {
                            stack.push(func);
                            i -= 1;//Redo the unwind instruction
                        }
                        Combinator(comb_ptr) => {
                            let comb = comb_ptr;
                            for j in range(stack.len() - (comb.arity as uint) - 1, stack.len() - 1) {
                                stack[j] = match stack[j].borrow() {
                                    &Application(_, ref arg) => arg.clone(),
                                    _ => fail!("Expected Application")
                                };
                            }
                            let mut newStack = ~[];
                            for i in range(0, comb.arity as uint) {
                                let index = stack.len() - comb.arity as uint + i - 1;
                                newStack.push(stack[index].clone());
                            }
                            self.execute(&mut newStack, comb.instructions);
                            assert_eq!(newStack.len(), 1);
                            for _ in range(0, comb.arity + 1) {
                                stack.pop();
                            }
                            stack.push(newStack.pop());
                        }
                        Indirection(node) => stack[stack.len() - 1] = node,
                        _ => ()
                    }
                }
                &Slide(size) => {
                    let top = stack.pop();
                    for _ in range(0, size) {
                        stack.pop();
                    }
                    stack.push(top);
                }
                &Split(size) => {
                    let x = stack.pop();
                    match x.borrow() {
                        &Constructor(_, ref fields) => {
                            for field in fields.iter() {
                                stack.push(field.clone());
                            }
                        }
                        _ => fail!("Expected constructor in Split instruction")
                    }
                }
                &Pack(tag, arity) => {
                    let args = std::vec::from_fn(arity as uint, |_| stack.pop());
                    stack.push(Rc::new(Constructor(tag, args)));
                }
                &CaseJump(jump_tag) => {
                    match stack[stack.len() - 1].borrow() {
                        &Constructor(tag, _) => {
                            if jump_tag != tag as uint {
                                i += 1;//Skip the jump instruction
                            }
                        }
                        _ => fail!("Expected constructor when executing CaseJump")
                    }
                }
                &Jump(to) => {
                    i = to - 1;
                }
                //undefined => fail!("Use of undefined instruction {:?}", undefined)
            }
            i += 1;
        }
        debug!("End frame");
        debug!("--------------------------");
    }
}

fn primitive(stack: &mut ~[Rc<Node>], f: |int, int| -> int) {
    let r = stack.pop();
    let l = stack.pop();
    match (l.borrow(), r.borrow()) {
        (&Int(lhs), &Int(rhs)) => stack.push(Rc::new(Int(f(lhs, rhs)))),
        (lhs, rhs) => fail!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs)
    }
}

fn main() {
    let arguments = std::os::args();
    match arguments {
        [_, expr_str] => {
            let mut parser = Parser::new(expr_str.chars());
            let mut expr = parser.expression_();

            let mut type_env = TypeEnvironment::new();
            type_env.typecheck(&mut expr);

            let mut compiler = Compiler::new();
            let instr = compiler.compileExpression(&expr);

            let vm = VM::new();
            let mut stack = ~[];
            vm.execute(&mut stack, instr);
            println!("{:?}", stack[0].borrow());
        }
        [_, ~"-l", filename] => {
            let path = &Path::new(filename);
            let s  = File::open(path).read_to_end();
            let contents : &str = from_utf8(s);

            let mut parser = Parser::new(contents.chars());
            let module = parser.module();

            let mut compiler = Compiler::new();
            let mut vm = VM::new();
            vm.assembly = compiler.compileModule(&module);
            let x = vm.assembly.superCombinators.iter().find(|& &(ref name, _)| *name == ~"main");
            match x {
                Some(&(_, ref sc)) => {
                    assert!(sc.arity == 0);
                    let result = vm.evaluate(sc.instructions);
                    println!("{:?}", result);
                }
                None => ()
            }
        }
        _ => return println!("Expected one argument which is the expression or 2 arguments where the first is -l and the second the file to run (needs a main function)")
    }
}

#[test]
fn test()
{
    format!("{:?}", main);
}
<|endoftext|>


<commit_before>/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(deserialize_with = "url_serde::deserialize",
    serialize_with = "url_serde::serialize")]
    url: Url,
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
extern crate url;

#[cfg(test)]
#[macro_use]
extern crate serde_derive;

use std::cmp::PartialEq;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::error::Error;
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use url::{Url};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer, De<T>: Deserialize
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<T> De<T> where De<T>: serde::Deserialize {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl Deserialize for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<De<Url>, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl Deserialize for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<De<Option<Url>>, D::Error> where D: Deserializer {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T)
    where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize;

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<T> Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T> Deref for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<T> Deserialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<T> Serialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    extern crate serde_json;
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    extern crate serde_json;

    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    extern crate serde_json;

    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    extern crate serde_json;

    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    extern crate serde_json;

    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}
<commit_msg>Auto merge of #280 - servo:serde-host, r=asajeffrey<commit_after>// Copyright 2017 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

This crate provides wrappers and convenience functions to make rust-url
and Serde work hand in hand.

The supported types are:

* `url::Url`

# How do I use a data type with a `Url` member with Serde?

Use the serde attributes `deserialize_with` and `serialize_with`.

```
#[derive(serde::Serialize, serde::Deserialize)]
struct MyStruct {
    #[serde(deserialize_with = "url_serde::deserialize",
    serialize_with = "url_serde::serialize")]
    url: Url,
}
```

# How do I encode a `Url` value with `serde_json::to_string`?

Use the `Ser` wrapper.

```
serde_json::to_string(&Ser::new(&url))
```

# How do I decode a `Url` value with `serde_json::parse`?

Use the `De` wrapper.

```
serde_json::from_str(r"http:://www.rust-lang.org").map(De::into_inner)
```

# How do I send `Url` values as part of an IPC channel?

Use the `Serde` wrapper. It implements `Deref` and `DerefMut` for convenience.

```
ipc::channel::<Serde<Url>>()
```
*/

#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate serde;
#[cfg(test)] #[macro_use] extern crate serde_derive;
#[cfg(test)] extern crate serde_json;
extern crate url;

use serde::{Deserialize, Serialize, Serializer, Deserializer};
use std::cmp::PartialEq;
use std::error::Error;
use std::fmt;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::str;
use url::{Url, Host};

/// Serialises `value` with a given serializer.
///
/// This is useful to serialize `rust-url` types used in structure fields or
/// tuple members with `#[serde(serialize_with = "url_serde::serialize")]`.
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer, for<'a> Ser<'a, T>: Serialize
{
    Ser::new(value).serialize(serializer)
}

/// A wrapper to serialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::to_string`.
///
/// Values of this type can only be passed to the `serde::Serialize` trait.
#[derive(Debug)]
pub struct Ser<'a, T: 'a>(&'a T);

impl<'a, T> Ser<'a, T> where Ser<'a, T>: Serialize {
    /// Returns a new `Ser` wrapper.
    #[inline(always)]
    pub fn new(value: &'a T) -> Self {
        Ser(value)
    }
}

/// Serializes this URL into a `serde` stream.
impl<'a> Serialize for Ser<'a, Url> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(self.0.as_str())
    }
}

/// Serializes this Option<URL> into a `serde` stream.
impl<'a> Serialize for Ser<'a, Option<Url>> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        if let Some(url) = self.0.as_ref() {
            serializer.serialize_some(url.as_str())
        } else {
            serializer.serialize_none()
        }
    }
}

impl<'a, String> Serialize for Ser<'a, Host<String>> where String: AsRef<str> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self.0 {
            Host::Domain(ref s) => serializer.serialize_str(s.as_ref()),
            Host::Ipv4(_) | Host::Ipv6(_) => {
                // max("101.102.103.104".len(),
                //     "[1000:1002:1003:1004:1005:1006:101.102.103.104]".len())
                const MAX_LEN: usize = 47;
                let mut buffer = [0; MAX_LEN];
                serializer.serialize_str(display_into_buffer(&self.0, &mut buffer))
            }
        }
    }
}

/// Like .to_string(), but doesn’t allocate memory for a `String`.
///
/// Panics if `buffer` is too small.
fn display_into_buffer<'a, T: fmt::Display>(value: &T, buffer: &'a mut [u8]) -> &'a str {
    let remaining_len;
    {
        let mut remaining = &mut *buffer;
        write!(remaining, "{}", value).unwrap();
        remaining_len = remaining.len()
    }
    let written_len = buffer.len() - remaining_len;
    let written = &buffer[..written_len];

    // write! only provides std::fmt::Formatter to Display implementations,
    // which has methods write_str and write_char but no method to write arbitrary bytes.
    // Therefore, `written` is well-formed in UTF-8.
    #[allow(unsafe_code)]
    unsafe {
        str::from_utf8_unchecked(written)
    }
}

/// Deserialises a `T` value with a given deserializer.
///
/// This is useful to deserialize Url types used in structure fields or
/// tuple members with `#[serde(deserialize_with = "url_serde::deserialize")]`.
pub fn deserialize<T, D>(deserializer: D) -> Result<T, D::Error>
    where D: Deserializer, De<T>: Deserialize
{
    De::deserialize(deserializer).map(De::into_inner)
}

/// A wrapper to deserialize `rust-url` types.
///
/// This is useful with functions such as `serde_json::from_str`.
///
/// Values of this type can only be obtained through
/// the `serde::Deserialize` trait.
#[derive(Debug)]
pub struct De<T>(T);

impl<T> De<T> where De<T>: serde::Deserialize {
    /// Consumes this wrapper, returning the deserialized value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

/// Deserializes this URL from a `serde` stream.
impl Deserialize for De<Url> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Url::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// Deserializes this Option<URL> from a `serde` stream.
impl Deserialize for De<Option<Url>> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let option_representation: Option<String> = Deserialize::deserialize(deserializer)?;
        if let Some(s) = option_representation {
            return Url::parse(&s)
                .map(Some)
                .map(De)
                .map_err(|err| {serde::de::Error::custom(err.description())});
        }
        Ok(De(None))

    }
}

impl Deserialize for De<Host> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer {
        let string_representation: String = Deserialize::deserialize(deserializer)?;
        Host::parse(&string_representation).map(De).map_err(|err| {
            serde::de::Error::custom(err.description())
        })
    }
}

/// A convenience wrapper to be used as a type parameter, for example when
/// a `Vec<T>` or an `HashMap<K, V>` need to be passed to serde.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Serde<T>(pub T)
    where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize;

/// A convenience type alias for Serde<Url>.
pub type SerdeUrl = Serde<Url>;

impl<T> Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    /// Consumes this wrapper, returning the inner value.
    #[inline(always)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> fmt::Debug for Serde<T>
where T: fmt::Debug, De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T> Deref for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: PartialEq> PartialEq<T> for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn eq(&self, other: &T) -> bool {
        self.0 == *other
    }
}

impl<T> Deserialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer
    {
        De::deserialize(deserializer).map(De::into_inner).map(Serde)
    }
}

impl<T> Serialize for Serde<T>
where De<T>: Deserialize, for<'a> Ser<'a, T>: Serialize
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        Ser(&self.0).serialize(serializer)
    }
}

#[test]
fn test_ser_de_url() {
    let url = Url::parse("http://www.test.com/foo/bar?$param=bazz").unwrap();
    let s = serde_json::to_string(&Ser::new(&url)).unwrap();
    let new_url: Url = serde_json::from_str(&s).map(De::into_inner).unwrap();
    assert_eq!(url, new_url);
}

#[test]
fn test_derive_deserialize_with_for_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Url::parse(url_str).unwrap()
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

}

#[test]
fn test_derive_deserialize_with_for_option_url() {
    #[derive(Deserialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(deserialize_with = "deserialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = Test {
        url: Some(Url::parse(url_str).unwrap())
    };
    let json_string = format!(r#"{{"_url_": "{}"}}"#, url_str);
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);

    let expected = Test {
        url: None
    };
    let json_string = r#"{"_url_": null}"#;
    let got: Test = serde_json::from_str(&json_string).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Url
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Url::parse(url_str).unwrap()};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_derive_serialize_with_for_option_url() {
    #[derive(Serialize, Debug, Eq, PartialEq)]
    struct Test {
        #[serde(serialize_with = "serialize", rename = "_url_")]
        url: Option<Url>
    }

    let url_str = "http://www.test.com/foo/bar?$param=bazz";

    let expected = format!(r#"{{"_url_":"{}"}}"#, url_str);
    let input = Test {url: Some(Url::parse(url_str).unwrap())};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);

    let expected = format!(r#"{{"_url_":null}}"#);
    let input = Test {url: None};
    let got = serde_json::to_string(&input).unwrap();
    assert_eq!(expected, got);
}

#[test]
fn test_host() {
    for host in &[
        Host::Domain("foo.com".to_owned()),
        Host::Ipv4("127.0.0.1".parse().unwrap()),
        Host::Ipv6("::1".parse().unwrap()),
    ] {
        let json = serde_json::to_string(&Ser(host)).unwrap();
        let de: De<Host> = serde_json::from_str(&json).unwrap();
        assert_eq!(de.into_inner(), *host)
    }
}
<|endoftext|>