<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]

use std::iter::FusedIterator;

use util::*;

/// Plane-specific configuration.
#[derive(Debug, Clone)]
pub struct PlaneConfig {
  pub stride: usize,
  pub alloc_height: usize,
  pub width: usize,
  pub height: usize,
  pub xdec: usize,
  pub ydec: usize,
  pub xorigin: usize,
  pub yorigin: usize
}

/// Absolute offset in pixels inside a plane
#[derive(Debug)]
pub struct PlaneOffset {
  pub x: isize,
  pub y: isize
}

#[derive(Debug, Clone)]
pub struct Plane {
  pub data: Vec<u16>,
  pub cfg: PlaneConfig
}

impl Plane {
  /// Stride alignment in bytes.
  const STRIDE_ALIGNMENT_LOG2: usize = 4;

  /// Data alignment in bytes.
  const DATA_ALIGNMENT_LOG2: usize = 4;

  pub fn new(
    width: usize, height: usize, xdec: usize, ydec: usize, xpad: usize,
    ypad: usize
  ) -> Plane {
    let xorigin = xpad.align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
    let yorigin = ypad;
    let stride = (xorigin + width + xpad)
      .align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
    let alloc_height = yorigin + height + ypad;
    let data = vec![128u16; stride * alloc_height];
    assert!(is_aligned(data.as_ptr(), Plane::DATA_ALIGNMENT_LOG2));
    Plane {
      data,
      cfg: PlaneConfig {
        stride,
        alloc_height,
        width,
        height,
        xdec,
        ydec,
        xorigin,
        yorigin
      }
    }
  }

  pub fn pad(&mut self, w: usize, h: usize) {
    let xorigin = self.cfg.xorigin;
    let yorigin = self.cfg.yorigin;
    let stride = self.cfg.stride;
    let width = w >> self.cfg.xdec;
    let height = h >> self.cfg.ydec;

    if xorigin > 0 {
      for y in 0..height {
        let mut ps = self
          .mut_slice(&PlaneOffset { x: -(xorigin as isize), y: y as isize });
        let s = ps.as_mut_slice_w_width(xorigin + 1);
        let fill_val = s[xorigin];
        for val in s[..xorigin].iter_mut() {
          *val = fill_val;
        }
      }
    }

    if xorigin + width < stride {
      for y in 0..height {
        let mut ps = self
          .mut_slice(&PlaneOffset { x: width as isize - 1, y: y as isize });
        let s = ps.as_mut_slice_w_width(stride - xorigin - width + 1);
        let fill_val = s[0];
        for val in s[1..].iter_mut() {
          *val = fill_val;
        }
      }
    }

    if yorigin > 0 {
      let mut ps = self.mut_slice(&PlaneOffset {
        x: -(xorigin as isize),
        y: -(yorigin as isize)
      });
      let (s1, s2) = ps.as_mut_slice().split_at_mut(yorigin * stride);
      for y in 0..yorigin {
        s1[y * stride..y * stride + stride].copy_from_slice(&s2[..stride]);
      }
    }

    if yorigin + height < self.cfg.alloc_height {
      let mut ps = self.mut_slice(&PlaneOffset {
        x: -(xorigin as isize),
        y: height as isize - 1
      });
      let (s2, s1) = ps.as_mut_slice().split_at_mut(stride);
      for y in 0..yorigin {
        s1[y * stride..y * stride + stride].copy_from_slice(&s2[..stride]);
      }
    }
  }

  pub fn slice<'a>(&'a self, po: &PlaneOffset) -> PlaneSlice<'a> {
    PlaneSlice { plane: self, x: po.x, y: po.y }
  }

  pub fn mut_slice<'a>(&'a mut self, po: &PlaneOffset) -> PlaneMutSlice<'a> {
    PlaneMutSlice { plane: self, x: po.x, y: po.y }
  }

  #[inline]
  fn index(&self, x: usize, y: usize) -> usize {
    (y + self.cfg.yorigin) * self.cfg.stride + (x + self.cfg.xorigin)
  }

  pub fn p(&self, x: usize, y: usize) -> u16 {
    self.data[self.index(x, y)]
  }

  pub fn data_origin(&self) -> &[u16] {
    &self.data[self.index(0, 0)..]
  }

  pub fn data_origin_mut(&mut self) -> &mut [u16] {
    let i = self.index(0, 0);
    &mut self.data[i..]
  }

  pub fn copy_from_raw_u8(
    &mut self, source: &[u8], source_stride: usize, source_bytewidth: usize
  ) {
    let stride = self.cfg.stride;
    for (self_row, source_row) in self
      .data_origin_mut()
      .chunks_mut(stride)
      .zip(source.chunks(source_stride))
    {
      match source_bytewidth {
        1 => for (self_pixel, source_pixel) in
          self_row.iter_mut().zip(source_row.iter())
        {
          *self_pixel = *source_pixel as u16;
        },
        2 => for (self_pixel, bytes) in
          self_row.iter_mut().zip(source_row.chunks(2))
        {
          *self_pixel = (bytes[1] as u16) << 8 | (bytes[0] as u16);
        },

        _ => {}
      }
    }
  }

  pub fn downsample_from(&mut self, src: &Plane) {
    let width = self.cfg.width;
    let height = self.cfg.height;

    assert!(width * 2 == src.cfg.width);
    assert!(height * 2 == src.cfg.height);

    for row in 0..height {
      let mut dst_slice = self.mut_slice(&PlaneOffset{ x: 0, y: row as isize });
      let mut dst = dst_slice.as_mut_slice();

      for col in 0..width {
        let mut sum = 0;
        sum = sum + src.p(2*col, 2*row);
        sum = sum + src.p(2*col+1, 2*row);
        sum = sum + src.p(2*col, 2*row+1);
        sum = sum + src.p(2*col+1, 2*row+1);
        let avg = (sum + 2) >> 2;
        dst[col] = avg;
      }
    }
  }

  /// Iterates over the pixels in the `Plane`, skipping stride data.
  pub fn iter(&self) -> PlaneIter {
    PlaneIter::new(self)
  }
}

#[derive(Debug)]
pub struct PlaneIter<'a> {
  plane: &'a Plane,
  y: usize,
  x: usize,
}

impl<'a> PlaneIter<'a> {
  pub fn new(plane: &'a Plane) -> Self {
    PlaneIter {
      plane,
      y: 0,
      x: 0,
    }
  }

  fn width(&self) -> usize {
    self.plane.cfg.width
  }

  fn height(&self) -> usize {
    self.plane.cfg.height
  }
}

impl<'a> Iterator for PlaneIter<'a> {
  type Item = u16;

  fn next(&mut self) -> Option<<Self as Iterator>::Item> {
    if self.y == self.height() - 1 && self.x == self.width() - 1 {
      return None;
    }
    let pixel = self.plane.p(self.x, self.y);
    if self.x == self.width() - 1 {
      self.x = 0;
      self.y += 1;
    } else {
      self.x += 1;
    }
    Some(pixel)
  }
}

#[derive(Clone, Copy)]
pub struct PlaneSlice<'a> {
  pub plane: &'a Plane,
  pub x: isize,
  pub y: isize
}

pub struct IterWidth<'a> {
    ps: PlaneSlice<'a>,
    width: usize,
}

impl<'a> Iterator for IterWidth<'a> {
    type Item = &'a [u16];

    #[inline]
    fn next(&mut self) -> Option<&'a [u16]> {
        let x = self.ps.plane.cfg.xorigin as isize + self.ps.x;
        let y = self.ps.plane.cfg.yorigin as isize + self.ps.y;
        let stride = self.ps.plane.cfg.stride;
        let base = y as usize * stride + x as usize;

        if self.ps.plane.data.len() < base + self.width {
            None
        } else {
            self.ps.y += 1;
            Some(&self.ps.plane.data[base..base + self.width])
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let size = self.ps.plane.cfg.height - self.ps.y as usize;

        (size, Some(size))
    }
}

impl<'a> ExactSizeIterator for IterWidth<'a> { }

impl<'a> FusedIterator for IterWidth<'a> { }

impl<'a> PlaneSlice<'a> {
  pub fn as_slice(&'a self) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[base..]
  }

  pub fn as_slice_clamped(&'a self) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let y = (self.y.min(self.plane.cfg.height as isize)
      + self.plane.cfg.yorigin as isize)
      .max(0) as usize;
    let x = (self.x.min(self.plane.cfg.width as isize)
      + self.plane.cfg.xorigin as isize)
      .max(0) as usize;
    &self.plane.data[y * stride + x..]
  }

  pub fn as_slice_w_width(&'a self, width: usize) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[base..base + width]
  }

  pub fn iter_width(&self, width: usize) -> IterWidth<'a> {
    IterWidth { ps: *self, width }
  }

  pub fn subslice(&'a self, xo: usize, yo: usize) -> PlaneSlice<'a> {
    PlaneSlice {
      plane: self.plane,
      x: self.x + xo as isize,
      y: self.y + yo as isize
    }
  }

  /// A slice starting i pixels above the current one.
  pub fn go_up(&'a self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
  }

  /// A slice starting i pixels to the left of the current one.
  pub fn go_left(&'a self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
  }

  pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    self.plane.data[new_y * self.plane.cfg.stride + new_x]
  }
}

pub struct PlaneMutSlice<'a> {
  pub plane: &'a mut Plane,
  pub x: isize,
  pub y: isize
}

