<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

#![allow(unsafe_code)]

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use canvas_traits::CanvasMsg;
use msg::compositor_msg::LayerId;
use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_cache_task::FontCacheTask;
use gfx::font_context::FontContext;
use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageResponse, ImageState};
use net_traits::image_cache_task::{UsePlaceholder};
use script::layout_interface::{Animation, LayoutChan, ReflowGoal};
use std::boxed;
use std::cell::Cell;
use std::collections::HashMap;
use std::collections::hash_state::DefaultState;
use std::ptr;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};
use style::selector_matching::Stylist;
use url::Url;
use util::fnv::FnvHasher;
use util::geometry::Au;
use util::opts;

struct LocalLayoutContext {
    font_context: FontContext,
    applicable_declarations_cache: ApplicableDeclarationsCache,
    style_sharing_candidate_cache: StyleSharingCandidateCache,
}

thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()));

fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
                               -> *mut LocalLayoutContext {
    LOCAL_CONTEXT_KEY.with(|ref r| {
        if r.get().is_null() {
            let context = box LocalLayoutContext {
                font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
                applicable_declarations_cache: ApplicableDeclarationsCache::new(),
                style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            };
            r.set(unsafe { boxed::into_raw(context) });
        } else if shared_layout_context.screen_size_changed {
            unsafe {
                (*r.get()).applicable_declarations_cache.evict_all();
            }
        }

        r.get()
    })
}

/// Layout information shared among all workers. This must be thread-safe.
pub struct SharedLayoutContext {
    /// The shared image cache task.
    pub image_cache_task: ImageCacheTask,

    /// A channel for the image cache to send responses to.
    pub image_cache_sender: ImageCacheChan,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// Screen sized changed?
    pub screen_size_changed: bool,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Interface to the font cache task.
    pub font_cache_task: FontCacheTask,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *const Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: Option<OpaqueNode>,

    /// The URL.
    pub url: Url,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,

    /// Starts at zero, and increased by one every time a layout completes.
    /// This can be used to easily check for invalid stale data.
    pub generation: u32,

    /// A channel on which new animations that have been triggered by style recalculation can be
    /// sent.
    pub new_animations_sender: Sender<Animation>,

    /// A channel to send canvas renderers to paint task, in order to correctly paint the layers
    pub canvas_layers_sender: Sender<(LayerId, Option<Arc<Mutex<Sender<CanvasMsg>>>>)>,

    /// The visible rects for each layer, as reported to us by the compositor.
    pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>,

    /// Why is this reflow occurring
    pub goal: ReflowGoal,
}

pub struct SharedLayoutContextWrapper(pub *const SharedLayoutContext);

unsafe impl Send for SharedLayoutContextWrapper {}

pub struct LayoutContext<'a> {
    pub shared: &'a SharedLayoutContext,
    cached_local_layout_context: *mut LocalLayoutContext,
}

impl<'a> LayoutContext<'a> {
    pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {

        let local_context = create_or_get_local_context(shared_layout_context);

        LayoutContext {
            shared: shared_layout_context,
            cached_local_layout_context: local_context,
        }
    }

    #[inline(always)]
    pub fn font_context<'b>(&'b self) -> &'b mut FontContext {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.font_context
        }
    }

    #[inline(always)]
    pub fn applicable_declarations_cache<'b>(&'b self) -> &'b mut ApplicableDeclarationsCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.applicable_declarations_cache
        }
    }

    #[inline(always)]
    pub fn style_sharing_candidate_cache<'b>(&'b self) -> &'b mut StyleSharingCandidateCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.style_sharing_candidate_cache
        }
    }

    pub fn get_or_request_image(&self, url: Url, use_placeholder: UsePlaceholder)
                                -> Option<Arc<Image>> {
        // See if the image is already available
        let result = self.shared.image_cache_task.get_image_if_available(url.clone(),
                                                                         use_placeholder);

        match result {
            Ok(image) => Some(image),
            Err(state) => {
                // If we are emitting an output file, then we need to block on
                // image load or we risk emitting an output file missing the image.
                let is_sync = opts::get().output_file.is_some();

                match (state, is_sync) {
                    // Image failed to load, so just return nothing
                    (ImageState::LoadError, _) => None,
                    // Not loaded, test mode - load the image synchronously
                    (_, true) => {
                        let (sync_tx, sync_rx) = channel();
                        self.shared.image_cache_task.request_image(url,
                                                                   ImageCacheChan(sync_tx),
                                                                   None);
                        match sync_rx.recv().unwrap().image_response {
                            ImageResponse::Loaded(image) |
                            ImageResponse::PlaceholderLoaded(image) => Some(image),
                            ImageResponse::None => None,
                        }
                    }
                    // Not yet requested, async mode - request image from the cache
                    (ImageState::NotRequested, false) => {
                        self.shared.image_cache_task.request_image(url,
                                                                   self.shared.image_cache_sender.clone(),
                                                                   None);
                        None
                    }
                    // Image has been requested, is still pending. Return no image
                    // for this paint loop. When the image loads it will trigger
                    // a reflow and/or repaint.
                    (ImageState::Pending, false) => None,
                }
            }
        }
    }
}
<commit_msg>Fix a rustup warning. `std::box::into_raw` is now safe.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Data needed by the layout task.

#![allow(unsafe_code)]

use css::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};

use canvas_traits::CanvasMsg;
use msg::compositor_msg::LayerId;
use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_cache_task::FontCacheTask;
use gfx::font_context::FontContext;
use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageResponse, ImageState};
use net_traits::image_cache_task::{UsePlaceholder};
use script::layout_interface::{Animation, LayoutChan, ReflowGoal};
use std::boxed;
use std::cell::Cell;
use std::collections::HashMap;
use std::collections::hash_state::DefaultState;
use std::ptr;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};
use style::selector_matching::Stylist;
use url::Url;
use util::fnv::FnvHasher;
use util::geometry::Au;
use util::opts;

struct LocalLayoutContext {
    font_context: FontContext,
    applicable_declarations_cache: ApplicableDeclarationsCache,
    style_sharing_candidate_cache: StyleSharingCandidateCache,
}

thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()));

fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
                               -> *mut LocalLayoutContext {
    LOCAL_CONTEXT_KEY.with(|ref r| {
        if r.get().is_null() {
            let context = box LocalLayoutContext {
                font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
                applicable_declarations_cache: ApplicableDeclarationsCache::new(),
                style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
            };
            r.set(boxed::into_raw(context));
        } else if shared_layout_context.screen_size_changed {
            unsafe {
                (*r.get()).applicable_declarations_cache.evict_all();
            }
        }

        r.get()
    })
}

/// Layout information shared among all workers. This must be thread-safe.
pub struct SharedLayoutContext {
    /// The shared image cache task.
    pub image_cache_task: ImageCacheTask,

    /// A channel for the image cache to send responses to.
    pub image_cache_sender: ImageCacheChan,

    /// The current screen size.
    pub screen_size: Size2D<Au>,

    /// Screen sized changed?
    pub screen_size_changed: bool,

    /// A channel up to the constellation.
    pub constellation_chan: ConstellationChan,

    /// A channel up to the layout task.
    pub layout_chan: LayoutChan,

    /// Interface to the font cache task.
    pub font_cache_task: FontCacheTask,

    /// The CSS selector stylist.
    ///
    /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s.
    pub stylist: *const Stylist,

    /// The root node at which we're starting the layout.
    pub reflow_root: Option<OpaqueNode>,

    /// The URL.
    pub url: Url,

    /// The dirty rectangle, used during display list building.
    pub dirty: Rect<Au>,

    /// Starts at zero, and increased by one every time a layout completes.
    /// This can be used to easily check for invalid stale data.
    pub generation: u32,

    /// A channel on which new animations that have been triggered by style recalculation can be
    /// sent.
    pub new_animations_sender: Sender<Animation>,

    /// A channel to send canvas renderers to paint task, in order to correctly paint the layers
    pub canvas_layers_sender: Sender<(LayerId, Option<Arc<Mutex<Sender<CanvasMsg>>>>)>,

    /// The visible rects for each layer, as reported to us by the compositor.
    pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>,

    /// Why is this reflow occurring
    pub goal: ReflowGoal,
}

pub struct SharedLayoutContextWrapper(pub *const SharedLayoutContext);

unsafe impl Send for SharedLayoutContextWrapper {}

pub struct LayoutContext<'a> {
    pub shared: &'a SharedLayoutContext,
    cached_local_layout_context: *mut LocalLayoutContext,
}

impl<'a> LayoutContext<'a> {
    pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {

        let local_context = create_or_get_local_context(shared_layout_context);

        LayoutContext {
            shared: shared_layout_context,
            cached_local_layout_context: local_context,
        }
    }