impl<'a> PlaneMutSlice<'a> {
  pub fn as_mut_slice(&'a mut self) -> &'a mut [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &mut self.plane.data[base..]
  }

  pub fn as_mut_slice_w_width(&'a mut self, width: usize) -> &'a mut [u16] {
    let stride = self.plane.cfg.stride;
    let y = self.y + self.plane.cfg.yorigin as isize;
    let x = self.x + self.plane.cfg.xorigin as isize;
    assert!(y >= 0);
    assert!(x >= 0);
    let base = y as usize * stride + x as usize;
    &mut self.plane.data[base..base + width]
  }

  pub fn offset(&self, add_x: usize, add_y: usize) -> &[u16] {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[new_y * self.plane.cfg.stride + new_x..]
  }

  pub fn offset_as_mutable(
    &'a mut self, add_x: usize, add_y: usize
  ) -> &'a mut [u16] {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    &mut self.plane.data[new_y * self.plane.cfg.stride + new_x..]
  }

  // FIXME: code duplication with PlaneSlice

  /// A slice starting i pixels above the current one.
  pub fn go_up(&'a self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
  }

  /// A slice starting i pixels to the left of the current one.
  pub fn go_left(&'a self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
  }

  pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    self.plane.data[new_y * self.plane.cfg.stride + new_x]
  }
}
<commit_msg>Fix over restrictive borrow rules for plane slice (#846)<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]

use std::iter::FusedIterator;

use util::*;

/// Plane-specific configuration.
#[derive(Debug, Clone)]
pub struct PlaneConfig {
  pub stride: usize,
  pub alloc_height: usize,
  pub width: usize,
  pub height: usize,
  pub xdec: usize,
  pub ydec: usize,
  pub xorigin: usize,
  pub yorigin: usize
}

/// Absolute offset in pixels inside a plane
#[derive(Debug)]
pub struct PlaneOffset {
  pub x: isize,
  pub y: isize
}

#[derive(Debug, Clone)]
pub struct Plane {
  pub data: Vec<u16>,
  pub cfg: PlaneConfig
}

impl Plane {
  /// Stride alignment in bytes.
  const STRIDE_ALIGNMENT_LOG2: usize = 4;

  /// Data alignment in bytes.
  const DATA_ALIGNMENT_LOG2: usize = 4;

  pub fn new(
    width: usize, height: usize, xdec: usize, ydec: usize, xpad: usize,
    ypad: usize
  ) -> Plane {
    let xorigin = xpad.align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
    let yorigin = ypad;
    let stride = (xorigin + width + xpad)
      .align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
    let alloc_height = yorigin + height + ypad;
    let data = vec![128u16; stride * alloc_height];
    assert!(is_aligned(data.as_ptr(), Plane::DATA_ALIGNMENT_LOG2));
    Plane {
      data,
      cfg: PlaneConfig {
        stride,
        alloc_height,
        width,
        height,
        xdec,
        ydec,
        xorigin,
        yorigin
      }
    }
  }

  pub fn pad(&mut self, w: usize, h: usize) {
    let xorigin = self.cfg.xorigin;
    let yorigin = self.cfg.yorigin;
    let stride = self.cfg.stride;
    let width = w >> self.cfg.xdec;
    let height = h >> self.cfg.ydec;

    if xorigin > 0 {
      for y in 0..height {
        let mut ps = self
          .mut_slice(&PlaneOffset { x: -(xorigin as isize), y: y as isize });
        let s = ps.as_mut_slice_w_width(xorigin + 1);
        let fill_val = s[xorigin];
        for val in s[..xorigin].iter_mut() {
          *val = fill_val;
        }
      }
    }

    if xorigin + width < stride {
      for y in 0..height {
        let mut ps = self
          .mut_slice(&PlaneOffset { x: width as isize - 1, y: y as isize });
        let s = ps.as_mut_slice_w_width(stride - xorigin - width + 1);
        let fill_val = s[0];
        for val in s[1..].iter_mut() {
          *val = fill_val;
        }
      }
    }

    if yorigin > 0 {
      let mut ps = self.mut_slice(&PlaneOffset {
        x: -(xorigin as isize),
        y: -(yorigin as isize)
      });
      let (s1, s2) = ps.as_mut_slice().split_at_mut(yorigin * stride);
      for y in 0..yorigin {
        s1[y * stride..y * stride + stride].copy_from_slice(&s2[..stride]);
      }
    }

    if yorigin + height < self.cfg.alloc_height {
      let mut ps = self.mut_slice(&PlaneOffset {
        x: -(xorigin as isize),
        y: height as isize - 1
      });
      let (s2, s1) = ps.as_mut_slice().split_at_mut(stride);
      for y in 0..yorigin {
        s1[y * stride..y * stride + stride].copy_from_slice(&s2[..stride]);
      }
    }
  }

  pub fn slice(&self, po: &PlaneOffset) -> PlaneSlice {
    PlaneSlice { plane: self, x: po.x, y: po.y }
  }

  pub fn mut_slice(&mut self, po: &PlaneOffset) -> PlaneMutSlice {
    PlaneMutSlice { plane: self, x: po.x, y: po.y }
  }

  #[inline]
  fn index(&self, x: usize, y: usize) -> usize {
    (y + self.cfg.yorigin) * self.cfg.stride + (x + self.cfg.xorigin)
  }

  pub fn p(&self, x: usize, y: usize) -> u16 {
    self.data[self.index(x, y)]
  }

  pub fn data_origin(&self) -> &[u16] {
    &self.data[self.index(0, 0)..]
  }

  pub fn data_origin_mut(&mut self) -> &mut [u16] {
    let i = self.index(0, 0);
    &mut self.data[i..]
  }

  pub fn copy_from_raw_u8(
    &mut self, source: &[u8], source_stride: usize, source_bytewidth: usize
  ) {
    let stride = self.cfg.stride;
    for (self_row, source_row) in self
      .data_origin_mut()
      .chunks_mut(stride)
      .zip(source.chunks(source_stride))
    {
      match source_bytewidth {
        1 => for (self_pixel, source_pixel) in
          self_row.iter_mut().zip(source_row.iter())
        {
          *self_pixel = *source_pixel as u16;
        },
        2 => for (self_pixel, bytes) in
          self_row.iter_mut().zip(source_row.chunks(2))
        {
          *self_pixel = (bytes[1] as u16) << 8 | (bytes[0] as u16);
        },

        _ => {}
      }
    }
  }

  pub fn downsample_from(&mut self, src: &Plane) {
    let width = self.cfg.width;
    let height = self.cfg.height;

    assert!(width * 2 == src.cfg.width);
    assert!(height * 2 == src.cfg.height);

    for row in 0..height {
      let mut dst_slice = self.mut_slice(&PlaneOffset{ x: 0, y: row as isize });
      let mut dst = dst_slice.as_mut_slice();

      for col in 0..width {
        let mut sum = 0;
        sum = sum + src.p(2*col, 2*row);
        sum = sum + src.p(2*col+1, 2*row);
        sum = sum + src.p(2*col, 2*row+1);
        sum = sum + src.p(2*col+1, 2*row+1);
        let avg = (sum + 2) >> 2;
        dst[col] = avg;
      }
    }
  }

  /// Iterates over the pixels in the `Plane`, skipping stride data.
  pub fn iter(&self) -> PlaneIter {
    PlaneIter::new(self)
  }
}

#[derive(Debug)]
pub struct PlaneIter<'a> {
  plane: &'a Plane,
  y: usize,
  x: usize,
}

impl<'a> PlaneIter<'a> {
  pub fn new(plane: &'a Plane) -> Self {
    PlaneIter {
      plane,
      y: 0,
      x: 0,
    }
  }

  fn width(&self) -> usize {
    self.plane.cfg.width
  }

  fn height(&self) -> usize {
    self.plane.cfg.height
  }
}

impl<'a> Iterator for PlaneIter<'a> {
  type Item = u16;

  fn next(&mut self) -> Option<<Self as Iterator>::Item> {
    if self.y == self.height() - 1 && self.x == self.width() - 1 {
      return None;
    }
    let pixel = self.plane.p(self.x, self.y);
    if self.x == self.width() - 1 {
      self.x = 0;
      self.y += 1;
    } else {
      self.x += 1;
    }
    Some(pixel)
  }
}

#[derive(Clone, Copy)]
pub struct PlaneSlice<'a> {
  pub plane: &'a Plane,
  pub x: isize,
  pub y: isize
}

pub struct IterWidth<'a> {
    ps: PlaneSlice<'a>,
    width: usize,
}

impl<'a> Iterator for IterWidth<'a> {
    type Item = &'a [u16];

    #[inline]
    fn next(&mut self) -> Option<&'a [u16]> {
        let x = self.ps.plane.cfg.xorigin as isize + self.ps.x;
        let y = self.ps.plane.cfg.yorigin as isize + self.ps.y;
        let stride = self.ps.plane.cfg.stride;
        let base = y as usize * stride + x as usize;

        if self.ps.plane.data.len() < base + self.width {
            None
        } else {
            self.ps.y += 1;
            Some(&self.ps.plane.data[base..base + self.width])
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let size = self.ps.plane.cfg.height - self.ps.y as usize;

        (size, Some(size))
    }
}

impl<'a> ExactSizeIterator for IterWidth<'a> { }

impl<'a> FusedIterator for IterWidth<'a> { }

impl<'a> PlaneSlice<'a> {
  pub fn as_slice(&self) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[base..]
  }

  pub fn as_slice_clamped(&self) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let y = (self.y.min(self.plane.cfg.height as isize)
      + self.plane.cfg.yorigin as isize)
      .max(0) as usize;
    let x = (self.x.min(self.plane.cfg.width as isize)
      + self.plane.cfg.xorigin as isize)
      .max(0) as usize;
    &self.plane.data[y * stride + x..]
  }

  pub fn as_slice_w_width(&self, width: usize) -> &'a [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[base..base + width]
  }

  pub fn iter_width(&self, width: usize) -> IterWidth<'a> {
    IterWidth { ps: *self, width }
  }

  pub fn subslice(&self, xo: usize, yo: usize) -> PlaneSlice<'a> {
    PlaneSlice {
      plane: self.plane,
      x: self.x + xo as isize,
      y: self.y + yo as isize
    }
  }

  /// A slice starting i pixels above the current one.
  pub fn go_up(&self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
  }

  /// A slice starting i pixels to the left of the current one.
  pub fn go_left(&self, i: usize) -> PlaneSlice<'a> {
    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
  }

  pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    self.plane.data[new_y * self.plane.cfg.stride + new_x]
  }
}

pub struct PlaneMutSlice<'a> {
  pub plane: &'a mut Plane,
  pub x: isize,
  pub y: isize
}

impl<'a> PlaneMutSlice<'a> {
  pub fn as_mut_slice(&mut self) -> &mut [u16] {
    let stride = self.plane.cfg.stride;
    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride
      + (self.x + self.plane.cfg.xorigin as isize) as usize;
    &mut self.plane.data[base..]
  }