    #[inline(always)]
    pub fn font_context<'b>(&'b self) -> &'b mut FontContext {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.font_context
        }
    }

    #[inline(always)]
    pub fn applicable_declarations_cache<'b>(&'b self) -> &'b mut ApplicableDeclarationsCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.applicable_declarations_cache
        }
    }

    #[inline(always)]
    pub fn style_sharing_candidate_cache<'b>(&'b self) -> &'b mut StyleSharingCandidateCache {
        unsafe {
            let cached_context = &mut *self.cached_local_layout_context;
            &mut cached_context.style_sharing_candidate_cache
        }
    }

    pub fn get_or_request_image(&self, url: Url, use_placeholder: UsePlaceholder)
                                -> Option<Arc<Image>> {
        // See if the image is already available
        let result = self.shared.image_cache_task.get_image_if_available(url.clone(),
                                                                         use_placeholder);

        match result {
            Ok(image) => Some(image),
            Err(state) => {
                // If we are emitting an output file, then we need to block on
                // image load or we risk emitting an output file missing the image.
                let is_sync = opts::get().output_file.is_some();

                match (state, is_sync) {
                    // Image failed to load, so just return nothing
                    (ImageState::LoadError, _) => None,
                    // Not loaded, test mode - load the image synchronously
                    (_, true) => {
                        let (sync_tx, sync_rx) = channel();
                        self.shared.image_cache_task.request_image(url,
                                                                   ImageCacheChan(sync_tx),
                                                                   None);
                        match sync_rx.recv().unwrap().image_response {
                            ImageResponse::Loaded(image) |
                            ImageResponse::PlaceholderLoaded(image) => Some(image),
                            ImageResponse::None => None,
                        }
                    }
                    // Not yet requested, async mode - request image from the cache
                    (ImageState::NotRequested, false) => {
                        self.shared.image_cache_task.request_image(url,
                                                                   self.shared.image_cache_sender.clone(),
                                                                   None);
                        None
                    }
                    // Image has been requested, is still pending. Return no image
                    // for this paint loop. When the image loads it will trigger
                    // a reflow and/or repaint.
                    (ImageState::Pending, false) => None,
                }
            }
        }
    }
}
<|endoftext|>


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

use syntax::ast;
use syntax::ast::P;
use syntax::ext::base::ExtCtxt;
use syntax::codemap::DUMMY_SP;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ToTokens;
use syntax::parse::token;

use super::Builder;
use super::super::node;
use super::utils;

/// A visitor to build the field setters for primitive registers
pub struct BuildSetters<'a, 'b, 'c> {
  builder: &'a mut Builder,
  cx: &'b ExtCtxt<'c>,
}

impl<'a, 'b, 'c> BuildSetters<'a, 'b, 'c> {
  pub fn new(builder: &'a mut Builder, cx: &'b ExtCtxt<'c>)
             -> BuildSetters<'a, 'b, 'c> {
    BuildSetters { builder: builder, cx: cx }
  }
}

impl<'a, 'b, 'c> node::RegVisitor for BuildSetters<'a, 'b, 'c> {
  fn visit_prim_reg<'a>(&'a mut self, path: &Vec<String>,
      reg: &'a node::Reg, _width: node::RegWidth, fields: &Vec<node::Field>)
  {
    if fields.iter().any(|f| f.access != node::ReadOnly) {
      let it = build_type(self.cx, path, reg, fields);
      self.builder.push_item(it);

      let it = build_drop(self.cx, path, reg, fields);
      self.builder.push_item(it);

      let it = build_impl(self.cx, path, reg, fields);
      self.builder.push_item(it);
    }
  }
}

fn build_type<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    reg: &node::Reg, _fields: &Vec<node::Field>) -> P<ast::Item>
{
  let packed_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");
  let name = utils::setter_name(cx, path);
  let reg_ty = cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));

  let reg_doc = match reg.docstring {
    Some(d) => d.node,
    None => cx.ident_of("no documentation"),
  };
  let docstring = format!("Update value of `{}` register: {}",
                          reg.name.node,
                          reg_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  let item = quote_item!(cx,
    $doc_attr
    #[allow(non_camel_case_types)]
    pub struct $name<'a> {
      value: $packed_ty,
      mask: $packed_ty,
      reg: &'a $reg_ty,
    }
  );
  item.unwrap()
}

fn build_new<'a>(cx: &'a ExtCtxt, path: &Vec<String>)
                 -> P<ast::Item> {
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));
  let setter_ty: P<ast::Ty> = cx.ty_ident(DUMMY_SP,
                                          utils::setter_name(cx, path));
  let item = quote_item!(cx,
    #[doc="Create a new updater"]
    pub fn new(reg: &'a $reg_ty) -> $setter_ty {
      $setter_ty {
        value: 0,
        mask: 0,
        reg: reg,
      }
    });
  item.unwrap()
}

fn build_drop<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    reg: &node::Reg, fields: &Vec<node::Field>) -> P<ast::Item>
{
  let setter_ty: P<ast::Ty> = cx.ty_ident(DUMMY_SP,
                                          utils::setter_name(cx, path));
  let unpacked_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");

  // ensure we don't unintentionally clear a set-to-clear flag
  let mut clear: u32 = 0;
  for f in fields.iter() {
    match f.access {
      node::SetToClear => {
        let mask = 1 << (f.count.node * f.width) - 1;
        clear |= mask;
      },
      _ => {},
    }
  }

  // no need to read write-only registers
  let wo_reg: bool = fields.iter().all(|f| f.access == node::WriteOnly);
  let initial_value =
    if wo_reg {
      quote_expr!(cx, 0)
    } else {
      quote_expr!(cx, self.reg.value.get())
    };

  let item = quote_item!(cx,
    #[unsafe_destructor]
    #[doc = "This performs the register update"]
    impl<'a> Drop for $setter_ty<'a> {
      fn drop(&mut self) {
        let clear_mask: $unpacked_ty = $clear as $unpacked_ty;
        if self.mask != 0 {
          let v: $unpacked_ty = $initial_value & ! clear_mask & ! self.mask;
          self.reg.value.set(self.value | v);
        }
      }
    }
  );
  item.unwrap()
}

fn build_done<'a>(cx: &'a ExtCtxt) -> P<ast::Method>
{
  quote_method!(cx,
    #[doc="Commit changes to register. This is to allow chains of `set_*` \
           invocations to be used as a statement."]
    pub fn done(self) {}
  )
}

fn build_impl<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                  fields: &Vec<node::Field>) -> P<ast::Item>
{
  let new = build_new(cx, path);
  let setter_ty: P<ast::Ty> = cx.ty_ident(
    DUMMY_SP,
    utils::setter_name(cx, path));
  let methods: Vec<P<ast::Method>> =
    FromIterator::from_iter(
      fields.iter()
        .filter_map(|field| build_field_fn(cx, path, reg, field)));
  let done: P<ast::Method> = build_done(cx);
  let impl_ = quote_item!(cx,
    #[allow(dead_code)]
    impl<'a> $setter_ty<'a> {
      $new
      $methods
      $done
    }
    );
  impl_.unwrap()
}

fn build_field_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                      field: &node::Field) -> Option<P<ast::Method>>
{
  match field.access {
    node::ReadOnly => None,
    node::SetToClear => Some(build_field_clear_fn(cx, path, reg, field)),
    _ => Some(build_field_set_fn(cx, path, reg, field)),
  }
}