  pub fn as_mut_slice_w_width(&mut self, width: usize) -> &mut [u16] {
    let stride = self.plane.cfg.stride;
    let y = self.y + self.plane.cfg.yorigin as isize;
    let x = self.x + self.plane.cfg.xorigin as isize;
    assert!(y >= 0);
    assert!(x >= 0);
    let base = y as usize * stride + x as usize;
    &mut self.plane.data[base..base + width]
  }

  pub fn offset(&self, add_x: usize, add_y: usize) -> &[u16] {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    &self.plane.data[new_y * self.plane.cfg.stride + new_x..]
  }

  pub fn offset_as_mutable(
    &mut self, add_x: usize, add_y: usize
  ) -> &mut [u16] {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    &mut self.plane.data[new_y * self.plane.cfg.stride + new_x..]
  }

  // FIXME: code duplication with PlaneSlice

  /// A slice starting i pixels above the current one.
  pub fn go_up(&self, i: usize) -> PlaneSlice {
    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
  }

  /// A slice starting i pixels to the left of the current one.
  pub fn go_left(&self, i: usize) -> PlaneSlice {
    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
  }

  pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
    let new_y =
      (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
    let new_x =
      (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
    self.plane.data[new_y * self.plane.cfg.stride + new_x]
  }
}
<|endoftext|>


<commit_before>use State;
use GLOBALSINDEX;
use Type;
use raw;

use libc;
use std::thread::Thread;
use std::any::AnyRefExt;
use std::sync::Arc;

#[test]
fn test_state_init() {
    let mut _s = State::new();
}

#[test]
#[should_fail]
fn test_error() {
    let mut s = State::new();
    s.pushinteger(42);
    s.error()
}

#[test]
fn test_errorstr() {
    let res = Thread::spawn::<(), _>(move || {
        let mut s = State::new();
        s.errorstr("some err");
    }).join();
    let err = res.unwrap_err();
    let expected = "unprotected error in call to Lua API (some err)";
    let s = err.downcast_ref::<String>();
    if s.is_some() {
        assert_eq!(s.unwrap().as_slice(), expected);
    } else {
        let s = err.downcast_ref::<&'static str>();
        if s.is_some() {
            assert_eq!(*s.unwrap(), expected);
        } else {
            panic!("unexpected failure result");
        }
    }
}

#[test]
fn test_describe() {
    let mut s = State::new();

    assert_eq!(s.typename(1), "no value");
    s.pushnil();
    assert_eq!(s.typename(-1), "nil");
    s.pushinteger(42);
    assert_eq!(s.typename(-1), "number");
    s.pushstring("test");
    assert_eq!(s.typename(-1), "string");
    s.pushboolean(true);
    assert_eq!(s.typename(-1), "boolean");
    s.pushcfunction(dummy);
    assert_eq!(s.typename(-1), "function");

    extern "C" fn dummy(_L: *mut ::raw::lua_State) -> ::libc::c_int {
        0
    }
}

#[test]
fn test_openlibs() {
    let mut s = State::new();

    s.openlibs();
    s.getfield(GLOBALSINDEX, "table");
    assert_eq!(s.type_(-1), Some(Type::Table));
}

#[deriving(PartialEq,Eq,Show)]
enum CheckOptionEnum {
    One,
    Two,
    Three
}

#[test]
fn test_checkoption() {
    let lst = [("one", CheckOptionEnum::One),
               ("two", CheckOptionEnum::Two),
               ("three", CheckOptionEnum::Three)];

    let mut s = State::new();

    for &(k,ref v) in lst.iter() {
        s.pushstring(k);
        assert_eq!(*s.checkoption(1, None, &lst), *v);
        s.pop(1);
    }
    assert_eq!(*s.checkoption(1, Some("three"), &lst), CheckOptionEnum::Three);

    let lst_arc1 = Arc::new(lst);
    let lst_arc2 = lst_arc1.clone();

    let res = Thread::spawn(move || {
        let mut s = State::new();
        s.checkoption(1, None, &*lst_arc1);
    }).join();
    assert!(res.is_err(), "expected error from checkoption");

    let res = Thread::spawn(move || {
        let mut s = State::new();
        s.checkoption(1, Some("four"), &*lst_arc2);
    }).join();
    assert!(res.is_err(), "expected error from checkoption");
}

#[test]
fn test_tocfunction() {
    let mut s = State::new();

    // extern "C" fns don't implement Eq, so cast them to a pointer instead

    s.pushstring("foo");
    assert_eq!(s.tocfunction(1).map(|f| f as *const ()), None);

    s.pushcfunction(cfunc);
    assert_eq!(s.tocfunction(2).map(|f| f as *const ()), Some(cfunc as *const ()));

    extern "C" fn cfunc(_L: *mut raw::lua_State) -> libc::c_int { 0 }
}

#[test]
fn test_gsub() {
    // do some pretty basic gsub tests
    let mut L = State::new();

    assert_eq!(L.gsub("foobar", "bar", "quux"), "fooquux");
    assert_eq!(L.gsub("foo", "o", "ö"), "föö");
    assert_eq!(L.gsub("test", "a", "b"), "test");
    assert_eq!(L.gsub("a b c d e", " ", "."), "a.b.c.d.e");
}
<commit_msg>Remove Arc from the tests<commit_after>use State;
use GLOBALSINDEX;
use Type;
use raw;

use libc;
use std::thread::Thread;
use std::any::AnyRefExt;

#[test]
fn test_state_init() {
    let mut _s = State::new();
}

#[test]
#[should_fail]
fn test_error() {
    let mut s = State::new();
    s.pushinteger(42);
    s.error()
}

#[test]
fn test_errorstr() {
    let res = Thread::spawn::<(), _>(move || {
        let mut s = State::new();
        s.errorstr("some err");
    }).join();
    let err = res.unwrap_err();
    let expected = "unprotected error in call to Lua API (some err)";
    let s = err.downcast_ref::<String>();
    if s.is_some() {
        assert_eq!(s.unwrap().as_slice(), expected);
    } else {
        let s = err.downcast_ref::<&'static str>();
        if s.is_some() {
            assert_eq!(*s.unwrap(), expected);
        } else {
            panic!("unexpected failure result");
        }
    }
}

#[test]
fn test_describe() {
    let mut s = State::new();

    assert_eq!(s.typename(1), "no value");
    s.pushnil();
    assert_eq!(s.typename(-1), "nil");
    s.pushinteger(42);
    assert_eq!(s.typename(-1), "number");
    s.pushstring("test");
    assert_eq!(s.typename(-1), "string");
    s.pushboolean(true);
    assert_eq!(s.typename(-1), "boolean");
    s.pushcfunction(dummy);
    assert_eq!(s.typename(-1), "function");

    extern "C" fn dummy(_L: *mut ::raw::lua_State) -> ::libc::c_int {
        0
    }
}

#[test]
fn test_openlibs() {
    let mut s = State::new();

    s.openlibs();
    s.getfield(GLOBALSINDEX, "table");
    assert_eq!(s.type_(-1), Some(Type::Table));
}

#[deriving(Copy,PartialEq,Eq,Show)]
enum CheckOptionEnum {
    One,
    Two,
    Three
}

#[test]
fn test_checkoption() {
    let lst = [("one", CheckOptionEnum::One),
               ("two", CheckOptionEnum::Two),
               ("three", CheckOptionEnum::Three)];

    let mut s = State::new();

    for &(k,ref v) in lst.iter() {
        s.pushstring(k);
        assert_eq!(*s.checkoption(1, None, &lst), *v);
        s.pop(1);
    }
    assert_eq!(*s.checkoption(1, Some("three"), &lst), CheckOptionEnum::Three);

    let res = Thread::spawn(move || {
        let mut s = State::new();
        s.checkoption(1, None, &lst);
    }).join();
    assert!(res.is_err(), "expected error from checkoption");

    let res = Thread::spawn(move || {
        let mut s = State::new();
        s.checkoption(1, Some("four"), &lst);
    }).join();
    assert!(res.is_err(), "expected error from checkoption");
}

#[test]
fn test_tocfunction() {
    let mut s = State::new();

    // extern "C" fns don't implement Eq, so cast them to a pointer instead

    s.pushstring("foo");
    assert_eq!(s.tocfunction(1).map(|f| f as *const ()), None);

    s.pushcfunction(cfunc);
    assert_eq!(s.tocfunction(2).map(|f| f as *const ()), Some(cfunc as *const ()));

    extern "C" fn cfunc(_L: *mut raw::lua_State) -> libc::c_int { 0 }
}

#[test]
fn test_gsub() {
    // do some pretty basic gsub tests
    let mut L = State::new();

    assert_eq!(L.gsub("foobar", "bar", "quux"), "fooquux");
    assert_eq!(L.gsub("foo", "o", "ö"), "föö");
    assert_eq!(L.gsub("test", "a", "b"), "test");
    assert_eq!(L.gsub("a b c d e", " ", "."), "a.b.c.d.e");
}
<|endoftext|>


<commit_before>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<commit_msg>rename test for consistency<commit_after>use super::Checked;

// Test a unary operator
macro_rules! test_unop {
    ($name:ident $t:ty: $op:tt $expr1:tt == $expr2:tt) => {
        #[test]
        fn $name() {
            let x = Checked::<$t>::from($expr1);
            let y = Checked::<$t>::from($expr2);
            assert_eq!($op x, y);
            assert_eq!($op &x, y);
        }
    };
}

// Test a binary operator
macro_rules! test_binop {
    ($name:ident $t:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$t>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $t;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$t>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };

    ($name:ident $t:ty, $u:ty, $v:ty: $expr1:tt $op:tt $expr2:tt == $expr3:tt) => {
        #[test]
        fn $name() {
            let x1 = Checked::<$t>::from($expr1);
            let y1 = Checked::<$u>::from($expr2);
            let x2 = $expr1 as $t;
            let y2 = $expr2 as $u;
            let z = Checked::<$v>::from($expr3);
            assert_eq!(x1 $op y1, z);
            assert_eq!(x2 $op y1, z);
            assert_eq!(x1 $op y2, z);
            assert_eq!(&x1 $op y1, z);
            assert_eq!(&x2 $op y1, z);
            assert_eq!(&x1 $op y2, z);
            assert_eq!(x1 $op &y1, z);
            assert_eq!(x2 $op &y1, z);
            assert_eq!(x1 $op &y2, z);
            assert_eq!(&x1 $op &y1, z);
            assert_eq!(&x2 $op &y1, z);
            assert_eq!(&x1 $op &y2, z);
        }
    };
}

// These tests use None to indicate over/underflow.
test_binop! (add1 u8: 5 + 6 == 11);
test_binop! (add2 u32: 3_000_000_000 + 2_000_000_000 == None);
test_binop! (add3 i32: (-2_000_000_000) + (-2_000_000_000) == None);
test_binop! (sub u8: 5 - 6 == None);
test_binop! (mul1 u8: 5 * 6 == 30);
test_binop! (mul2 i32: 2_000_000_000 * 3 == None);
test_binop! (div1 u8: 10 / 3 == 3);
test_binop! (div2 u8: 10 / 0 == None);
test_binop! (and u8: 5 & 6 == 4);
test_binop! (xor u8: 5 ^ 6 == 3);
test_binop! (or u8: 5 | 6 == 7);
test_binop! (rem u8: 10 % 3 == 1);
test_binop! (shl u8, u32: 10 << 3 == 80);
test_binop! (shr u8, u32: 80 >> 3 == 10);
test_unop! (neg1 u8: - 5 == None);
test_unop! (neg2 i8: - 5 == (-5));
test_unop! (not i8: ! 5 == (-6));
<|endoftext|>


<commit_before>/// Associates readiness events with [`event::Source`]s.
///
/// `Token` is a wrapper around `usize` and is used as an argument to
/// [`Registry::register`] and [`Registry::reregister`].
///
/// See [`Poll`] for more documentation on polling.
///
/// [`event::Source`]: crate::event::Source
/// [`Poll`]: crate::Poll
/// [`Registry::register`]: crate::Registry::register
/// [`Registry::reregister`]: crate::Registry::reregister
///
/// # Example
///
/// Using `Token` to track which socket generated the event. In this example,
/// `HashMap` is used, but usually something like [`slab`] is better.
///
/// [`slab`]: https://crates.io/crates/slab
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Events, Interest, Poll, Token};
/// use mio::net::TcpListener;
///
/// use std::thread;
/// use std::io::{self, Read};
/// use std::collections::HashMap;
///
/// // After this number of sockets is accepted, the server will shutdown.
/// const MAX_SOCKETS: usize = 32;
///
/// // Pick a token that will not be used by any other socket and use that one
/// // for the listener.
/// const LISTENER: Token = Token(1024);
///
/// // Used to store the sockets.
/// let mut sockets = HashMap::new();
///
/// // This is used to generate a unique token for a socket
/// let mut next_socket_index = 0;
///
/// // The `Poll` instance
/// let mut poll = Poll::new()?;
///
/// // Tcp listener
/// let listener = TcpListener::bind("127.0.0.1:0".parse()?)?;
///
/// // Register the listener
/// poll.registry().register(&listener, LISTENER, Interest::READABLE)?;
///
/// // Spawn a thread that will connect a bunch of sockets then close them
/// let addr = listener.local_addr()?;
/// thread::spawn(move || {
///     use std::net::TcpStream;
///
///     // +1 here is to connect an extra socket to signal the socket to close
///     for _ in 0..(MAX_SOCKETS+1) {
///         // Connect then drop the socket
///         let _ = TcpStream::connect(addr).unwrap();
///     }
/// });
///
/// // Event storage
/// let mut events = Events::with_capacity(1024);
///
/// // Read buffer, this will never actually get filled
/// let mut buf = [0; 256];
///
/// // The main event loop
/// loop {
///     // Wait for events
///     poll.poll(&mut events, None)?;
///
///     for event in &events {
///         match event.token() {
///             LISTENER => {
///                 // Perform operations in a loop until `WouldBlock` is
///                 // encountered.
///                 loop {
///                     match listener.accept() {
///                         Ok((socket, _)) => {
///                             // Shutdown the server
///                             if next_socket_index == MAX_SOCKETS {
///                                 return Ok(());
///                             }
///
///                             // Get the token for the socket
///                             let token = Token(next_socket_index);
///                             next_socket_index += 1;
///
///                             // Register the new socket w/ poll
///                             poll.registry().register(&socket, token, Interest::READABLE)?;
///
///                             // Store the socket
///                             sockets.insert(token, socket);
///                         }
///                         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
///                             // Socket is not ready anymore, stop accepting
///                             break;
///                         }
///                         e => panic!("err={:?}", e), // Unexpected error
///                     }
///                 }
///             }
///             token => {
///                 // Always operate in a loop
///                 loop {
///                     match sockets.get_mut(&token).unwrap().read(&mut buf) {
///                         Ok(0) => {
///                             // Socket is closed, remove it from the map
///                             sockets.remove(&token);
///                             break;
///                         }
///                         // Data is not actually sent in this example
///                         Ok(_) => unreachable!(),
///                         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
///                             // Socket is not ready anymore, stop reading
///                             break;
///                         }
///                         e => panic!("err={:?}", e), // Unexpected error
///                     }
///                 }
///             }
///         }
///     }
/// }
/// # }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Token(pub usize);

impl From<usize> for Token {
    fn from(val: usize) -> Token {
        Token(val)
    }
}

impl From<Token> for usize {
    fn from(val: Token) -> usize {
        val.0
    }
}
<commit_msg>Remove From<usize> for Token<commit_after>/// Associates readiness events with [`event::Source`]s.
///
/// `Token` is a wrapper around `usize` and is used as an argument to
/// [`Registry::register`] and [`Registry::reregister`].
///
/// See [`Poll`] for more documentation on polling.
///
/// [`event::Source`]: crate::event::Source
/// [`Poll`]: crate::Poll
/// [`Registry::register`]: crate::Registry::register
/// [`Registry::reregister`]: crate::Registry::reregister
///
/// # Example
///
/// Using `Token` to track which socket generated the event. In this example,
/// `HashMap` is used, but usually something like [`slab`] is better.
///
/// [`slab`]: https://crates.io/crates/slab
///
/// ```
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use mio::{Events, Interest, Poll, Token};
/// use mio::net::TcpListener;
///
/// use std::thread;
/// use std::io::{self, Read};
/// use std::collections::HashMap;
///
/// // After this number of sockets is accepted, the server will shutdown.
/// const MAX_SOCKETS: usize = 32;
///
/// // Pick a token that will not be used by any other socket and use that one
/// // for the listener.
/// const LISTENER: Token = Token(1024);
///
/// // Used to store the sockets.
/// let mut sockets = HashMap::new();
///
/// // This is used to generate a unique token for a socket
/// let mut next_socket_index = 0;
///
/// // The `Poll` instance
/// let mut poll = Poll::new()?;
///
/// // Tcp listener
/// let listener = TcpListener::bind("127.0.0.1:0".parse()?)?;
///
/// // Register the listener
/// poll.registry().register(&listener, LISTENER, Interest::READABLE)?;
///
/// // Spawn a thread that will connect a bunch of sockets then close them
/// let addr = listener.local_addr()?;
/// thread::spawn(move || {
///     use std::net::TcpStream;
///
///     // +1 here is to connect an extra socket to signal the socket to close
///     for _ in 0..(MAX_SOCKETS+1) {
///         // Connect then drop the socket
///         let _ = TcpStream::connect(addr).unwrap();
///     }
/// });
///
/// // Event storage
/// let mut events = Events::with_capacity(1024);
///
/// // Read buffer, this will never actually get filled
/// let mut buf = [0; 256];
///
/// // The main event loop
/// loop {
///     // Wait for events
///     poll.poll(&mut events, None)?;
///
///     for event in &events {
///         match event.token() {
///             LISTENER => {
///                 // Perform operations in a loop until `WouldBlock` is
///                 // encountered.
///                 loop {
///                     match listener.accept() {
///                         Ok((socket, _)) => {
///                             // Shutdown the server
///                             if next_socket_index == MAX_SOCKETS {
///                                 return Ok(());
///                             }
///
///                             // Get the token for the socket
///                             let token = Token(next_socket_index);
///                             next_socket_index += 1;
///
///                             // Register the new socket w/ poll
///                             poll.registry().register(&socket, token, Interest::READABLE)?;
///
///                             // Store the socket
///                             sockets.insert(token, socket);
///                         }
///                         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
///                             // Socket is not ready anymore, stop accepting
///                             break;
///                         }
///                         e => panic!("err={:?}", e), // Unexpected error
///                     }
///                 }
///             }
///             token => {
///                 // Always operate in a loop
///                 loop {
///                     match sockets.get_mut(&token).unwrap().read(&mut buf) {
///                         Ok(0) => {
///                             // Socket is closed, remove it from the map
///                             sockets.remove(&token);
///                             break;
///                         }
///                         // Data is not actually sent in this example
///                         Ok(_) => unreachable!(),
///                         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
///                             // Socket is not ready anymore, stop reading
///                             break;
///                         }
///                         e => panic!("err={:?}", e), // Unexpected error
///                     }
///                 }
///             }
///         }
///     }
/// }
/// # }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Token(pub usize);

impl From<Token> for usize {
    fn from(val: Token) -> usize {
        val.0
    }
}
<|endoftext|>


<commit_before>use errors;
use std::result;

/// see OSC Type Tag String: [OSC Spec. 1.0](http://opensoundcontrol.org/spec-1_0)
/// padding: zero bytes (n*4)
#[derive(Clone,Debug, PartialEq)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    // use struct for time tag to avoid destructuring
    Time(u32, u32),
    Long(i64),
    Double(f64),
    Char(char),
    Color(OscColor),
    Midi(OscMidiMessage),
    Bool(bool),
    Nil,
    Inf,
}
macro_rules! value_impl {
    ($(($name:ident, $variant:ident, $ty:ty)),*) => {
        $(
        impl OscType {
            #[allow(dead_code)]
            pub fn $name(self) -> Option<$ty> {
                match self {
                    OscType::$variant(v) => Some(v),
                    _ => None
                }
            }
        }
        impl From<$ty> for OscType {
            fn from(v: $ty) -> Self {
                OscType::$variant(v)
            }
        }
        )*
    }
}
value_impl! {
    (int, Int, i32),
    (float, Float, f32),
    (string, String, String),
    (blob, Blob, Vec<u8>),
    (long, Long, i64),
    (double, Double, f64),
    (char, Char, char),
    (color, Color, OscColor),
    (midi, Midi, OscMidiMessage),
    (bool, Bool, bool)
}
/// Represents the parts of a Midi message. Mainly used for
/// tunneling midi over a network using the OSC protocol.
#[derive(Clone,Debug, PartialEq)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Clone,Debug, PartialEq)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