/// Build a setter for a field
fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                          field: &node::Field) -> P<ast::Method>
{
  let setter_ty = utils::setter_name(cx, path);
  let unpacked_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");
  let fn_name =
    cx.ident_of((String::from_str("set_")+field.name.node).as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let mask = utils::mask(cx, field);

  let field_doc = match field.docstring {
    Some(d) => token::get_ident(d.node).get().into_string(),
    None => "no documentation".into_string(),
  };
  let docstring = format!("Set value of `{}` field: {}",
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  if field.count.node == 1 {
    let shift = utils::shift(cx, None, field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, new_value: $field_ty)
          -> &'b mut $setter_ty<'a> {
        self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  } else {
    let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, idx: uint, new_value: $field_ty)
          -> &'b mut $setter_ty<'a> {
        self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  }
}

fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    _: &node::Reg, field: &node::Field) -> P<ast::Method>
{
  let setter_ty = utils::setter_name(cx, path);
  let fn_name =
    cx.ident_of((String::from_str("clear_")+field.name.node).as_slice());
  let mask = utils::mask(cx, field);

  let field_doc = match field.docstring {
    Some(d) => token::get_ident(d.node).get().into_string(),
    None => "no documentation".into_string(),
  };
  let docstring = format!("Clear `{}` flag: {}",
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  if field.count.node == 1 {
    let shift = utils::shift(cx, None, field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self) -> &'b mut $setter_ty<'a> {
        self.value |= $mask << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  } else {
    let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, idx: uint) -> &'b mut $setter_ty<'a> {
        self.value |= $mask << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  }
}
<commit_msg>ioreg::setter: Make documentation consistent with others<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use syntax::ast;
use syntax::ast::P;
use syntax::ext::base::ExtCtxt;
use syntax::codemap::DUMMY_SP;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ToTokens;
use syntax::parse::token;

use super::Builder;
use super::super::node;
use super::utils;

/// A visitor to build the field setters for primitive registers
pub struct BuildSetters<'a, 'b, 'c> {
  builder: &'a mut Builder,
  cx: &'b ExtCtxt<'c>,
}

impl<'a, 'b, 'c> BuildSetters<'a, 'b, 'c> {
  pub fn new(builder: &'a mut Builder, cx: &'b ExtCtxt<'c>)
             -> BuildSetters<'a, 'b, 'c> {
    BuildSetters { builder: builder, cx: cx }
  }
}

impl<'a, 'b, 'c> node::RegVisitor for BuildSetters<'a, 'b, 'c> {
  fn visit_prim_reg<'a>(&'a mut self, path: &Vec<String>,
      reg: &'a node::Reg, _width: node::RegWidth, fields: &Vec<node::Field>)
  {
    if fields.iter().any(|f| f.access != node::ReadOnly) {
      let it = build_type(self.cx, path, reg, fields);
      self.builder.push_item(it);

      let it = build_drop(self.cx, path, reg, fields);
      self.builder.push_item(it);

      let it = build_impl(self.cx, path, reg, fields);
      self.builder.push_item(it);
    }
  }
}

fn build_type<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    reg: &node::Reg, _fields: &Vec<node::Field>) -> P<ast::Item>
{
  let packed_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");
  let name = utils::setter_name(cx, path);
  let reg_ty = cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));

  let reg_doc = match reg.docstring {
    Some(d) => token::get_ident(d.node).get().into_string(),
    None => "no documentation".into_string(),
  };
  let docstring = format!("Update value of `{}` register: {}",
                          reg.name.node,
                          reg_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  let item = quote_item!(cx,
    $doc_attr
    #[allow(non_camel_case_types)]
    pub struct $name<'a> {
      value: $packed_ty,
      mask: $packed_ty,
      reg: &'a $reg_ty,
    }
  );
  item.unwrap()
}

fn build_new<'a>(cx: &'a ExtCtxt, path: &Vec<String>)
                 -> P<ast::Item> {
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));
  let setter_ty: P<ast::Ty> = cx.ty_ident(DUMMY_SP,
                                          utils::setter_name(cx, path));
  let item = quote_item!(cx,
    #[doc="Create a new updater"]
    pub fn new(reg: &'a $reg_ty) -> $setter_ty {
      $setter_ty {
        value: 0,
        mask: 0,
        reg: reg,
      }
    });
  item.unwrap()
}

fn build_drop<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    reg: &node::Reg, fields: &Vec<node::Field>) -> P<ast::Item>
{
  let setter_ty: P<ast::Ty> = cx.ty_ident(DUMMY_SP,
                                          utils::setter_name(cx, path));
  let unpacked_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");

  // ensure we don't unintentionally clear a set-to-clear flag
  let mut clear: u32 = 0;
  for f in fields.iter() {
    match f.access {
      node::SetToClear => {
        let mask = 1 << (f.count.node * f.width) - 1;
        clear |= mask;
      },
      _ => {},
    }
  }

  // no need to read write-only registers
  let wo_reg: bool = fields.iter().all(|f| f.access == node::WriteOnly);
  let initial_value =
    if wo_reg {
      quote_expr!(cx, 0)
    } else {
      quote_expr!(cx, self.reg.value.get())
    };

  let item = quote_item!(cx,
    #[unsafe_destructor]
    #[doc = "This performs the register update"]
    impl<'a> Drop for $setter_ty<'a> {
      fn drop(&mut self) {
        let clear_mask: $unpacked_ty = $clear as $unpacked_ty;
        if self.mask != 0 {
          let v: $unpacked_ty = $initial_value & ! clear_mask & ! self.mask;
          self.reg.value.set(self.value | v);
        }
      }
    }
  );
  item.unwrap()
}

fn build_done<'a>(cx: &'a ExtCtxt) -> P<ast::Method>
{
  quote_method!(cx,
    #[doc="Commit changes to register. This is to allow chains of `set_*` \
           invocations to be used as a statement."]
    pub fn done(self) {}
  )
}

fn build_impl<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                  fields: &Vec<node::Field>) -> P<ast::Item>
{
  let new = build_new(cx, path);
  let setter_ty: P<ast::Ty> = cx.ty_ident(
    DUMMY_SP,
    utils::setter_name(cx, path));
  let methods: Vec<P<ast::Method>> =
    FromIterator::from_iter(
      fields.iter()
        .filter_map(|field| build_field_fn(cx, path, reg, field)));
  let done: P<ast::Method> = build_done(cx);
  let impl_ = quote_item!(cx,
    #[allow(dead_code)]
    impl<'a> $setter_ty<'a> {
      $new
      $methods
      $done
    }
    );
  impl_.unwrap()
}

fn build_field_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                      field: &node::Field) -> Option<P<ast::Method>>
{
  match field.access {
    node::ReadOnly => None,
    node::SetToClear => Some(build_field_clear_fn(cx, path, reg, field)),
    _ => Some(build_field_set_fn(cx, path, reg, field)),
  }
}