/// An OSC message consists of an address and
/// zero or more arguments. The address should
/// specify an element of your Instrument (or whatever
/// you want to control with OSC) and the arguments
/// are used to set properties of the element to the
/// respective values.
#[derive(Clone,Debug, PartialEq)]
pub struct OscMessage {
    pub addr: String,
    pub args: Option<Vec<OscType>>,
}

/// An OSC bundle contains zero or more OSC packets
/// and a time tag. The contained packets *should* be
/// applied at the given time tag.
#[derive(Clone,Debug, PartialEq)]
pub struct OscBundle {
    pub timetag: OscType,
    pub content: Vec<OscPacket>,
}

/// An RGBA color.
#[derive(Clone,Debug, PartialEq)]
pub struct OscColor {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
    pub alpha: u8,
}

pub type Result<T> = result::Result<T, errors::OscError>;

impl From<String> for OscMessage {
    fn from(s: String) -> OscMessage {
        OscMessage {
            addr: s,
            args: None
        }
    }
}
impl<'a> From<&'a str> for OscMessage {
    fn from(s: &str) -> OscMessage {
        OscMessage {
            addr: s.to_string(),
            args: None
        }
    }
}
<commit_msg>add basic impl for OscType::Time<commit_after>use errors;
use std::result;

/// see OSC Type Tag String: [OSC Spec. 1.0](http://opensoundcontrol.org/spec-1_0)
/// padding: zero bytes (n*4)
#[derive(Clone,Debug, PartialEq)]
pub enum OscType {
    Int(i32),
    Float(f32),
    String(String),
    Blob(Vec<u8>),
    // use struct for time tag to avoid destructuring
    Time(u32, u32),
    Long(i64),
    Double(f64),
    Char(char),
    Color(OscColor),
    Midi(OscMidiMessage),
    Bool(bool),
    Nil,
    Inf,
}
macro_rules! value_impl {
    ($(($name:ident, $variant:ident, $ty:ty)),*) => {
        $(
        impl OscType {
            #[allow(dead_code)]
            pub fn $name(self) -> Option<$ty> {
                match self {
                    OscType::$variant(v) => Some(v),
                    _ => None
                }
            }
        }
        impl From<$ty> for OscType {
            fn from(v: $ty) -> Self {
                OscType::$variant(v)
            }
        }
        )*
    }
}
value_impl! {
    (int, Int, i32),
    (float, Float, f32),
    (string, String, String),
    (blob, Blob, Vec<u8>),
    (long, Long, i64),
    (double, Double, f64),
    (char, Char, char),
    (color, Color, OscColor),
    (midi, Midi, OscMidiMessage),
    (bool, Bool, bool)
}
impl From<(u32, u32)> for OscType {
    fn from(time: (u32, u32)) -> Self {
        OscType::Time(time.0, time.1)
    }
}
impl OscType {
    #[allow(dead_code)]
    pub fn time(self) -> Option<(u32, u32)> {
        match self {
            OscType::Time(sec, frac) => Some((sec, frac)),
            _ => None,
        }
    }
}
/// Represents the parts of a Midi message. Mainly used for
/// tunneling midi over a network using the OSC protocol.
#[derive(Clone,Debug, PartialEq)]
pub struct OscMidiMessage {
    pub port: u8,
    pub status: u8,
    pub data1: u8, // maybe use an enum for data?
    pub data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
#[derive(Clone,Debug, PartialEq)]
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

/// An OSC message consists of an address and
/// zero or more arguments. The address should
/// specify an element of your Instrument (or whatever
/// you want to control with OSC) and the arguments
/// are used to set properties of the element to the
/// respective values.
#[derive(Clone,Debug, PartialEq)]
pub struct OscMessage {
    pub addr: String,
    pub args: Option<Vec<OscType>>,
}

/// An OSC bundle contains zero or more OSC packets
/// and a time tag. The contained packets *should* be
/// applied at the given time tag.
#[derive(Clone,Debug, PartialEq)]
pub struct OscBundle {
    pub timetag: OscType,
    pub content: Vec<OscPacket>,
}

/// An RGBA color.
#[derive(Clone,Debug, PartialEq)]
pub struct OscColor {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
    pub alpha: u8,
}

pub type Result<T> = result::Result<T, errors::OscError>;

impl From<String> for OscMessage {
    fn from(s: String) -> OscMessage {
        OscMessage {
            addr: s,
            args: None
        }
    }
}
impl<'a> From<&'a str> for OscMessage {
    fn from(s: &str) -> OscMessage {
        OscMessage {
            addr: s.to_string(),
            args: None
        }
    }
}
<|endoftext|>


<commit_before>extern crate bev;

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use bev::{Bez3o2d};

use gfx::traits::FactoryExt;
use gfx::{Device, Primitive};
use gfx::state::Rasterizer;

use glutin::Event;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_vertex_struct!{ Vertex {
    pos: [f32; 2] = "v_pos",
    col: [f32; 3] = "v_col",
}}

gfx_pipeline!{ pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    out: gfx::RenderTarget<ColorFormat> = "r_target",
}}

fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_dimensions(720, 720)
        .with_multisampling(16)
        .with_title("Hello Bézier".into());
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let sset = factory.create_shader_set(VERT, FRAG).unwrap();
    let pso = factory.create_pipeline_state(
        &sset,
        Primitive::TriangleStrip,
        Rasterizer::new_fill(),
        pipe::new()
    ).unwrap();

    let curve = Bez3o2d::new(
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0
    );

    let mut verts = [Vertex{ pos: [0.0, 0.0], col: [1.0, 1.0, 1.0] }; 31];
    let mut perps = [Vertex{ pos: [0.0, 0.0], col: [1.0, 1.0, 1.0] }; 62];
    for i in 0..verts.len() {
        let t = i as f32/(verts.len()-1) as f32;

        let interp = curve.interp(t);
        verts[i].pos = interp.into();

        let perp = curve.slope(t).normalize().perp() * 0.01;
        perps[i*2].pos = (-perp + interp).into();
        perps[i*2 + 1].pos = (perp + interp).into();
    }

    // let (vert_buffer, vert_slice) = factory.create_vertex_buffer_with_slice(&verts, ());
    let (perp_buffer, perp_slice) = factory.create_vertex_buffer_with_slice(&perps, ());
    let mut data = pipe::Data {
        vbuf: perp_buffer.clone(),
        out: main_color
    };

    'main: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => break 'main,
                _ => ()
            }
        }

        encoder.clear(&data.out, [0.0, 0.0, 0.0, 1.0]);

        // data.vbuf = vert_buffer.clone();
        // encoder.draw(&vert_slice, &pso, &data);

        data.vbuf = perp_buffer.clone();
        encoder.draw(&perp_slice, &pso, &data);

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

const VERT: &'static [u8] = br#"
    #version 150 core

    in vec2 v_pos;
    in vec3 v_col;
    out vec4 f_col;

    void main() {
        f_col = vec4(v_col, 1.0);
        gl_Position = vec4(v_pos, 0.0, 1.0);
    }
"#;

const FRAG: &'static [u8] = br#"
    #version 150 core

    in vec4 f_col;
    out vec4 r_target;

    void main() {
        r_target = f_col;
    }
"#;<commit_msg>Added control point visualization to drawing example<commit_after>extern crate bev;

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use bev::{Bez3o2d};

use gfx::traits::FactoryExt;
use gfx::{Device, Primitive};
use gfx::state::Rasterizer;

use glutin::Event;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_vertex_struct!{ Vertex {
    pos: [f32; 2] = "v_pos",
    col: [f32; 3] = "v_col",
}}

gfx_pipeline!{ pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    offset: gfx::Global<[f32; 2]> = "offset",
    out: gfx::RenderTarget<ColorFormat> = "r_target",
}}

fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_dimensions(720, 720)
        .with_multisampling(16)
        .with_title("Hello Bézier".into());
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let sset = factory.create_shader_set(VERT, FRAG).unwrap();
    let pso = factory.create_pipeline_state(
        &sset,
        Primitive::TriangleStrip,
        Rasterizer::new_fill(),
        pipe::new()
    ).unwrap();

    let curve = Bez3o2d::new(
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0
    );

    let verts = [Vertex{ pos: [0.0, 0.0], col: [1.0, 1.0, 1.0] }; 31];
    let mut perps = [Vertex{ pos: [0.0, 0.0], col: [1.0, 1.0, 1.0] }; 62];
    for i in 0..verts.len() {
        let t = i as f32/(verts.len()-1) as f32;

        let interp = curve.interp(t);

        let perp = curve.slope(t).normalize().perp() * 0.01;
        perps[i*2].pos = (-perp + interp).into();
        perps[i*2 + 1].pos = (perp + interp).into();
    }

    let circle = gen_circle(16, 0.02, [1.0, 0.0, 0.0]);
    let mut indices = vec![0u16; 42];
    for (ind, i) in indices.iter_mut().enumerate() {
        let ind = ind + 3;
        if ind % 3 == 1 {
            *i = ind as u16/3;
        } else if ind % 3 == 2 {
            *i = ind as u16/3 + 1
        }
    }
    // println!("{:#?}", circle);

    let (perp_buffer, perp_slice) = factory.create_vertex_buffer_with_slice(&perps, ());
    let (cir_buffer, cir_slice) = factory.create_vertex_buffer_with_slice(&circle, &indices[..]);
    let mut data = pipe::Data {
        vbuf: perp_buffer.clone(),
        offset: [0.0, 0.0],
        out: main_color
    };

    'main: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => break 'main,
                _ => ()
            }
        }

        encoder.clear(&data.out, [0.0, 0.0, 0.0, 1.0]);

        data.offset = [0.0, 0.0];
        data.vbuf = perp_buffer.clone();
        encoder.draw(&perp_slice, &pso, &data);

        data.vbuf = cir_buffer.clone();
        data.offset = curve.start().into();
        encoder.draw(&cir_slice, &pso, &data);
        data.offset = curve.ctrl0().into();
        encoder.draw(&cir_slice, &pso, &data);
        data.offset = curve.ctrl1().into();
        encoder.draw(&cir_slice, &pso, &data);
        data.offset = curve.end().into();
        encoder.draw(&cir_slice, &pso, &data);

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

fn gen_circle(divs: u16, scale: f32, col: [f32; 3]) -> Vec<Vertex> {
    use std::f32::consts::PI;
    let mut verts = vec![Vertex{ pos: [0.0, 0.0], col: col}; divs as usize];

    for d in 0..divs {
        let theta = 2.0 * PI * (d as f32/divs as f32);
        let d = d as usize;
        verts[d].pos[0] = theta.sin() * scale;
        verts[d].pos[1] = theta.cos() * scale;
    }

    verts
}

const VERT: &'static [u8] = br#"
    #version 150 core

    uniform vec2 offset;

    in vec2 v_pos;
    in vec3 v_col;
    out vec4 f_col;

    void main() {
        f_col = vec4(v_col, 1.0);
        gl_Position = vec4(v_pos + offset, 0.0, 1.0);
    }
"#;

const FRAG: &'static [u8] = br#"
    #version 150 core

    in vec4 f_col;
    out vec4 r_target;

    void main() {
        r_target = f_col;
    }
"#;<|endoftext|>


<commit_before>use std::collections::hash_map::HashMap;

struct Function {
    blocks: HashMap<Block, BlockData>,
    instructions: HashMap<Inst, InstData>,
    params: Vec<Type>,
    entry_block: Option<Block>,
    exit_block: Option<Block>,
}

struct Inst(u32);
struct Block(u32);
struct Param(u32);

struct BlockData {
    predecessors: Vec<Block>,
    successors: Vec<Block>,
    first_inst: Option<Inst>,
    last_inst: Option<Inst>,
}

enum CmpOp {
    Lt, Le, Eq, Ne, Gt, Ge,
}

enum InstData {
    Add {
        ty: Type,
        lhs: Value,
        rhs: Value,
    },

    Sub {
        ty: Type,
        lhs: Value,
        rhs: Value,
    },

    Branch {
        target: Block,
    },

    CondBranch {
        opnd: Value,
        then_block: Block,
        else_block: Block,
    },

    Cmp {
        ty: Type,
        op: CmpOp,
        lhs: Value,
        rhs: Value,
    },

    Ret {
        opnd: Option<Value>,
    },

    Deleted,
}

enum Value {
    Inst(Inst),
    Param(Param),
}

struct InstLoc {
    block: Option<Block>,
    prev: Option<Inst>,
    next: Option<Inst>,
}

enum Type {
    Int8,
    Int32,
    Int64,
    Float32,
    Float64,
    Reference,
}<commit_msg>boots: added IR use list<commit_after>use std::collections::hash_map::HashMap;

struct Function {
    blocks: HashMap<Block, BlockData>,
    instructions: HashMap<Inst, InstData>,
    uses: HashMap<Inst, UseList>,
    params: Vec<Type>,
    entry_block: Option<Block>,
    exit_block: Option<Block>,
}

struct Inst(u32);
struct Block(u32);
struct Param(u32);

struct UseList(Vec<Inst>);

struct BlockData {
    predecessors: Vec<Block>,
    successors: Vec<Block>,
    first_inst: Option<Inst>,
    last_inst: Option<Inst>,
}

enum CmpOp {
    Lt, Le, Eq, Ne, Gt, Ge,
}

enum InstData {
    Add {
        ty: Type,
        lhs: Value,
        rhs: Value,
    },

    Sub {
        ty: Type,
        lhs: Value,
        rhs: Value,
    },

    Goto {
        target: Block,
    },

    If {
        opnd: Value,
        then_block: Block,
        else_block: Block,
    },

    Cmp {
        ty: Type,
        op: CmpOp,
        lhs: Value,
        rhs: Value,
    },

    Ret {
        opnd: Option<Value>,
    },

    Deleted,
}

enum Value {
    Inst(Inst),
    Param(Param),
}

struct InstLoc {
    block: Option<Block>,
    prev: Option<Inst>,
    next: Option<Inst>,
}

enum Type {
    Int8,
    Int32,
    Int64,
    Float32,
    Float64,
    Reference,
}<|endoftext|>


<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 https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::cell::{DomRefCell, Ref};
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::customelementregistry::CallbackReaction;
use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::mutationobserver::{Mutation, MutationObserver};
use crate::dom::node::Node;
use crate::dom::virtualmethods::vtable_for;
use crate::script_thread::ScriptThread;
use devtools_traits::AttrInfo;
use dom_struct::dom_struct;
use html5ever::{LocalName, Namespace, Prefix};
use servo_atoms::Atom;
use std::borrow::ToOwned;
use std::mem;
use style::attr::{AttrIdentifier, AttrValue};

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    node_: Node,
    identifier: AttrIdentifier,
    value: DomRefCell<AttrValue>,

    /// the element that owns this attribute.
    owner: MutNullableDom<Element>,
}

impl Attr {
    fn new_inherited(
        document: &Document,
        local_name: LocalName,
        value: AttrValue,
        name: LocalName,
        namespace: Namespace,
        prefix: Option<Prefix>,
        owner: Option<&Element>,
    ) -> Attr {
        Attr {
            node_: Node::new_inherited(document),
            identifier: AttrIdentifier {
                local_name: local_name,
                name: name,
                namespace: namespace,
                prefix: prefix,
            },
            value: DomRefCell::new(value),
            owner: MutNullableDom::new(owner),
        }
    }

    pub fn new(
        document: &Document,
        local_name: LocalName,
        value: AttrValue,
        name: LocalName,
        namespace: Namespace,
        prefix: Option<Prefix>,
        owner: Option<&Element>,
    ) -> DomRoot<Attr> {
        Node::reflect_node(
            Box::new(Attr::new_inherited(
                document, local_name, value, name, namespace, prefix, owner,
            )),
            document,
        )
    }

    #[inline]
    pub fn name(&self) -> &LocalName {
        &self.identifier.name
    }

    #[inline]
    pub fn namespace(&self) -> &Namespace {
        &self.identifier.namespace
    }

    #[inline]
    pub fn prefix(&self) -> Option<&Prefix> {
        self.identifier.prefix.as_ref()
    }
}