/// Build a setter for a field
fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg,
                          field: &node::Field) -> P<ast::Method>
{
  let setter_ty = utils::setter_name(cx, path);
  let unpacked_ty = utils::reg_primitive_type(cx, reg)
    .expect("Unexpected non-primitive register");
  let fn_name =
    cx.ident_of((String::from_str("set_")+field.name.node).as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let mask = utils::mask(cx, field);

  let field_doc = match field.docstring {
    Some(d) => token::get_ident(d.node).get().into_string(),
    None => "no documentation".into_string(),
  };
  let docstring = format!("Set value of `{}` field: {}",
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  if field.count.node == 1 {
    let shift = utils::shift(cx, None, field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, new_value: $field_ty)
          -> &'b mut $setter_ty<'a> {
        self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  } else {
    let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, idx: uint, new_value: $field_ty)
          -> &'b mut $setter_ty<'a> {
        self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  }
}

fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
    _: &node::Reg, field: &node::Field) -> P<ast::Method>
{
  let setter_ty = utils::setter_name(cx, path);
  let fn_name =
    cx.ident_of((String::from_str("clear_")+field.name.node).as_slice());
  let mask = utils::mask(cx, field);

  let field_doc = match field.docstring {
    Some(d) => token::get_ident(d.node).get().into_string(),
    None => "no documentation".into_string(),
  };
  let docstring = format!("Clear `{}` flag: {}",
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  if field.count.node == 1 {
    let shift = utils::shift(cx, None, field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self) -> &'b mut $setter_ty<'a> {
        self.value |= $mask << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  } else {
    let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field);
    quote_method!(cx,
      $doc_attr
      pub fn $fn_name<'b>(&'b mut self, idx: uint) -> &'b mut $setter_ty<'a> {
        self.value |= $mask << $shift;
        self.mask |= $mask << $shift;
        self
      }
    )
  }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::result::Result as StdResult;

type Result<T> = StdResult<T, Box<dyn StdError>>;

use chainerror::*;
use std::io::BufRead;
use std::{thread, time};
use varlink::Connection;

fn run_self_test(address: String, multiplex: bool) -> Result<()> {
    let server_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = crate::run_server(&server_address, 4, multiplex) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    {
        let con = Connection::with_address(&address)
            .map_err(mstrerr!("Could not connect to {}", address))?;

        let mut conn = con.write().unwrap();
        let mut writer = conn.writer.take().unwrap();
        let mut reader = conn.reader.take().unwrap();

        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\0"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(r#"{"parameters":{"pong":"ping"}}"#, "\0").as_bytes();

            assert!(reader.read_until(0, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }

        {
            let mut inbuf = Vec::new();
            let reply = "{}\0".as_bytes();

            assert!(writer
                .write_all(
                    concat!(
                        r#"{"method" : "org.example.ping.Upgrade", "upgrade" : true}"#,
                        "\0"
                    )
                    .as_bytes(),
                )
                .is_ok());
            assert!(writer.flush().is_ok());

            assert!(reader.read_until(0, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(
                r#"server reply: {"method" : "org.example.ping.Ping", "#,
                r#""parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            assert!(reader.read_until(0x0a, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\nEnd\n"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(
                r#"server reply: {"method" : "org.example.ping.Ping", "#,
                r#""parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            assert!(reader.read_until(0x0a, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
    }

    {
        let con = Connection::with_address(&address)
            .map_err(mstrerr!("Could not connect to {}", address))?;

        let ret = crate::run_client(&con);
        if let Err(e) = ret {
            panic!("error: {:#?}", e);
        }
    }
    eprintln!("run_client finished");

    if let Err(_) = child.join() {
        Err(strerr!("Error joining thread").into())
    } else {
        Ok(())
    }
}

#[cfg(target_os = "linux")]
#[test]
fn test_unix_multiplex() -> Result<()> {
    run_self_test("unix:org.example.ping_multiplex".into(), true)
}

#[test]
fn test_unix() -> Result<()> {
    run_self_test("unix:org.example.ping".into(), false)
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:127.0.0.1:12345".into(), false)
}
<commit_msg>examples/ping: disable test_unix_multiplex()<commit_after>use std::error::Error as StdError;
use std::result::Result as StdResult;

type Result<T> = StdResult<T, Box<dyn StdError>>;

use chainerror::*;
use std::io::BufRead;
use std::{thread, time};
use varlink::Connection;

fn run_self_test(address: String, multiplex: bool) -> Result<()> {
    let server_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = crate::run_server(&server_address, 4, multiplex) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    {
        let con = Connection::with_address(&address)
            .map_err(mstrerr!("Could not connect to {}", address))?;

        let mut conn = con.write().unwrap();
        let mut writer = conn.writer.take().unwrap();
        let mut reader = conn.reader.take().unwrap();

        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\0"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(r#"{"parameters":{"pong":"ping"}}"#, "\0").as_bytes();

            assert!(reader.read_until(0, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }

        {
            let mut inbuf = Vec::new();
            let reply = "{}\0".as_bytes();

            assert!(writer
                .write_all(
                    concat!(
                        r#"{"method" : "org.example.ping.Upgrade", "upgrade" : true}"#,
                        "\0"
                    )
                    .as_bytes(),
                )
                .is_ok());
            assert!(writer.flush().is_ok());

            assert!(reader.read_until(0, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(
                r#"server reply: {"method" : "org.example.ping.Ping", "#,
                r#""parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            assert!(reader.read_until(0x0a, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
        {
            let br = concat!(
                r#"{"method" : "org.example.ping.Ping", "parameters": { "ping": "ping" }}"#,
                "\nEnd\n"
            )
            .as_bytes();

            let a = &br[0..10];
            let b = &br[10..20];
            let c = &br[20..];

            for i in vec![a, b, c] {
                assert!(writer.write_all(i).is_ok());
                assert!(writer.flush().is_ok());
                thread::sleep(time::Duration::from_millis(500));
            }

            let mut inbuf = Vec::new();
            let reply = concat!(
                r#"server reply: {"method" : "org.example.ping.Ping", "#,
                r#""parameters": { "ping": "ping" }}"#,
                "\n"
            )
            .as_bytes();

            assert!(reader.read_until(0x0a, &mut inbuf).is_ok());
            eprintln!("Got reply: {}", String::from_utf8_lossy(&inbuf));
            assert_eq!(inbuf, reply);
        }
    }

    {
        let con = Connection::with_address(&address)
            .map_err(mstrerr!("Could not connect to {}", address))?;

        let ret = crate::run_client(&con);
        if let Err(e) = ret {
            panic!("error: {:#?}", e);
        }
    }
    eprintln!("run_client finished");

    if let Err(_) = child.join() {
        Err(strerr!("Error joining thread").into())
    } else {
        Ok(())
    }
}

#[cfg(target_os = "not_working")]
#[test]
fn test_unix_multiplex() -> Result<()> {
    run_self_test("unix:org.example.ping_multiplex".into(), true)
}

#[test]
fn test_unix() -> Result<()> {
    run_self_test("unix:org.example.ping".into(), false)
}

#[test]
fn test_tcp() -> Result<()> {
    run_self_test("tcp:127.0.0.1:12345".into(), false)
}
<|endoftext|>


<commit_before>// Copyright 2015-2018 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

use cortex::backend::Backend;
use cortex::models::Corpus;
use regex::Regex;
use std::env;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use Archive::*;

/// Reads a lit of arXiv ids given on input, and packages the respective `CorTeX` entries into a
/// new sandbox.
fn main() {
  // Read input arguments
  let mut input_args = env::args();
  let _ = input_args.next(); // skip process name
  let ids_filepath = match input_args.next() {
    Some(path) => path,
    None => "arxiv_ids.txt".to_string(),
  };
  let sandbox_path = match input_args.next() {
    Some(path) => path,
    None => "sandbox.zip".to_string(),
  };

  // Fish out the arXiv root directory from CorTeX
  let backend = Backend::default();
  let sandbox_start = time::get_time();
  let corpus = match Corpus::find_by_name("arXMLiv", &backend.connection) {
    Ok(corpus) => corpus,
    _ => {
      println!("--  The arXMLiv corpus isn't registered in the CorTeX backend, aborting.");
      return;
    },
  };
  let corpus_path = corpus.path;
  println!("-- using arXiv path: {:?}", corpus_path);

  // Prepare to read in the arXiv ids we will sandbox
  let ids_fh = match File::open(&ids_filepath) {
    Ok(fh) => fh,
    _ => {
      println!(
        "-- Couldn't read file with arXiv ids {:?}, aborting.",
        ids_filepath
      );
      return;
    },
  };

  // Prepare a sandbox archive file writer
  let mut sandbox_writer = Writer::new()
    .unwrap()
    .set_compression(ArchiveFilter::None)
    .set_format(ArchiveFormat::Zip);
  sandbox_writer.open_filename(&sandbox_path).unwrap();

  // Read in ids, and whenever a source exists, write it to the sandbox archive
  let reader = BufReader::new(&ids_fh);
  let no_version = Regex::new(r"v\d+$").unwrap();
  let old_style = Regex::new(r"^([^/]+)/(\d\d\d\d)(.+)$").unwrap();
  let new_style = Regex::new(r"^(\d\d\d\d)\.(.+)$").unwrap();

  let mut counter = 0;

  for line in reader.lines() {
    let mut id = line.unwrap();
    id = no_version.replace(&id, "").to_string();
    // We have two styles of ids:
    //   - old, such as "cond-mat/0306509", which map to ""
    //   - new, such as "1511.03528", which map to "/rootpath/idmonth/id/id.zip"
    let entry = match old_style.captures(&id) {
      None => {
        match new_style.captures(&id) {
          None => {
            println!("-- Malformed arxiv id: {:?}", id);
            None
          },
          Some(caps) => {
            // Obtain new-style entry path
            let month = caps.get(1).unwrap().as_str();
            let paper = caps.get(0).unwrap().as_str();
            Some(month.to_owned() + "/" + paper + "/" + paper + ".zip")
          },
        }
      },
      Some(caps) => {
        // Obtain old-style entry path
        let month = caps.get(2).unwrap().as_str();
        let paper =
          caps.get(1).unwrap().as_str().to_owned() + month + caps.get(3).unwrap().as_str();
        Some(month.to_owned() + "/" + &paper + "/" + &paper + ".zip")
      },
    };
    if entry.is_none() {
      continue;
    }
    let relative_entry_path = entry.unwrap();
    let entry_path = corpus_path.clone() + "/" + &relative_entry_path;
    match File::open(entry_path) {
      Err(_) => println!("-- missing arXiv source for {:?}", id),
      Ok(mut entry_fh) => {
        let mut buffer = Vec::new();
        if entry_fh.read_to_end(&mut buffer).is_ok() {
          // Everything looks ok with this paper, adding it to the sandbox:
          counter += 1;
          match sandbox_writer.write_header_new(&relative_entry_path, buffer.len() as i64) {
            Ok(_) => {},
            Err(e) => {
              println!("Couldn't write header {:?}: {:?}", relative_entry_path, e);
              continue;
            },
          };
          match sandbox_writer.write_data(buffer) {
            Ok(_) => {},
            Err(e) => println!(
              "Failed to write data to {:?} because {:?}",
              relative_entry_path.clone(),
              e
            ),
          };
        }
      },
    };
  }

  let sandbox_end = time::get_time();
  let sandbox_duration = (sandbox_end - sandbox_start).num_milliseconds();
  println!(
    "-- Sandboxing {:?} arXiv papers took took {:?}ms",
    counter, sandbox_duration
  );
}
<commit_msg>lowercase name<commit_after>// Copyright 2015-2018 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.

use cortex::backend::Backend;
use cortex::models::Corpus;
use regex::Regex;
use std::env;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;
use Archive::*;

/// Reads a lit of arXiv ids given on input, and packages the respective `CorTeX` entries into a
/// new sandbox.
fn main() {
  // Read input arguments
  let mut input_args = env::args();
  let _ = input_args.next(); // skip process name
  let ids_filepath = match input_args.next() {
    Some(path) => path,
    None => "arxiv_ids.txt".to_string(),
  };
  let sandbox_path = match input_args.next() {
    Some(path) => path,
    None => "sandbox.zip".to_string(),
  };

  // Fish out the arXiv root directory from CorTeX
  let backend = Backend::default();
  let sandbox_start = time::get_time();
  let corpus = match Corpus::find_by_name("arxmliv", &backend.connection) {
    Ok(corpus) => corpus,
    _ => {
      println!("--  The arXMLiv corpus isn't registered in the CorTeX backend, aborting.");
      return;
    },
  };
  let corpus_path = corpus.path;
  println!("-- using arXiv path: {:?}", corpus_path);

  // Prepare to read in the arXiv ids we will sandbox
  let ids_fh = match File::open(&ids_filepath) {
    Ok(fh) => fh,
    _ => {
      println!(
        "-- Couldn't read file with arXiv ids {:?}, aborting.",
        ids_filepath
      );
      return;
    },
  };

  // Prepare a sandbox archive file writer
  let mut sandbox_writer = Writer::new()
    .unwrap()
    .set_compression(ArchiveFilter::None)
    .set_format(ArchiveFormat::Zip);
  sandbox_writer.open_filename(&sandbox_path).unwrap();

  // Read in ids, and whenever a source exists, write it to the sandbox archive
  let reader = BufReader::new(&ids_fh);
  let no_version = Regex::new(r"v\d+$").unwrap();
  let old_style = Regex::new(r"^([^/]+)/(\d\d\d\d)(.+)$").unwrap();
  let new_style = Regex::new(r"^(\d\d\d\d)\.(.+)$").unwrap();

  let mut counter = 0;

  for line in reader.lines() {
    let mut id = line.unwrap();
    id = no_version.replace(&id, "").to_string();
    // We have two styles of ids:
    //   - old, such as "cond-mat/0306509", which map to ""
    //   - new, such as "1511.03528", which map to "/rootpath/idmonth/id/id.zip"
    let entry = match old_style.captures(&id) {
      None => {
        match new_style.captures(&id) {
          None => {
            println!("-- Malformed arxiv id: {:?}", id);
            None
          },
          Some(caps) => {
            // Obtain new-style entry path
            let month = caps.get(1).unwrap().as_str();
            let paper = caps.get(0).unwrap().as_str();
            Some(month.to_owned() + "/" + paper + "/" + paper + ".zip")
          },
        }
      },
      Some(caps) => {
        // Obtain old-style entry path
        let month = caps.get(2).unwrap().as_str();
        let paper =
          caps.get(1).unwrap().as_str().to_owned() + month + caps.get(3).unwrap().as_str();
        Some(month.to_owned() + "/" + &paper + "/" + &paper + ".zip")
      },
    };
    if entry.is_none() {
      continue;
    }
    let relative_entry_path = entry.unwrap();
    let entry_path = corpus_path.clone() + "/" + &relative_entry_path;
    match File::open(entry_path) {
      Err(_) => println!("-- missing arXiv source for {:?}", id),
      Ok(mut entry_fh) => {
        let mut buffer = Vec::new();
        if entry_fh.read_to_end(&mut buffer).is_ok() {
          // Everything looks ok with this paper, adding it to the sandbox:
          counter += 1;
          match sandbox_writer.write_header_new(&relative_entry_path, buffer.len() as i64) {
            Ok(_) => {},
            Err(e) => {
              println!("Couldn't write header {:?}: {:?}", relative_entry_path, e);
              continue;
            },
          };
          match sandbox_writer.write_data(buffer) {
            Ok(_) => {},
            Err(e) => println!(
              "Failed to write data to {:?} because {:?}",
              relative_entry_path.clone(),
              e
            ),
          };
        }
      },
    };
  }

  let sandbox_end = time::get_time();
  let sandbox_duration = (sandbox_end - sandbox_start).num_milliseconds();
  println!(
    "-- Sandboxing {:?} arXiv papers took took {:?}ms",
    counter, sandbox_duration
  );
}
<|endoftext|>


<commit_before>extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate darling;

use syn::{Ident, Type};

use darling::{ast, util, FromDeriveInput};
use proc_macro::TokenStream;

#[derive(Debug, FromField)]
#[darling(attributes(dummy))]
struct DummyField {
    ident: Option<Ident>,
    ty: Type,
    #[darling(default)]
    faker: Option<String>,
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(dummy), supports(struct_named))]
struct Dummy {
    ident: Ident,
    data: ast::Data<util::Ignored, DummyField>,
}

#[proc_macro_derive(Dummy, attributes(dummy))]
pub fn hello_world(input: TokenStream) -> TokenStream {
    let parsed = syn::parse(input).unwrap();
    let receiver = Dummy::from_derive_input(&parsed).unwrap();

    let struct_name = &receiver.ident;
    let expanded = match receiver.data {
        darling::ast::Data::Struct(darling::ast::Fields { ref fields, .. }) => {
            let struct_fields: Vec<_> = fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();;

            let let_statements: Vec<_> = fields
                .iter()
                .map(|f| {
                    let field_name = f.ident.as_ref().unwrap();
                    let field_ty = &f.ty;
                    let faker = if let Some(ref expr) = f.faker {
                        syn::parse_str::<syn::Expr>(expr).unwrap()
                    } else {
                        syn::parse_str::<syn::Expr>(&"fake::Faker").unwrap()
                    };
                    quote! {
                        let #field_name: #field_ty = (#faker).fake_with_rng(rng);
                    }
                })
                .collect();;

            let impl_dummy = quote! {
                impl fake::Dummy<fake::Faker> for #struct_name {
                    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &fake::Faker, rng: &mut R) -> Self {
                        #(#let_statements)*
                        #struct_name {
                            #(#struct_fields),*
                        }
                    }
                }
            };
            impl_dummy
        }
        _ => panic!("Dummy custom derive is not implemented for union or enum type."),
    };
    expanded.into()
}
<commit_msg>fix trailing comma<commit_after>extern crate proc_macro;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate darling;

use syn::{Ident, Type};

use darling::{ast, util, FromDeriveInput};
use proc_macro::TokenStream;

#[derive(Debug, FromField)]
#[darling(attributes(dummy))]
struct DummyField {
    ident: Option<Ident>,
    ty: Type,
    #[darling(default)]
    faker: Option<String>,
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(dummy), supports(struct_named))]
struct Dummy {
    ident: Ident,
    data: ast::Data<util::Ignored, DummyField>,
}

#[proc_macro_derive(Dummy, attributes(dummy))]
pub fn hello_world(input: TokenStream) -> TokenStream {
    let parsed = syn::parse(input).unwrap();
    let receiver = Dummy::from_derive_input(&parsed).unwrap();

    let struct_name = &receiver.ident;
    let expanded = match receiver.data {
        darling::ast::Data::Struct(darling::ast::Fields { ref fields, .. }) => {
            let struct_fields: Vec<_> = fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();

            let let_statements: Vec<_> = fields
                .iter()
                .map(|f| {
                    let field_name = f.ident.as_ref().unwrap();
                    let field_ty = &f.ty;
                    let faker = if let Some(ref expr) = f.faker {
                        syn::parse_str::<syn::Expr>(expr).unwrap()
                    } else {
                        syn::parse_str::<syn::Expr>(&"fake::Faker").unwrap()
                    };
                    quote! {
                        let #field_name: #field_ty = (#faker).fake_with_rng(rng);
                    }
                })
                .collect();

            let impl_dummy = quote! {
                impl fake::Dummy<fake::Faker> for #struct_name {
                    fn dummy_with_rng<R: rand::Rng + ?Sized>(_: &fake::Faker, rng: &mut R) -> Self {
                        #(#let_statements)*
                        #struct_name {
                            #(#struct_fields),*
                        }
                    }
                }
            };
            impl_dummy
        }
        _ => panic!("Dummy custom derive is not implemented for union or enum type."),
    };
    expanded.into()
}
<|endoftext|>


<commit_before>use std::{ops, cmp, fmt, str, error};
use std::marker::Copy;

use super::num::bigint::BigInt;

/// Represents currency through an optional symbol and amount of coin.
///
/// Every 100 coins results in a banknote. (100 is formatted as 1.00)
/// The currency will be formatted as such: `Currency(Some('$'), 432)` ==> "$4.32"
#[derive(Debug)]
pub struct Currency {
    symbol: Option<char>,
    coin: BigInt
}

impl Currency {
    /// Creates a blank Currency with no symbol and 0 coin.
    ///
    /// # Examples
    /// ```
    /// extern crate currency;
    /// use currency::Currency;
    ///
    /// let mut c = Currency::new();
    /// ```
    pub fn new() -> Currency {
        Currency {
            symbol: None,
            coin: BigInt::zero()
        }
    }
}

/// Allows any Currency to be displayed as a String. The format includes no comma delimiting with a
/// two digit precision decimal.
///
/// # Examples
/// ```
/// use currency::Currency;
///
/// assert!(Currency(Some('$'), 1210).to_string() == "$12.10");
/// assert!(Currency(None, 1210).to_string() == "12.10");
///
/// println!("{}", Currency(Some('$'), 100099));
/// ```
/// The last line prints:
/// ```text
/// "$1000.99"
/// ```
impl fmt::Display for Currency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let decimal = format!("{:.2}", (self.1 as f32 / 100.0));
        match self.0 {
            Some(c) => write!(f, "{}{}", c, decimal),
            None    => write!(f, "{}", decimal),
        }
    }
}

impl str::FromStr for Currency {
    type Err = ParseCurrencyError;

    /// Uses a Regular Expression to parse a string literal (&str) and attempts to turn it into a
    /// currency. Returns `Some(Currency)` on a successful conversion, otherwise `None`.
    ///
    /// If the currency is intended to be a negative amount, ensure the '-' is the first character
    /// in the string.
    /// The Regex recognizes European notation (€1,00)
    ///
    /// # Examples
    /// ```
    /// use currency::Currency;
    ///
    /// assert!(Currency::from_string("$4.32")  == Some(Currency(Some('$'), 432)));
    /// assert!(Currency::from_string("-$4.32") == Some(Currency(Some('$'), -432)));
    /// assert!(Currency::from_string("424.44") == Some(Currency(None, 42444)));
    /// assert!(Currency::from_string("£12,00") == Some(Currency(Some('£'), 1200)));
    /// assert!(Currency::from_string("¥12")    == Some(Currency(Some('¥'), 1200)));
    /// ```
    fn from_str(s: &str) -> Result<Currency, ParseCurrencyError> {
        use regex::Regex;

        // Shadow s with a trimmed version
        let s = s.trim();
        let re =
        Regex::new(r"(?:\b|(-)?)(\p{Sc})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b")
        .unwrap();

        if !re.is_match(s) {
            return None;
        }

        // Used to negate the final result if the regex matches a negative
        let mut multiplier = 1;
        let mut sign: Option<char> = None;
        let mut coin_str: String = "".to_string();

        // If anyone's looking at this and knows how to do this without a loop, fork this.
        for cap in re.captures_iter(s) {
            if cap.at(0).unwrap_or("") != s {
                return None;
            }

            if cap.at(1).is_some() {
                multiplier = -1;
            }

            if cap.at(2).is_some() {
                if multiplier < 0 {
                    sign = Some(s.chars().skip(1).next().unwrap());
                } else {
                    sign = Some(s.chars().next().unwrap());
                }
            }
            coin_str = cap.at(3).unwrap().replace(".", "").replace(",", "")
            + cap.at(4).unwrap_or("00");

            break;
        }

        if let Ok(coin) = coin_str.parse::<i64>(){
            return Some(Currency(sign, multiplier * coin));
        }
        None
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct ParseCurrencyError;

impl error::Error for ParseCurrencyError {
    fn description(&self) -> &str {
        "failed to parse currency"
    }
}

/// Identical to the implementation of Display, but replaces the "." with a ",". Access this
/// formating by using "{:e}".
///
/// # Examples
/// ```
/// use currency::Currency;
///
/// println!("{:e}", Currency(Some('£'), 100099));
/// ```
/// The last line prints the following:
/// ```text
/// "£1000,99"
/// ```
impl fmt::LowerExp for Currency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", format!("{}", self).replace(".", ","))
    }
}

/// Overloads the '==' operator for Currency objects.
///
/// # Panics
/// Panics if the two comparators are different types of currency, as denoted by the Currency's
/// symbol.
impl PartialEq<Currency> for Currency {
    fn eq(&self, rhs: &Currency) -> bool {
        self.0 == rhs.0 && self.1 == rhs.1
    }

    fn ne(&self, rhs: &Currency) -> bool {
        self.0 != rhs.0 || self.1 != rhs.1
    }
}

/// Overloads the order operators for Currency objects.
///
/// These operators include '<', '<=', '>', and '>='.
///
/// # Panics
/// Panics if the two comparators are different types of currency, as denoted by
/// the Currency's symbol.
impl PartialOrd<Currency> for Currency {
    fn partial_cmp(&self, rhs: &Currency) -> Option<cmp::Ordering> {
        if self.symbol == rhs.symbol {
            self.coin.partial_cmp(rhs.coin)
        }
        None
    }

    fn lt(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.lt(rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn le(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.le(rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn gt(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.gt(rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn ge(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.ge(rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }
}

/// Overloads the '+' operator for Currency objects.
///
/// # Panics
/// Panics if the two addends are different types of currency, as denoted by the Currency's symbol.
impl Add for Currency {
    type Output = Currency;

    fn add(self, rhs: Currency) -> Currency {
        if self.0 == rhs.0 {
            Currency(self.0, self.1 + rhs.1)
        } else {
            panic!("Cannot add two different types of currency!");
        }
    }
}

/// Overloads the '-' operator for Currency objects.
///
/// # Panics
/// Panics if the minuend and subtrahend are two different types of currency, as denoted by the
/// Currency's symbol.
impl Sub for Currency {
    type Output = Currency;

    fn sub(self, rhs: Currency) -> Currency {
        if self.0 == rhs.0 {
            Currency(self.0, self.1 - rhs.1)
        } else {
            panic!("Cannot subtract two different types of currency!");
        }
    }
}

/// Overloads the '*' operator for Currency objects.
///
/// Allows a Currency to be multiplied by an i64.
impl Mul<i64> for Currency {
    type Output = Currency;

    fn mul(self, rhs: i64) -> Currency {
        Currency(self.0, self.1 * rhs)
    }
}

/// Overloads the '*' operator for i64.
///
/// Allows an i64 to be multiplied by a Currency.
/// Completes the commutative property for i64 multiplied by Currency.
impl Mul<Currency> for i64 {
    type Output = Currency;

    fn mul(self, rhs: Currency) -> Currency {
        Currency(rhs.0, rhs.1 * self)
    }
}

/// Overloads the '/' operator for Currency objects.
///
/// Allows a Currency to be divided by an i64.
impl Div<i64> for Currency {
    type Output = Currency;

    fn div(self, rhs: i64) -> Currency {
        Currency(self.0, self.1 / rhs)
    }
}

/// Allows Currencies to be copied, rather than using move semantics.
impl Copy for Currency { }
impl Clone for Currency {
    fn clone(&self) -> Currency { *self }
}

// TODO
// - neg
// - rem
// - hash
<commit_msg>compiles, but not all functionality exists... need more ops traits and from_str<commit_after>use std::{ops, cmp, fmt, str, error};
use std::marker::Copy;

use super::num::bigint::BigInt;
use super::num::Zero;

/// Represents currency through an optional symbol and amount of coin.
///
/// Every 100 coins results in a banknote. (100 is formatted as 1.00)
/// The currency will be formatted as such: `Currency(Some('$'), 432)` ==> "$4.32"
#[derive(Debug, Clone)]
pub struct Currency {
    symbol: Option<char>,
    coin: BigInt
}

impl Currency {
    /// Creates a blank Currency with no symbol and 0 coin.
    ///
    /// # Examples
    /// ```
    /// extern crate currency;
    /// use currency::Currency;
    ///
    /// let mut c = Currency::new();
    /// ```
    pub fn new() -> Currency {
        Currency {
            symbol: None,
            coin: BigInt::zero()
        }
    }

    // TODO
    // - to_str with comma delimiting
    // - to_str with euro delimiting
}

/// Allows any Currency to be displayed as a String. The format includes no comma delimiting with a
/// two digit precision decimal.
///
/// # Formats
///
/// ## Arguments
///
/// `#` display commas
///
/// ## Examples
///
/// {} => No commas, rounded to nearest dollar.
/// {:#} => Commas, rounded to nearest dollar.
/// {:#.2} => Commas, with decimal point. (values greater than two will route to this fmt as well)
/// {:.1} => No commas, rounded to nearest ten cents.
///
/// # Examples
/// ```
/// use currency::Currency;
///
/// assert!(Currency(Some('$'), 1210).to_string() == "$12.10");
/// assert!(Currency(None, 1210).to_string() == "12.10");
///
/// println!("{:#}", Currency(Some('$'), 100099)); // $1,000
/// println!("{:.2}", Currency(Some('$'), 100099)); //
/// println!("{:.1}", Currency(Some('$'), 100099));
/// println!("{:.0}", Currency(Some('$'), 100099)); //
/// ```
/// The last line prints:
/// ```text
/// "$1000.99"
/// ```
impl fmt::Display for Currency { // TODO TODO TODO TODO
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let one_hundred = BigInt::from(100);
        // TODO cases
        let cents = &self.coin % one_hundred;
        let dollars = &self.coin - &cents;
        match self.symbol {
            Some(c) => write!(f, "{}{}.{}", c, dollars, cents),
            None    => write!(f, "{}.{}", dollars, cents),
        }
    }
}

// impl str::FromStr for Currency {
//     type Err = ParseCurrencyError;
//
//     /// Uses a Regular Expression to parse a string literal (&str) and attempts to turn it into a
//     /// currency. Returns `Some(Currency)` on a successful conversion, otherwise `None`.
//     ///
//     /// If the currency is intended to be a negative amount, ensure the '-' is the first character
//     /// in the string.
//     /// The Regex recognizes European notation (€1,00)
//     ///
//     /// # Examples
//     /// ```
//     /// use currency::Currency;
//     ///
//     /// assert!(Currency::from_string("$4.32")  == Some(Currency(Some('$'), 432)));
//     /// assert!(Currency::from_string("-$4.32") == Some(Currency(Some('$'), -432)));
//     /// assert!(Currency::from_string("424.44") == Some(Currency(None, 42444)));
//     /// assert!(Currency::from_string("£12,00") == Some(Currency(Some('£'), 1200)));
//     /// assert!(Currency::from_string("¥12")    == Some(Currency(Some('¥'), 1200)));
//     /// ```
//     fn from_str(s: &str) -> Result<Currency, ParseCurrencyError> {
//         use regex::Regex;
//
//         // Shadow s with a trimmed version
//         let s = s.trim();
//         let re =
//         Regex::new(r"(?:\b|(-)?)(\p{Sc})?((?:(?:\d{1,3}[\.,])+\d{3})|\d+)(?:[\.,](\d{2}))?\b")
//         .unwrap();
//
//         if !re.is_match(s) {
//             return None;
//         }
//
//         // Used to negate the final result if the regex matches a negative
//         let mut multiplier = 1;
//         let mut sign: Option<char> = None;
//         let mut coin_str: String = "".to_string();
//
//         // If anyone's looking at this and knows how to do this without a loop, fork this.
//         for cap in re.captures_iter(s) {
//             if cap.at(0).unwrap_or("") != s {
//                 return None;
//             }
//
//             if cap.at(1).is_some() {
//                 multiplier = -1;
//             }
//
//             if cap.at(2).is_some() {
//                 if multiplier < 0 {
//                     sign = Some(s.chars().skip(1).next().unwrap());
//                 } else {
//                     sign = Some(s.chars().next().unwrap());
//                 }
//             }
//             coin_str = cap.at(3).unwrap().replace(".", "").replace(",", "")
//             + cap.at(4).unwrap_or("00");
//
//             break;
//         }
//
//         if let Ok(coin) = coin_str.parse::<i64>(){
//             return Some(Currency(sign, multiplier * coin));
//         }
//         None
//     }
// }

#[derive(Debug, Clone, PartialEq)]
pub struct ParseCurrencyError {
    source: String
}

impl fmt::Display for ParseCurrencyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Could not parse {} into a currency.", self.source)
    }
}

impl error::Error for ParseCurrencyError {
    fn description(&self) -> &str {
        "Failed to parse currency"
    }
}

/// Identical to the implementation of Display, but replaces the "." with a ",". Access this
/// formating by using "{:e}".
///
/// # Examples
/// ```
/// use currency::Currency;
///
/// println!("{:e}", Currency(Some('£'), 100099));
/// ```
/// The last line prints the following:
/// ```text
/// "£1000,99"
/// ```
impl fmt::LowerExp for Currency {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", format!("{}", self).replace(".", ","))
    }
}

/// Overloads the '==' operator for Currency objects.
///
/// # Panics
/// Panics if the two comparators are different types of currency, as denoted by the Currency's
/// symbol.
impl PartialEq<Currency> for Currency {
    fn eq(&self, rhs: &Currency) -> bool {
        self.symbol == rhs.symbol && self.coin == rhs.coin
    }

    fn ne(&self, rhs: &Currency) -> bool {
        self.symbol != rhs.symbol || self.coin != rhs.coin
    }
}

/// Overloads the order operators for Currency objects.
///
/// These operators include '<', '<=', '>', and '>='.
///
/// # Panics
/// Panics if the two comparators are different types of currency, as denoted by
/// the Currency's symbol.
impl PartialOrd<Currency> for Currency {
    fn partial_cmp(&self, rhs: &Currency) -> Option<cmp::Ordering> {
        if self.symbol == rhs.symbol {
            self.coin.partial_cmp(&rhs.coin)
        } else {
            None
        }
    }

    fn lt(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.lt(&rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn le(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.le(&rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn gt(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.gt(&rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }

    fn ge(&self, rhs: &Currency) -> bool {
        if self.symbol == rhs.symbol {
            self.coin.ge(&rhs.coin)
        } else {
            panic!("Cannot compare two different types of currency.");
        }
    }
}

/// Overloads the '+' operator for Currency objects.
///
/// # Panics
/// Panics if the two addends are different types of currency, as denoted by the Currency's symbol.
impl ops::Add for Currency {
    type Output = Currency;

    fn add(self, rhs: Currency) -> Currency {
        if self.symbol == rhs.symbol {
            Currency {
                symbol: self.symbol,
                coin: self.coin.add(rhs.coin)
            }
        } else {
            panic!("Cannot add two different types of currency.");
        }
    }
}

/// Overloads the '-' operator for Currency objects.
///
/// # Panics
/// Panics if the minuend and subtrahend are two different types of currency, as denoted by the
/// Currency's symbol.
impl ops::Sub for Currency {
    type Output = Currency;

    fn sub(self, rhs: Currency) -> Currency {
        if self.symbol == rhs.symbol {
            Currency {
                symbol: self.symbol,
                coin: self.coin.sub(rhs.coin)
            }
        } else {
            panic!("Cannot subtract two different types of currency.");
        }
    }
}

/// Overloads the '*' operator for Currency objects.
///
/// Allows a Currency to be multiplied by an i64.
impl ops::Mul<i64> for Currency {
    type Output = Currency;

    fn mul(self, rhs: i64) -> Currency {
        Currency {
            symbol: self.symbol,
            coin: self.coin.mul(BigInt::from(rhs))
        }
    }
}
// TODO mul for each num type, both ways

/// Overloads the '*' operator for Currency objects.
///
/// Allows a Currency to be multiplied by an i64.
impl ops::Mul<Currency> for Currency {
    type Output = Currency;

    fn mul(self, rhs: Currency) -> Currency {
        if self.symbol == rhs.symbol {
            Currency {
                symbol: self.symbol,
                coin: self.coin.mul(rhs.coin)
            }
        } else {
            panic!("Cannot multiply two different types of currency.");
        }
    }
}

// TODO
// - neg
// - rem
// - hash
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use super::functions::sql_function;
use super::{is_aggregate, AsExpression};
use super::{Expression, ValidGrouping};
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};
use crate::backend::Backend;
use crate::{AppearsOnTable, SelectableExpression};

sql_function! {
    /// Creates a SQL `COUNT` expression
    ///
    /// As with most bare functions, this is not exported by default. You can import
    /// it specifically as `diesel::dsl::count`, or glob import
    /// `diesel::dsl::*`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use diesel::dsl::*;
    /// #
    /// # fn main() {
    /// #     use schema::animals::dsl::*;
    /// #     let connection = establish_connection();
    /// assert_eq!(Ok(1), animals.select(count(name)).first(&connection));
    /// # }
    /// ```
    #[aggregate]
    fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](crate::query_dsl::QueryDsl::count())
/// on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_star`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), users.select(count_star()).first(&connection));
/// # }
/// ```
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
#[diesel(aggregate)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(*)");
        Ok(())
    }
}

impl_selectable_expression!(CountStar);

/// Creates a SQL `COUNT(DISTINCT ...)` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_distinct`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::posts::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), posts.select(count_distinct(user_id)).first(&connection));
/// # }
/// ```
pub fn count_distinct<T, E>(expr: E) -> CountDistinct<T, E::Expression>
where
    T: SqlType + SingleValue,
    E: AsExpression<T>,
{
    CountDistinct {
        expr: expr.as_expression(),
        _marker: PhantomData,
    }
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
#[doc(hidden)]
pub struct CountDistinct<T, E> {
    expr: E,
    _marker: PhantomData<T>,
}

impl<T, E> Expression for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    E: Expression,
{
    type SqlType = BigInt;
}

impl<T, E, GB> ValidGrouping<GB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
{
    type IsAggregate = is_aggregate::Yes;
}

impl<T, E, QS> SelectableExpression<QS> for CountDistinct<T, E>
where
    Self: AppearsOnTable<QS>,
    E: SelectableExpression<QS>,
{
}

impl<T, E, QS> AppearsOnTable<QS> for CountDistinct<T, E>
where
    Self: Expression,
    E: AppearsOnTable<QS>,
{
}

impl<T, E, DB> QueryFragment<DB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    DB: Backend,
    for<'a> &'a E: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(DISTINCT ");
        (&self.expr).walk_ast(out.reborrow())?;
        out.push_sql(")");
        Ok(())
    }
}
<commit_msg>Separate assert and query for readability<commit_after>use std::marker::PhantomData;

use super::functions::sql_function;
use super::{is_aggregate, AsExpression};
use super::{Expression, ValidGrouping};
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};
use crate::backend::Backend;
use crate::{AppearsOnTable, SelectableExpression};

sql_function! {
    /// Creates a SQL `COUNT` expression
    ///
    /// As with most bare functions, this is not exported by default. You can import
    /// it specifically as `diesel::dsl::count`, or glob import
    /// `diesel::dsl::*`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use diesel::dsl::*;
    /// #
    /// # fn main() {
    /// #     use schema::animals::dsl::*;
    /// #     let connection = establish_connection();
    /// assert_eq!(Ok(1), animals.select(count(name)).first(&connection));
    /// # }
    /// ```
    #[aggregate]
    fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](crate::query_dsl::QueryDsl::count())
/// on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_star`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), users.select(count_star()).first(&connection));
/// # }
/// ```
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
#[diesel(aggregate)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(*)");
        Ok(())
    }
}

impl_selectable_expression!(CountStar);

/// Creates a SQL `COUNT(DISTINCT ...)` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_distinct`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::posts::dsl::*;
/// #     let connection = establish_connection();
/// let unique_user_count = posts.select(count_distinct(user_id)).first(&connection);
/// assert_eq!(Ok(2), unique_user_count);
/// # }
/// ```
pub fn count_distinct<T, E>(expr: E) -> CountDistinct<T, E::Expression>
where
    T: SqlType + SingleValue,
    E: AsExpression<T>,
{
    CountDistinct {
        expr: expr.as_expression(),
        _marker: PhantomData,
    }
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
#[doc(hidden)]
pub struct CountDistinct<T, E> {
    expr: E,
    _marker: PhantomData<T>,
}

impl<T, E> Expression for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    E: Expression,
{
    type SqlType = BigInt;
}

impl<T, E, GB> ValidGrouping<GB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
{
    type IsAggregate = is_aggregate::Yes;
}

impl<T, E, QS> SelectableExpression<QS> for CountDistinct<T, E>
where
    Self: AppearsOnTable<QS>,
    E: SelectableExpression<QS>,
{
}

impl<T, E, QS> AppearsOnTable<QS> for CountDistinct<T, E>
where
    Self: Expression,
    E: AppearsOnTable<QS>,
{
}

impl<T, E, DB> QueryFragment<DB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    DB: Backend,
    for<'a> &'a E: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(DISTINCT ");
        (&self.expr).walk_ast(out.reborrow())?;
        out.push_sql(")");
        Ok(())
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove extra padding<commit_after><|endoftext|>


<commit_before>use std;
use std::collections::BTreeMap;
use std::default::Default;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

use digest::Digest;
use ignore::WalkBuilder;
use serde_bytes;
use serde_cbor;
use serde_json;

use sha2;
use sha3;

use error;

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct Database(BTreeMap<PathBuf, Entry>);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Entry {
    File(HashSums),
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSums {
    sha2: HashSum,
    sha3: HashSum,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSum(#[serde(with = "serde_bytes")] Vec<u8>);

#[derive(Default)]
struct Hashers {
    sha2: sha2::Sha256,
    sha3: sha3::Sha3_256,
}

impl Hashers {
    fn input(&mut self, input: &[u8]) {
        self.sha2.input(input);
        self.sha3.input(input);
    }
    fn result(self) -> HashSums {
        HashSums {
            sha2: HashSum(Vec::from(self.sha2.result().as_slice())),
            sha3: HashSum(Vec::from(self.sha3.result().as_slice())),
        }
    }
}

fn compute_hashes<P>(path: P) -> Result<HashSums, error::Error>
where
    P: AsRef<Path>
{
    let mut f = File::open(path)?;

    let mut hashers = Hashers::default();

    let mut buffer = [0; 4096];
    loop {
        let n = f.read(&mut buffer[..])?;
        if n == 0 { break }
        hashers.input(&buffer[0..n]);
    }
    Ok(hashers.result())
}

impl Database {
    pub fn build<P: AsRef<Path>>(path: P) -> Result<Database, error::Error> {
        let mut database = Database::default();
        for entry in WalkBuilder::new(&path).build() {
            let entry = entry?;
            if entry.file_type().map_or(false, |t| t.is_file()) {
                let hashes = compute_hashes(entry.path())?;
                let result = Entry::File(hashes);
                let short_path = entry.path().strip_prefix(&path)?;
                database.0.insert(short_path.to_owned(), result);
            }
        }
        Ok(database)
    }

    pub fn dump_json<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let json = serde_json::to_string(self)?;
        let mut f = File::create(path)?;
        write!(f, "{}", json)?;
        Ok(())
    }

    pub fn dump_cbor<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let cbor = serde_cbor::to_vec(self)?;
        let mut f = File::create(path)?;
        f.write_all(cbor.as_slice())?;
        Ok(())
    }
}

impl std::fmt::Display for Database {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        for (path, entry) in self.0.iter() {
            match entry {
                &Entry::File(ref hashes) => {
                    let hash: Vec<_> = hashes.sha2.0.iter().map(
                        |b| format!("{:02x}", b)).collect();
                    writeln!(f, "{} {}", hash.join(""), Path::new(path).display())?
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Factor out insert function.<commit_after>use std;
use std::collections::BTreeMap;
use std::default::Default;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

use digest::Digest;
use ignore::WalkBuilder;
use serde_bytes;
use serde_cbor;
use serde_json;

use sha2;
use sha3;

use error;

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct Database(BTreeMap<PathBuf, Entry>);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Entry {
    File(HashSums),
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSums {
    sha2: HashSum,
    sha3: HashSum,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSum(#[serde(with = "serde_bytes")] Vec<u8>);

#[derive(Default)]
struct Hashers {
    sha2: sha2::Sha256,
    sha3: sha3::Sha3_256,
}

impl Hashers {
    fn input(&mut self, input: &[u8]) {
        self.sha2.input(input);
        self.sha3.input(input);
    }
    fn result(self) -> HashSums {
        HashSums {
            sha2: HashSum(Vec::from(self.sha2.result().as_slice())),
            sha3: HashSum(Vec::from(self.sha3.result().as_slice())),
        }
    }
}

fn compute_hashes<P>(path: P) -> Result<HashSums, error::Error>
where
    P: AsRef<Path>
{
    let mut f = File::open(path)?;

    let mut hashers = Hashers::default();

    let mut buffer = [0; 4096];
    loop {
        let n = f.read(&mut buffer[..])?;
        if n == 0 { break }
        hashers.input(&buffer[0..n]);
    }
    Ok(hashers.result())
}

impl Database {
    fn insert(&mut self, path: PathBuf, entry: Entry) {
        self.0.insert(path, entry);
    }

    pub fn build<P>(path: P) -> Result<Database, error::Error>
    where
        P: AsRef<Path>
    {
        let mut database = Database::default();
        for entry in WalkBuilder::new(&path).build() {
            let entry = entry?;
            if entry.file_type().map_or(false, |t| t.is_file()) {
                let hashes = compute_hashes(entry.path())?;
                let result = Entry::File(hashes);
                let short_path = entry.path().strip_prefix(&path)?;
                database.insert(short_path.to_owned(), result);
            }
        }
        Ok(database)
    }

    pub fn dump_json<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let json = serde_json::to_string(self)?;
        let mut f = File::create(path)?;
        write!(f, "{}", json)?;
        Ok(())
    }

    pub fn dump_cbor<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let cbor = serde_cbor::to_vec(self)?;
        let mut f = File::create(path)?;
        f.write_all(cbor.as_slice())?;
        Ok(())
    }
}

impl std::fmt::Display for Database {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        for (path, entry) in self.0.iter() {
            match entry {
                &Entry::File(ref hashes) => {
                    let hash: Vec<_> = hashes.sha2.0.iter().map(
                        |b| format!("{:02x}", b)).collect();
                    writeln!(f, "{} {}", hash.join(""), Path::new(path).display())?
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>