impl AttrMethods for Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        DOMString::from(&**self.local_name())
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from AttrValue to DOMString
        DOMString::from(&**self.value())
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(&self, value: DOMString) {
        if let Some(owner) = self.owner() {
            let value = owner.parse_attribute(&self.identifier.namespace, self.local_name(), value);
            self.set_value(value, &owner);
        } else {
            *self.value.borrow_mut() = AttrValue::String(value.into());
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        DOMString::from(&*self.identifier.name)
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(&self) -> Option<DOMString> {
        match self.identifier.namespace {
            ns!() => None,
            ref url => Some(DOMString::from(&**url)),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(&self) -> Option<DOMString> {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        self.prefix().map(|p| DOMString::from(&**p))
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(&self) -> Option<DomRoot<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(&self) -> bool {
        true // Always returns true
    }
}

impl Attr {
    pub fn set_value(&self, mut value: AttrValue, owner: &Element) {
        let name = self.local_name().clone();
        let namespace = self.namespace().clone();
        let old_value = DOMString::from(&**self.value());
        let new_value = DOMString::from(&*value);
        let mutation = Mutation::Attribute {
            name: name.clone(),
            namespace: namespace.clone(),
            old_value: Some(old_value.clone()),
        };

        MutationObserver::queue_a_mutation_record(owner.upcast::<Node>(), mutation);

        if owner.get_custom_element_definition().is_some() {
            let reaction = CallbackReaction::AttributeChanged(
                name,
                Some(old_value),
                Some(new_value),
                namespace,
            );
            ScriptThread::enqueue_callback_reaction(owner, reaction, None);
        }

        assert_eq!(Some(owner), self.owner().as_deref());
        owner.will_mutate_attr(self);
        self.swap_value(&mut value);
        if self.identifier.namespace == ns!() {
            vtable_for(owner.upcast())
                .attribute_mutated(self, AttributeMutation::Set(Some(&value)));
        }
    }

    /// Used to swap the attribute's value without triggering mutation events
    pub fn swap_value(&self, value: &mut AttrValue) {
        mem::swap(&mut *self.value.borrow_mut(), value);
    }

    pub fn identifier(&self) -> &AttrIdentifier {
        &self.identifier
    }

    pub fn value(&self) -> Ref<AttrValue> {
        self.value.borrow()
    }

    pub fn local_name(&self) -> &LocalName {
        &self.identifier.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    pub fn set_owner(&self, owner: Option<&Element>) {
        let ns = &self.identifier.namespace;
        match (self.owner(), owner) {
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(
                    old.get_attribute(&ns, &self.identifier.local_name)
                        .as_deref() !=
                        Some(self)
                )
            },
            (Some(old), Some(new)) => assert_eq!(&*old, new),
            _ => {},
        }
        self.owner.set(owner);
    }

    pub fn owner(&self) -> Option<DomRoot<Element>> {
        self.owner.get()
    }

    pub fn summarize(&self) -> AttrInfo {
        AttrInfo {
            namespace: (*self.identifier.namespace).to_owned(),
            name: String::from(self.Name()),
            value: String::from(self.Value()),
        }
    }

    pub fn qualified_name(&self) -> DOMString {
        match self.prefix() {
            Some(ref prefix) => DOMString::from(format!("{}:{}", prefix, &**self.local_name())),
            None => DOMString::from(&**self.local_name()),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout<'dom> {
    unsafe fn value(self) -> &'dom AttrValue;
    unsafe fn value_ref_forever(self) -> &'dom str;
    unsafe fn value_tokens(self) -> Option<&'dom [Atom]>;
    unsafe fn local_name_atom(self) -> LocalName;
}

#[allow(unsafe_code)]
impl<'dom> AttrHelpersForLayout<'dom> for LayoutDom<'dom, Attr> {
    #[inline]
    unsafe fn value(self) -> &'dom AttrValue {
        (*self.unsafe_get()).value.borrow_for_layout()
    }

    #[inline]
    unsafe fn value_ref_forever(self) -> &'dom str {
        &**self.value()
    }

    #[inline]
    unsafe fn value_tokens(self) -> Option<&'dom [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom(self) -> LocalName {
        (*self.unsafe_get()).identifier.local_name.clone()
    }
}
<commit_msg>Make AttrHelpersForLayout methods be 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 https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::cell::{DomRefCell, Ref};
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::customelementregistry::CallbackReaction;
use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::mutationobserver::{Mutation, MutationObserver};
use crate::dom::node::Node;
use crate::dom::virtualmethods::vtable_for;
use crate::script_thread::ScriptThread;
use devtools_traits::AttrInfo;
use dom_struct::dom_struct;
use html5ever::{LocalName, Namespace, Prefix};
use servo_atoms::Atom;
use std::borrow::ToOwned;
use std::mem;
use style::attr::{AttrIdentifier, AttrValue};

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    node_: Node,
    identifier: AttrIdentifier,
    value: DomRefCell<AttrValue>,

    /// the element that owns this attribute.
    owner: MutNullableDom<Element>,
}

impl Attr {
    fn new_inherited(
        document: &Document,
        local_name: LocalName,
        value: AttrValue,
        name: LocalName,
        namespace: Namespace,
        prefix: Option<Prefix>,
        owner: Option<&Element>,
    ) -> Attr {
        Attr {
            node_: Node::new_inherited(document),
            identifier: AttrIdentifier {
                local_name: local_name,
                name: name,
                namespace: namespace,
                prefix: prefix,
            },
            value: DomRefCell::new(value),
            owner: MutNullableDom::new(owner),
        }
    }

    pub fn new(
        document: &Document,
        local_name: LocalName,
        value: AttrValue,
        name: LocalName,
        namespace: Namespace,
        prefix: Option<Prefix>,
        owner: Option<&Element>,
    ) -> DomRoot<Attr> {
        Node::reflect_node(
            Box::new(Attr::new_inherited(
                document, local_name, value, name, namespace, prefix, owner,
            )),
            document,
        )
    }

    #[inline]
    pub fn name(&self) -> &LocalName {
        &self.identifier.name
    }

    #[inline]
    pub fn namespace(&self) -> &Namespace {
        &self.identifier.namespace
    }

    #[inline]
    pub fn prefix(&self) -> Option<&Prefix> {
        self.identifier.prefix.as_ref()
    }
}

impl AttrMethods for Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        DOMString::from(&**self.local_name())
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from AttrValue to DOMString
        DOMString::from(&**self.value())
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(&self, value: DOMString) {
        if let Some(owner) = self.owner() {
            let value = owner.parse_attribute(&self.identifier.namespace, self.local_name(), value);
            self.set_value(value, &owner);
        } else {
            *self.value.borrow_mut() = AttrValue::String(value.into());
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(&self) -> DOMString {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        DOMString::from(&*self.identifier.name)
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(&self) -> Option<DOMString> {
        match self.identifier.namespace {
            ns!() => None,
            ref url => Some(DOMString::from(&**url)),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(&self) -> Option<DOMString> {
        // FIXME(ajeffrey): convert directly from LocalName to DOMString
        self.prefix().map(|p| DOMString::from(&**p))
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(&self) -> Option<DomRoot<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(&self) -> bool {
        true // Always returns true
    }
}

impl Attr {
    pub fn set_value(&self, mut value: AttrValue, owner: &Element) {
        let name = self.local_name().clone();
        let namespace = self.namespace().clone();
        let old_value = DOMString::from(&**self.value());
        let new_value = DOMString::from(&*value);
        let mutation = Mutation::Attribute {
            name: name.clone(),
            namespace: namespace.clone(),
            old_value: Some(old_value.clone()),
        };

        MutationObserver::queue_a_mutation_record(owner.upcast::<Node>(), mutation);

        if owner.get_custom_element_definition().is_some() {
            let reaction = CallbackReaction::AttributeChanged(
                name,
                Some(old_value),
                Some(new_value),
                namespace,
            );
            ScriptThread::enqueue_callback_reaction(owner, reaction, None);
        }

        assert_eq!(Some(owner), self.owner().as_deref());
        owner.will_mutate_attr(self);
        self.swap_value(&mut value);
        if self.identifier.namespace == ns!() {
            vtable_for(owner.upcast())
                .attribute_mutated(self, AttributeMutation::Set(Some(&value)));
        }
    }

    /// Used to swap the attribute's value without triggering mutation events
    pub fn swap_value(&self, value: &mut AttrValue) {
        mem::swap(&mut *self.value.borrow_mut(), value);
    }

    pub fn identifier(&self) -> &AttrIdentifier {
        &self.identifier
    }

    pub fn value(&self) -> Ref<AttrValue> {
        self.value.borrow()
    }

    pub fn local_name(&self) -> &LocalName {
        &self.identifier.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    pub fn set_owner(&self, owner: Option<&Element>) {
        let ns = &self.identifier.namespace;
        match (self.owner(), owner) {
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(
                    old.get_attribute(&ns, &self.identifier.local_name)
                        .as_deref() !=
                        Some(self)
                )
            },
            (Some(old), Some(new)) => assert_eq!(&*old, new),
            _ => {},
        }
        self.owner.set(owner);
    }

    pub fn owner(&self) -> Option<DomRoot<Element>> {
        self.owner.get()
    }

    pub fn summarize(&self) -> AttrInfo {
        AttrInfo {
            namespace: (*self.identifier.namespace).to_owned(),
            name: String::from(self.Name()),
            value: String::from(self.Value()),
        }
    }

    pub fn qualified_name(&self) -> DOMString {
        match self.prefix() {
            Some(ref prefix) => DOMString::from(format!("{}:{}", prefix, &**self.local_name())),
            None => DOMString::from(&**self.local_name()),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout<'dom> {
    fn value(self) -> &'dom AttrValue;
    fn value_ref_forever(self) -> &'dom str;
    fn value_tokens(self) -> Option<&'dom [Atom]>;
    fn local_name_atom(self) -> LocalName;
}

#[allow(unsafe_code)]
impl<'dom> AttrHelpersForLayout<'dom> for LayoutDom<'dom, Attr> {
    #[inline]
    fn value(self) -> &'dom AttrValue {
        unsafe { self.unsafe_get().value.borrow_for_layout() }
    }

    #[inline]
    fn value_ref_forever(self) -> &'dom str {
        &**self.value()
    }

    #[inline]
    fn value_tokens(self) -> Option<&'dom [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    fn local_name_atom(self) -> LocalName {
        unsafe { self.unsafe_get().identifier.local_name.clone() }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Dmitry Tantsur <divius.inside@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.

//! Various utilities.

use hyper::Client;
#[cfg(feature = "tls")]
use hyper::net::HttpsConnector;
#[cfg(feature = "tls")]
use hyper_rustls::TlsClient;

/// Create an HTTP(s) client.
#[cfg(feature = "tls")]
pub fn http_client() -> Client {
    let connector = HttpsConnector::new(TlsClient::new());
    Client::with_connector(connector)
}
#[cfg(not(feature = "tls"))]
pub fn http_client() -> Client {
    Client::new()
}
<commit_msg>Fix missing_docs warning when builting without TLS<commit_after>// Copyright 2017 Dmitry Tantsur <divius.inside@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.

//! Various utilities.

use hyper::Client;
#[cfg(feature = "tls")]
use hyper::net::HttpsConnector;
#[cfg(feature = "tls")]
use hyper_rustls::TlsClient;

/// Create an HTTP(s) client.
#[cfg(feature = "tls")]
pub fn http_client() -> Client {
    let connector = HttpsConnector::new(TlsClient::new());
    Client::with_connector(connector)
}

/// Create an HTTP-only client.
#[cfg(not(feature = "tls"))]
pub fn http_client() -> Client {
    Client::new()
}
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs. Stored as a vector of tuples for performance
  /// and to maintain key ordering.
  Object(LinearMap<Key, Value>),
  /// A list of values. Just a value, but using *only* integer keys.
  Array(Vec<Value>)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<Value> {
    match self {
      &Value::Null => if pointer.len() == 0 { Some(Value::Null) } else { None },
      &Value::Boolean(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Number(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::String(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Object(ref map) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else {
          let key = pointer.remove(0);
          if let Some(value) = map.get(&key) {
            value.get(pointer)
          } else {
            None
          }
        }
      },
      &Value::Array(ref vec) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else {
          let key = pointer.remove(0);
          if let Some(index) = key.parse::<usize>().ok() {
            if let Some(value) = vec.get(index) {
              value.get(pointer)
            } else {
              None
            }
          } else {
            None
          }
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(vnull!().get(point![]), Some(vnull!()));
    assert_eq!(vnull!().get(point!["hello"]), None);
    assert_eq!(vnull!().get(point!["a", "b", "c", "d", "e"]), None);
    assert_eq!(vbool!(true).get(point![]), Some(vbool!(true)));
    assert_eq!(vbool!(true).get(point!["hello"]), None);
    assert_eq!(vnum!(36f64).get(point![]), Some(vnum!(36f64)));
    assert_eq!(vnum!(36f64).get(point!["hello"]), None);
    assert_eq!(vstring!("world").get(point![]), Some(vstring!("world")));
    assert_eq!(vstring!("world").get(point!["hello"]), None);
  }

  #[test]
  fn test_get_object() {
    let object = vobject!{
      "hello" => vbool!(true),
      "world" => vnum!(8f64),
      "5" => vnull!(),
      "moon" => vobject!{
        "hello" => vstring!("yoyo")
      }
    };
    assert_eq!(object.get(point![]), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]), Some(vbool!(true)));
    assert_eq!(object.get(point!["5"]), Some(vnull!()));
    assert_eq!(object.get(point!["world", "hello"]), None);
    assert_eq!(object.get(point!["moon", "hello"]), Some(vstring!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]), None);
  }

  #[test]
  fn test_get_array() {
    let array = varray![
      vbool!(false),
      vnum!(64f64),
      vobject!{
        "hello" => vbool!(true),
        "world" => vbool!(false),
        "moon" => vobject!{
          "goodbye" => vstring!("yoyo")
        }
      },
      varray![
        varray![
          vnum!(1f64),
          vnum!(2f64),
          vnum!(3f64)
        ],
        vnum!(4f64),
        vnum!(5f64)
      ]
    ];
    assert_eq!(array.get(point![]), Some(array.clone()));
    assert_eq!(array.get(point!["0"]), Some(vbool!(false)));
    assert_eq!(array.get(point!["1"]), Some(vnum!(64f64)));
    assert_eq!(array.get(point!["2", "hello"]), Some(vbool!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]), Some(vstring!("yoyo")));
    assert_eq!(array.get(point!["length"]), None);
    assert_eq!(array.get(point!["3", "0", "1"]), Some(vnum!(2f64)));
  }
}
<commit_msg>refactor: clean up nasty if trees<commit_after>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs. Stored as a vector of tuples for performance
  /// and to maintain key ordering.
  Object(LinearMap<Key, Value>),
  /// A list of values. Just a value, but using *only* integer keys.
  Array(Vec<Value>)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<Value> {
    match self {
      &Value::Null => if pointer.len() == 0 { Some(Value::Null) } else { None },
      &Value::Boolean(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Number(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::String(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Object(ref map) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      &Value::Array(ref vec) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(vnull!().get(point![]), Some(vnull!()));
    assert_eq!(vnull!().get(point!["hello"]), None);
    assert_eq!(vnull!().get(point!["a", "b", "c", "d", "e"]), None);
    assert_eq!(vbool!(true).get(point![]), Some(vbool!(true)));
    assert_eq!(vbool!(true).get(point!["hello"]), None);
    assert_eq!(vnum!(36f64).get(point![]), Some(vnum!(36f64)));
    assert_eq!(vnum!(36f64).get(point!["hello"]), None);
    assert_eq!(vstring!("world").get(point![]), Some(vstring!("world")));
    assert_eq!(vstring!("world").get(point!["hello"]), None);
  }

  #[test]
  fn test_get_object() {
    let object = vobject!{
      "hello" => vbool!(true),
      "world" => vnum!(8f64),
      "5" => vnull!(),
      "moon" => vobject!{
        "hello" => vstring!("yoyo")
      }
    };
    assert_eq!(object.get(point![]), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]), Some(vbool!(true)));
    assert_eq!(object.get(point!["5"]), Some(vnull!()));
    assert_eq!(object.get(point!["world", "hello"]), None);
    assert_eq!(object.get(point!["moon", "hello"]), Some(vstring!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]), None);
  }

  #[test]
  fn test_get_array() {
    let array = varray![
      vbool!(false),
      vnum!(64f64),
      vobject!{
        "hello" => vbool!(true),
        "world" => vbool!(false),
        "moon" => vobject!{
          "goodbye" => vstring!("yoyo")
        }
      },
      varray![
        varray![
          vnum!(1f64),
          vnum!(2f64),
          vnum!(3f64)
        ],
        vnum!(4f64),
        vnum!(5f64)
      ]
    ];
    assert_eq!(array.get(point![]), Some(array.clone()));
    assert_eq!(array.get(point!["0"]), Some(vbool!(false)));
    assert_eq!(array.get(point!["1"]), Some(vnum!(64f64)));
    assert_eq!(array.get(point!["2", "hello"]), Some(vbool!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]), Some(vstring!("yoyo")));
    assert_eq!(array.get(point!["length"]), None);
    assert_eq!(array.get(point!["3", "0", "1"]), Some(vnum!(2f64)));
  }
}
<|endoftext|>


<commit_before>use serde::Serialize;
use serde_json::value::{to_value, Value as Json};

#[derive(Debug)]
pub enum ScopedJson<'reg: 'rc, 'rc> {
    Constant(&'reg Json),
    Derived(Json),
    Context(&'rc Json),
}

impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc> {
    pub fn as_json(&self) -> &Json {
        match self {
            ScopedJson::Constant(j) => j,
            ScopedJson::Derived(ref j) => j,
            ScopedJson::Context(j) => j,
        }
    }

    pub fn render(&self) -> String {
        self.as_json().render()
    }
}

impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
    fn from(v: Json) -> ScopedJson<'reg, 'rc> {
        ScopedJson::Derived(v)
    }
}

/// Json wrapper that holds the Json value and reference path information
///
#[derive(Debug)]
pub struct PathAndJson<'reg: 'rc, 'rc> {
    path: Option<String>,
    value: ScopedJson<'reg, 'rc>,
}

impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
    pub fn new(path: Option<String>, value: ScopedJson<'reg, 'rc>) -> PathAndJson<'reg, 'rc> {
        PathAndJson { path, value }
    }

    /// Returns relative path when the value is referenced
    /// If the value is from a literal, the path is `None`
    pub fn path(&self) -> Option<&String> {
        self.path.as_ref()
    }

    /// Return root level of this path if any
    pub fn path_root(&self) -> Option<&str> {
        self.path
            .as_ref()
            .and_then(|p| p.split(|c| c == '.' || c == '/').nth(0))
    }

    /// Returns the value
    pub fn value(&self) -> &Json {
        self.value.as_json()
    }
}

/// Render Json data with default format
pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(ref s) => s.to_string(),
            Json::Bool(i) => i.to_string(),
            Json::Number(ref n) => n.to_string(),
            Json::Null => "".to_owned(),
            Json::Array(ref a) => {
                let mut buf = String::new();
                buf.push('[');
                for i in a.iter() {
                    buf.push_str(i.render().as_ref());
                    buf.push_str(", ");
                }
                buf.push(']');
                buf
            }
            Json::Object(_) => "[object]".to_owned(),
        }
    }
}

pub fn to_json<T>(src: &T) -> Json
where
    T: Serialize,
{
    to_value(src).unwrap_or_default()
}

pub fn as_string(src: &Json) -> Option<&str> {
    src.as_str()
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::Bool(ref i) => *i,
            Json::Number(ref n) => n.as_f64().map(|f| f.is_normal()).unwrap_or(false),
            Json::Null => false,
            Json::String(ref i) => i.len() > 0,
            Json::Array(ref i) => i.len() > 0,
            Json::Object(ref i) => i.len() > 0,
        }
    }
}

#[test]
fn test_json_render() {
    let raw = "
Hello world
\n<p thing=\"hello\"
";
    let thing = Json::String(raw.to_string());

    assert_eq!(raw, thing.render());
}
<commit_msg>(doc) added docs for ScopedJson<commit_after>use serde::Serialize;
use serde_json::value::{to_value, Value as Json};

/// A JSON wrapper designed for handlebars internal use case
///
/// * Constant: the JSON value hardcoded into template
/// * Context:  the JSON value referenced in your provided data context
/// * Derived:  the owned JSON value computed during rendering process
///
#[derive(Debug)]
pub enum ScopedJson<'reg: 'rc, 'rc> {
    Constant(&'reg Json),
    Derived(Json),
    Context(&'rc Json),
}

impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc> {
    /// get the JSON reference
    pub fn as_json(&self) -> &Json {
        match self {
            ScopedJson::Constant(j) => j,
            ScopedJson::Derived(ref j) => j,
            ScopedJson::Context(j) => j,
        }
    }

    pub fn render(&self) -> String {
        self.as_json().render()
    }
}

impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
    fn from(v: Json) -> ScopedJson<'reg, 'rc> {
        ScopedJson::Derived(v)
    }
}

/// Json wrapper that holds the Json value and reference path information
///
#[derive(Debug)]
pub struct PathAndJson<'reg: 'rc, 'rc> {
    path: Option<String>,
    value: ScopedJson<'reg, 'rc>,
}

impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
    pub fn new(path: Option<String>, value: ScopedJson<'reg, 'rc>) -> PathAndJson<'reg, 'rc> {
        PathAndJson { path, value }
    }

    /// Returns relative path when the value is referenced
    /// If the value is from a literal, the path is `None`
    pub fn path(&self) -> Option<&String> {
        self.path.as_ref()
    }

    /// Return root level of this path if any
    pub fn path_root(&self) -> Option<&str> {
        self.path
            .as_ref()
            .and_then(|p| p.split(|c| c == '.' || c == '/').nth(0))
    }

    /// Returns the value
    pub fn value(&self) -> &Json {
        self.value.as_json()
    }
}

/// Render Json data with default format
pub trait JsonRender {
    fn render(&self) -> String;
}

pub trait JsonTruthy {
    fn is_truthy(&self) -> bool;
}

impl JsonRender for Json {
    fn render(&self) -> String {
        match *self {
            Json::String(ref s) => s.to_string(),
            Json::Bool(i) => i.to_string(),
            Json::Number(ref n) => n.to_string(),
            Json::Null => "".to_owned(),
            Json::Array(ref a) => {
                let mut buf = String::new();
                buf.push('[');
                for i in a.iter() {
                    buf.push_str(i.render().as_ref());
                    buf.push_str(", ");
                }
                buf.push(']');
                buf
            }
            Json::Object(_) => "[object]".to_owned(),
        }
    }
}

pub fn to_json<T>(src: &T) -> Json
where
    T: Serialize,
{
    to_value(src).unwrap_or_default()
}

pub fn as_string(src: &Json) -> Option<&str> {
    src.as_str()
}

impl JsonTruthy for Json {
    fn is_truthy(&self) -> bool {
        match *self {
            Json::Bool(ref i) => *i,
            Json::Number(ref n) => n.as_f64().map(|f| f.is_normal()).unwrap_or(false),
            Json::Null => false,
            Json::String(ref i) => i.len() > 0,
            Json::Array(ref i) => i.len() > 0,
            Json::Object(ref i) => i.len() > 0,
        }
    }
}

#[test]
fn test_json_render() {
    let raw = "
Hello world
\n<p thing=\"hello\"
";
    let thing = Json::String(raw.to_string());

    assert_eq!(raw, thing.render());
}
<|endoftext|>