<commit_before>
//! Constructor methods for ndarray
//!
use libnum;

use imp_prelude::*;
use dimension;
use linspace;
use error::{self, ShapeError};

/// Constructor methods for one-dimensional arrays.
impl<S> ArrayBase<S, Ix>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no allocation needed).
    pub fn from_vec(v: Vec<S::Elem>) -> ArrayBase<S, Ix> {
        unsafe { Self::from_vec_dim_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    pub fn from_iter<I: IntoIterator<Item=S::Elem>>(iterable: I) -> ArrayBase<S, Ix> {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    pub fn linspace<F>(start: F, end: F, n: usize) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::linspace(start, end, n))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, (Ix, Ix)>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> ArrayBase<S, (Ix, Ix)>
        where S: DataMut,
              A: Clone + libnum::Zero + libnum::One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

/// Constructor methods for arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    ///
    /// ```
    /// use ndarray::RcArray;
    /// use ndarray::arr3;
    ///
    /// let a = RcArray::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// ```
    pub fn from_elem(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array with copies of `elem`, dimension `dim` and fortran
    /// memory order.
    ///
    /// **Panics** if the number of elements would overflow usize.
    ///
    /// ```
    /// use ndarray::RcArray;
    /// use ndarray::arr3;
    ///
    /// let a = RcArray::from_elem_f((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked_f(dim, v) }
    }

    /// Create an array with zeros, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem(dim, libnum::zero())
    }

    /// Create an array with zeros, dimension `dim` and fortran memory order.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros_f(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem_f(dim, libnum::zero())
    }

    /// Create an array with default values, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn default(dim: D) -> ArrayBase<S, D>
        where A: Default
    {
        let v = (0..dim.size()).map(|_| A::default()).collect();
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array from a vector (with no allocation needed).
    ///
    /// **Errors** if `dim` does not correspond to the number of elements in `v`.
    pub fn from_vec_dim(dim: D, v: Vec) -> Result<ArrayBase<S, D>, ShapeError> {
        if dim.size_checked() != Some(v.len()) {
            return Err(error::incompatible_shapes(&v.len(), &dim));
        }
        unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
    }

    /// Create an array from a vector (with no allocation needed).
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.default_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector (with no allocation needed),
    /// using fortran memory order to interpret the data.
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked_f(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.fortran_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Checks whether `dim` and `strides` are compatible with the vector's
    /// length, returning an `Err` if not compatible.
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    pub fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<ArrayBase<S, D>, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> ArrayBase<S, D>
    {
        debug_assert!(dimension::can_index_slice(&v, &dim, &strides).is_ok());
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}

<commit_msg>Edit docs for constructors<commit_after>
//! Constructor methods for ndarray
//!
use libnum;

use imp_prelude::*;
use dimension;
use linspace;
use error::{self, ShapeError};

/// Constructor methods for one-dimensional arrays.
impl<S> ArrayBase<S, Ix>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no allocation needed).
    pub fn from_vec(v: Vec<S::Elem>) -> ArrayBase<S, Ix> {
        unsafe { Self::from_vec_dim_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    pub fn from_iter(iterable: I) -> ArrayBase<S, Ix>
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    pub fn linspace<F>(start: F, end: F, n: usize) -> ArrayBase<S, Ix>
        where S: Data<Elem=F>,
              F: libnum::Float,
    {
        Self::from_iter(linspace::linspace(start, end, n))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, (Ix, Ix)>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> ArrayBase<S, (Ix, Ix)>
        where S: DataMut,
              A: Clone + libnum::Zero + libnum::One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    /// use ndarray::arr3;
    ///
    /// let a = OwnedArray::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    /// ```
    pub fn from_elem(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array with copies of `elem`, dimension `dim` and fortran
    /// memory order.
    ///
    /// **Panics** if the number of elements would overflow usize.
    ///
    /// ```
    /// use ndarray::OwnedArray;
    ///
    /// let a = OwnedArray::from_elem_f((2, 2, 2), 1.);
    /// assert!(a.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem_f(dim: D, elem: A) -> ArrayBase<S, D>
        where A: Clone
    {
        let size = dim.size_checked().expect("Shape too large: overflow in size");
        let v = vec![elem; size];
        unsafe { Self::from_vec_dim_unchecked_f(dim, v) }
    }

    /// Create an array with zeros, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem(dim, libnum::zero())
    }

    /// Create an array with zeros, dimension `dim` and fortran memory order.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn zeros_f(dim: D) -> ArrayBase<S, D>
        where A: Clone + libnum::Zero
    {
        Self::from_elem_f(dim, libnum::zero())
    }

    /// Create an array with default values, dimension `dim`.
    ///
    /// **Panics** if the number of elements in `dim` would overflow usize.
    pub fn default(dim: D) -> ArrayBase<S, D>
        where A: Default
    {
        let v = (0..dim.size()).map(|_| A::default()).collect();
        unsafe { Self::from_vec_dim_unchecked(dim, v) }
    }

    /// Create an array from a vector (with no allocation needed).
    ///
    /// **Errors** if `dim` does not correspond to the number of elements in `v`.
    pub fn from_vec_dim(dim: D, v: Vec) -> Result<ArrayBase<S, D>, ShapeError> {
        if dim.size_checked() != Some(v.len()) {
            return Err(error::incompatible_shapes(&v.len(), &dim));
        }
        unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
    }

    /// Create an array from a vector (with no allocation needed).
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.default_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector (with no allocation needed),
    /// using fortran memory order to interpret the data.
    ///
    /// Unsafe because dimension is unchecked, and must be correct.
    pub unsafe fn from_vec_dim_unchecked_f(dim: D, mut v: Vec) -> ArrayBase<S, D> {
        debug_assert!(dim.size_checked() == Some(v.len()));
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: dim.fortran_strides(),
            dim: dim,
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Checks whether `dim` and `strides` are compatible with the vector's
    /// length, returning an `Err` if not compatible.
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    pub fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<ArrayBase<S, D>, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. No allocation needed.
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> ArrayBase<S, D>
    {
        debug_assert!(dimension::can_index_slice(&v, &dim, &strides).is_ok());
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}

<|endoftext|>


<commit_before>use base::noise::{PermutationTable, open_simplex2};
use base::gen::seeded_rng;
use base::rand::Rand;

pub fn create_noise(seed: u64) -> Vec<Vec<(f32, f32, f32)>> {
    let mut texture_rng = seeded_rng(seed, 13, ());
    let table = PermutationTable::rand(&mut texture_rng);

    let mut v = vec![Vec::new(); 256];
    for i in 0..256 {
        for j in 0..256 {
            let s = (open_simplex2::<f32>(&table, &[(i as f32) * 0.25, (j as f32) * 0.25]) + 1.0) /
                    2.0;
            v[i].push((s, s, s));
        }
    }
    v
}
<commit_msg>Height maps for grass, sand and snow<commit_after>use base::noise::{PermutationTable, open_simplex2};
use base::gen::seeded_rng;
use base::rand::Rand;

pub fn create_noise(seed: u64) -> Vec<Vec<(f32, f32, f32)>> {
    let mut texture_rng = seeded_rng(seed, 13, ());
    let table = PermutationTable::rand(&mut texture_rng);

    let mut v = vec![Vec::new(); 256];
    for i in 0..256 {
        for j in 0..256 {
            let s = (open_simplex2::<f32>(&table, &[(i as f32) * 0.25, (j as f32) * 0.25]) + 1.0) /
                    2.0;
            v[i].push((s, s, s));
        }
    }
    v
}

pub fn create_height_map_for_snow(seed: u64) -> Vec<Vec<f32>> {
    let mut texture_rng = seeded_rng(seed, 13, ());
    let table = PermutationTable::rand(&mut texture_rng);
    let mut snow_height_map = vec![Vec::new(); 256];

    for i in 0..256 {
        for j in 0..256 {
            let e = ((open_simplex2::<f32>(&table, &[(i as f32), (j as f32)]) + 1.0) / 2.0) +
                    0.5 *
                    ((open_simplex2::<f32>(&table, &[(i as f32) * 2.0, (j as f32) * 2.0]) +
                      1.0) / 2.0) +
                    0.25 *
                    ((open_simplex2::<f32>(&table, &[(i as f32) * 4.0, (j as f32) * 4.0]) + 1.0) /
                     2.0);
            snow_height_map[i].push(e.powf(0.35));
        }
    }
    snow_height_map
}

pub fn create_height_map_for_sand(seed: u64) -> Vec<Vec<f32>> {
    let mut texture_rng = seeded_rng(seed, 13, ());
    let table = PermutationTable::rand(&mut texture_rng);
    let mut sand_height_map = vec![Vec::new(); 256];

    for i in 0..256 {
        for j in 0..256 {
            let e = (open_simplex2::<f32>(&table, &[(i as f32) * 1.14, (j as f32) * 1.14]) + 1.0) /
                    2.0;
            sand_height_map[i].push(e);
        }
    }
    sand_height_map
}

pub fn create_height_map_for_grass(seed: u64) -> Vec<Vec<f32>> {
    let mut texture_rng = seeded_rng(seed, 13, ());
    let table = PermutationTable::rand(&mut texture_rng);
    let mut grass_height_map = vec![Vec::new(); 256];

    for i in 0..256 {
        for j in 0..256 {
            let e = ((open_simplex2::<f32>(&table, &[(i as f32) * 7.0, (j as f32)]) + 7.0) / 2.0) +
                    0.5 *
                    ((open_simplex2::<f32>(&table, &[(i as f32) * 9.0, (j as f32) * 9.0]) + 1.0) /
                     2.0);
            grass_height_map[i].push(e.powf(0.35));
        }
    }
    grass_height_map
}
<|endoftext|>


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

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```ignore
//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    let (expr, file, line) = *expr_file_line;
    panic_fmt(format_args!("{}", expr), &(file, line))
}

#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line)
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { panic_impl(fmt, file, line as uint) }
}
<commit_msg>Auto merge of #22948 - rprichard:simple-panic-opt, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```ignore
//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    let (expr, file, line) = *expr_file_line;
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line))
}

#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line)
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { panic_impl(fmt, file, line as uint) }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

pub struct ChatJson {
    pub msg: Message,
    pub extra: Option<Vec<Json>>,
    pub color: Option<Color>,
    pub formats: Option<Vec<Format>>,
    pub click_event: Option<ClickEvent>,
    pub hover_event: Option<HoverEvent>,
    pub insertion: Option<String>
}

impl ChatJson {
    pub fn msg(msg: String) -> ChatJson {
        ChatJson {
            msg: Message::PlainText(msg), extra: None, color: None, formats: None,
            click_event: None, hover_event: None, insertion: None
        }
    }
}

impl ToJson for ChatJson {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        match self.msg {
            Message::PlainText(ref text) => {
                d.insert("text".to_string(), text.to_json());
            },
            _ => unimplemented!()
        };

        if let Some(ref extra) = self.extra {
            d.insert("extra".to_string(), extra.to_json());
        }
        if let Some(ref color) = self.color {
            d.insert("color".to_string(), color.to_string().to_json());
        }
        if let Some(ref event) = self.click_event {
            d.insert("clickEvent".to_string(), event.to_json());
        }
        if let Some(ref event) = self.hover_event {
            d.insert("hoverEvent".to_string(), event.to_json());
        }
        if let Some(ref ins) = self.insertion {
            d.insert("insertion".to_string(), ins.to_json());
        }

        Json::Object(d)
    }
}

pub enum Message {
    PlainText(String),
    Score(String, String),
    Translatable,
    Selector
}

pub enum ClickEvent {
    OpenUrl(String),
    OpenFile(String),
    RunCommand(String),
    SuggestCommand(String)
}

impl ToJson for ClickEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &ClickEvent::OpenUrl(ref url) => {
                d.insert("action".to_string(), "open_url".to_json());
                d.insert("value".to_string(), url.to_json());
            },
            &ClickEvent::OpenFile(ref file) => {
                d.insert("action".to_string(), "open_file".to_json());
                d.insert("value".to_string(), file.to_json());
            },
            &ClickEvent::RunCommand(ref cmd) => {
                d.insert("action".to_string(), "run_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            },
            &ClickEvent::SuggestCommand(ref cmd) => {
                d.insert("action".to_string(), "suggest_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            }
        }
        Json::Object(d)
    }
}

pub enum HoverEvent {
    Text(String),
    Achievement(String),
    Item(String)
}

impl ToJson for HoverEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &HoverEvent::Text(ref text) => {
                d.insert("action".to_string(), "show_text".to_json());
                d.insert("value".to_string(), text.to_json());
            },
            &HoverEvent::Achievement(ref ach) => {
                d.insert("action".to_string(), "show_achievement".to_json());
                d.insert("value".to_string(), ach.to_json());
            },
            &HoverEvent::Item(ref item) => {
                d.insert("action".to_string(), "show_item".to_json());
                // The string is actually a JSON object, just in the form of a
                // string.
                d.insert("value".to_string(), item.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Copy, FromPrimitive)]
pub enum Color {
    Black       = 0x0,
    DarkBlue    = 0x1,
    DarkGreen   = 0x2,
    DarkCyan    = 0x3,
    DarkRed     = 0x4,
    Purple      = 0x5,
    Gold        = 0x6,
    Gray        = 0x7,
    DarkGray    = 0x8,
    Blue        = 0x9,
    BrightGreen = 0xa,
    Cyan        = 0xb,
    Red         = 0xc,
    Pink        = 0xd,
    Yellow      = 0xe,
    White       = 0xf
}

impl Color {
    pub fn to_code(&self) -> u8 {
        (*self) as u8
    }

    pub fn to_string(&self) -> String {
        match self {
            &Color::Black => "black".to_string(),
            &Color::DarkBlue => "dark_blue".to_string(),
            &Color::DarkGreen => "dark_green".to_string(),
            &Color::DarkCyan => "dark_aqua".to_string(),
            &Color::DarkRed => "dark_red".to_string(),
            &Color::Purple => "dark_purple".to_string(),
            &Color::Gold => "gold".to_string(),
            &Color::Gray => "gray".to_string(),
            &Color::DarkGray => "dark_gray".to_string(),
            &Color::Blue => "blue".to_string(),
            &Color::BrightGreen => "green".to_string(),
            &Color::Cyan => "aqua".to_string(),
            &Color::Red => "red".to_string(),
            &Color::Pink => "light_purple".to_string(),
            &Color::Yellow => "yellow".to_string(),
            &Color::White => "white".to_string()
        }
    }

    pub fn from_string(string: &String) -> Option<Color> {
        match string.as_slice() {
            "black"        => Some(Color::Black),
            "dark_blue"    => Some(Color::DarkBlue),
            "dark_green"   => Some(Color::DarkGreen),
            "dark_aqua"    => Some(Color::DarkCyan),
            "dark_red"     => Some(Color::DarkRed),
            "dark_purple"  => Some(Color::Purple),
            "gold"         => Some(Color::Gold),
            "gray"         => Some(Color::Gray),
            "dark_gray"    => Some(Color::DarkGray),
            "blue"         => Some(Color::Blue),
            "green"        => Some(Color::BrightGreen),
            "aqua"         => Some(Color::Cyan),
            "red"          => Some(Color::Red),
            "light_purple" => Some(Color::Pink),
            "yellow"       => Some(Color::Yellow),
            "white"        => Some(Color::White),
            _              => None
        }
    }
}

pub enum Format {
    Bold, Underlined, Strikethrough, Italic, Obfuscated, Random, Reset
}

#[cfg(test)]
mod test {
    use super::*;
    use rustc_serialize::json::ToJson;

    #[test]
    fn chat_plain() {
        let msg = ChatJson::msg("Hello, world!".to_string());
        println!("{}", msg.to_json());
    }
}
<commit_msg>chat: Implements a first pass at decoding from JSON.<commit_after>use std::collections::{BTreeMap, BTreeSet};
use std::io;
use std::error::FromError;

use rustc_serialize::json;
use rustc_serialize::json::{Json, ToJson};

#[derive(Clone, Debug)]
pub enum ChatJsonError {
    MalformedJson(json::ParserError),
    IoError(io::Error),
    InvalidObject,
    InvalidField,
    UnknownField,
    UnknownColor,
    InvalidClickEvent,
    InvalidHoverEvent
}

impl FromError<io::Error> for ChatJsonError {
    fn from_error(err: io::Error) -> ChatJsonError {
        ChatJsonError::IoError(err)
    }
}

impl FromError<json::ParserError> for ChatJsonError {
    fn from_error(err: json::ParserError) -> ChatJsonError {
        if let json::ParserError::IoError(e) = err {
            ChatJsonError::IoError(e)
        } else {
            ChatJsonError::MalformedJson(err)
        }
    }
}

#[derive(Clone, Debug)]
pub struct ChatJson {
    pub msg: Message,
    pub extra: Option<Vec<Json>>,
    pub color: Option<Color>,
    pub formats: BTreeSet<Format>,
    pub click_event: Option<ClickEvent>,
    pub hover_event: Option<HoverEvent>,
    pub insertion: Option<String>
}

impl ChatJson {
    pub fn msg(msg: String) -> ChatJson {
        ChatJson {
            msg: Message::PlainText(msg), extra: None, color: None, formats: BTreeSet::new(),
            click_event: None, hover_event: None, insertion: None
        }
    }

    pub fn from_json<T: Iterator<Item=char>>(src: T) -> Result<ChatJson, ChatJsonError> {
        let json = try!(json::Builder::new(src).build());
        if let Json::Object(map) = json {
            let mut result = ChatJson::msg("".to_string());
            for (key, value) in map {
                println!("{:?}: {:?}", key, value);
                match key.as_slice() {
                    "text" => {
                        if let Json::String(string) = value {
                            result.msg = Message::PlainText(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "insertion" => {
                        if let Json::String(string) = value {
                            result.insertion = Some(string);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    "color" => {
                        if let Json::String(string) = value {
                            result.color = match Color::from_string(&string) {
                                None => return Err(ChatJsonError::UnknownColor),
                                c => c
                            };
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle all of the different format strings.
                    "bold"|"italic"|"underlined"|"strikethrough"|"obfuscated"|"reset"|"random" => {
                        if let Json::Boolean(b) = value {
                            if b == true {
                                result.formats.insert(Format::from_string(&key).unwrap());
                            }
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // Handle the JSON format of click events.
                    "clickEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidClickEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.click_event = match string.as_slice() {
                                    "open_url" => Some(ClickEvent::OpenUrl(val)),
                                    "open_file" => Some(ClickEvent::OpenFile(val)),
                                    "run_command" => Some(ClickEvent::RunCommand(val)),
                                    "suggest_command" => Some(ClickEvent::SuggestCommand(val)),
                                    _ => return Err(ChatJsonError::InvalidClickEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidClickEvent);
                            }
                        }
                    },
                    // Handle the JSON format of hover events.
                    "hoverEvent" => {
                        if let Json::Object(event) = value {
                            // Get the `value` first.
                            let val: String = match event.get("value") {
                                Some(&Json::String(ref string)) => string.clone(),
                                _ => return Err(ChatJsonError::InvalidHoverEvent)
                            };
                            // Handle the different click events.
                            if let Some(&Json::String(ref string)) = event.get("action") {
                                result.hover_event = match string.as_slice() {
                                    "show_text" => Some(HoverEvent::Text(val)),
                                    "show_achievement" => Some(HoverEvent::Achievement(val)),
                                    "show_item" => Some(HoverEvent::Item(val)),
                                    _ => return Err(ChatJsonError::InvalidHoverEvent)
                                };
                            } else {
                                return Err(ChatJsonError::InvalidHoverEvent);
                            }
                        }
                    },
                    "extra" => {
                        if let Json::Array(extra) = value {
                            result.extra = Some(extra);
                        } else {
                            return Err(ChatJsonError::InvalidField);
                        }
                    },
                    // TODO: Error on unknown key when the implementation is complete.
                    _ => (),
                };
            }
            Ok(result)
        } else {
            Err(ChatJsonError::InvalidObject)
        }
    }
}

impl ToJson for ChatJson {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        match self.msg {
            Message::PlainText(ref text) => {
                d.insert("text".to_string(), text.to_json());
            },
            _ => unimplemented!()
        };

        if let Some(ref extra) = self.extra {
            d.insert("extra".to_string(), extra.to_json());
        }
        if let Some(ref color) = self.color {
            d.insert("color".to_string(), color.to_string().to_json());
        }
        if let Some(ref event) = self.click_event {
            d.insert("clickEvent".to_string(), event.to_json());
        }
        if let Some(ref event) = self.hover_event {
            d.insert("hoverEvent".to_string(), event.to_json());
        }
        if let Some(ref ins) = self.insertion {
            d.insert("insertion".to_string(), ins.to_json());
        }

        Json::Object(d)
    }
}

#[derive(Clone, Debug)]
pub enum Message {
    PlainText(String),
    Score(String, String),
    Translatable,
    Selector
}

#[derive(Clone, Debug)]
pub enum ClickEvent {
    OpenUrl(String),
    OpenFile(String),
    RunCommand(String),
    SuggestCommand(String)
}

impl ToJson for ClickEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &ClickEvent::OpenUrl(ref url) => {
                d.insert("action".to_string(), "open_url".to_json());
                d.insert("value".to_string(), url.to_json());
            },
            &ClickEvent::OpenFile(ref file) => {
                d.insert("action".to_string(), "open_file".to_json());
                d.insert("value".to_string(), file.to_json());
            },
            &ClickEvent::RunCommand(ref cmd) => {
                d.insert("action".to_string(), "run_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            },
            &ClickEvent::SuggestCommand(ref cmd) => {
                d.insert("action".to_string(), "suggest_command".to_json());
                d.insert("value".to_string(), cmd.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Clone, Debug)]
pub enum HoverEvent {
    Text(String),
    Achievement(String),
    Item(String)
}

impl ToJson for HoverEvent {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self {
            &HoverEvent::Text(ref text) => {
                d.insert("action".to_string(), "show_text".to_json());
                d.insert("value".to_string(), text.to_json());
            },
            &HoverEvent::Achievement(ref ach) => {
                d.insert("action".to_string(), "show_achievement".to_json());
                d.insert("value".to_string(), ach.to_json());
            },
            &HoverEvent::Item(ref item) => {
                d.insert("action".to_string(), "show_item".to_json());
                // The string is actually a JSON object, just in the form of a
                // string.
                d.insert("value".to_string(), item.to_json());
            }
        }
        Json::Object(d)
    }
}

#[derive(Copy, Debug, Clone)]
pub enum Color {
    Black       = 0x0,
    DarkBlue    = 0x1,
    DarkGreen   = 0x2,
    DarkCyan    = 0x3,
    DarkRed     = 0x4,
    Purple      = 0x5,
    Gold        = 0x6,
    Gray        = 0x7,
    DarkGray    = 0x8,
    Blue        = 0x9,
    BrightGreen = 0xa,
    Cyan        = 0xb,
    Red         = 0xc,
    Pink        = 0xd,
    Yellow      = 0xe,
    White       = 0xf
}

impl Color {
    pub fn to_string(&self) -> String {
        match self {
            &Color::Black => "black".to_string(),
            &Color::DarkBlue => "dark_blue".to_string(),
            &Color::DarkGreen => "dark_green".to_string(),
            &Color::DarkCyan => "dark_aqua".to_string(),
            &Color::DarkRed => "dark_red".to_string(),
            &Color::Purple => "dark_purple".to_string(),
            &Color::Gold => "gold".to_string(),
            &Color::Gray => "gray".to_string(),
            &Color::DarkGray => "dark_gray".to_string(),
            &Color::Blue => "blue".to_string(),
            &Color::BrightGreen => "green".to_string(),
            &Color::Cyan => "aqua".to_string(),
            &Color::Red => "red".to_string(),
            &Color::Pink => "light_purple".to_string(),
            &Color::Yellow => "yellow".to_string(),
            &Color::White => "white".to_string()
        }
    }

    pub fn from_string(string: &String) -> Option<Color> {
        match string.as_slice() {
            "black"        => Some(Color::Black),
            "dark_blue"    => Some(Color::DarkBlue),
            "dark_green"   => Some(Color::DarkGreen),
            "dark_aqua"    => Some(Color::DarkCyan),
            "dark_red"     => Some(Color::DarkRed),
            "dark_purple"  => Some(Color::Purple),
            "gold"         => Some(Color::Gold),
            "gray"         => Some(Color::Gray),
            "dark_gray"    => Some(Color::DarkGray),
            "blue"         => Some(Color::Blue),
            "green"        => Some(Color::BrightGreen),
            "aqua"         => Some(Color::Cyan),
            "red"          => Some(Color::Red),
            "light_purple" => Some(Color::Pink),
            "yellow"       => Some(Color::Yellow),
            "white"        => Some(Color::White),
            _              => None
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum Format {
    Bold, Underlined, Strikethrough, Italic, Obfuscated, Random, Reset
}

impl Format {
    pub fn from_string(string: &String) -> Option<Format> {
        match string.as_slice() {
            "bold"          => Some(Format::Bold),
            "italic"        => Some(Format::Italic),
            "underlined"    => Some(Format::Underlined),
            "strikethrough" => Some(Format::Strikethrough),
            "obfuscated"    => Some(Format::Obfuscated),
            "random"        => Some(Format::Random),
            "reset"         => Some(Format::Reset),
            _               => None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use rustc_serialize::json::ToJson;

    #[test]
    fn chat_plain() {
        let msg = ChatJson::msg("Hello, world!".to_string());
        println!("{}", msg.to_json());
    }

    #[test]
    fn chat_extra() {
        let blob = r#"{
            "text": "Hello world",
            "extra": [
                "Testing",
                {"translate":"demo.day.2"}
            ],
            "bold":true,
            "italic":false,
            "underlined": false,
            "strikethrough": true,
            "obfuscated": false,
            "color":"red",
            "clickEvent":{
                "action":"run_command",
                "value": "/time set day"
            },
            "hoverEvent": {
                "action":"show_text",
                "value": "Hello"
            },
            "insertion": "Hello world"
        }"#;

        let parsed = ChatJson::from_json(blob.chars());
        println!("{:?}", parsed);
    }
}
<|endoftext|>


<commit_before>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: CharPos,
    hi: CharPos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

pub struct Loc<A: Pos> {
    file: @FileMap, line: uint, col: A
}

/// An absolute offset within the CodeMap (not a relative offset within a
/// a single FileMap)
pub struct FilePos {
    ch: CharPos, byte: BytePos
}

impl FilePos : cmp::Eq {
    pure fn eq(other: &FilePos) -> bool {
        self.ch == (*other).ch && self.byte == (*other).byte
    }
    pure fn ne(other: &FilePos) -> bool { !self.eq(other) }
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub type LookupFn = pure fn(FilePos) -> uint;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: FilePos,
    mut lines: ~[FilePos]
}

pub impl FileMap {
    static fn new_w_substr(+filename: FileName, +substr: FileSubstr,
                           src: @~str,
                           +start_pos: FilePos)
        -> FileMap {
        return FileMap {
            name: filename, substr: substr, src: src,
            start_pos: start_pos,
            mut lines: ~[]
        };
    }

    static fn new(+filename: FileName, src: @~str,
                  +start_pos: FilePos)
        -> FileMap {
        return FileMap::new_w_substr(filename, FssNone, src,
                                     start_pos);
    }

    fn next_line(@self, +pos: FilePos) {
        self.lines.push(pos);
    }

    pub fn get_line(@self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line].byte - self.start_pos.byte;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    pub fn add_filemap(@self, filemap: @FileMap) {
        let expected_byte_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.byte.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };
        let actual_byte_pos = filemap.start_pos.byte.to_uint();
        debug!("codemap: adding filemap: %s", filemap.name);
        debug!("codemap: expected offset: %u", expected_byte_pos);
        debug!("codemap: actual offset: %u", actual_byte_pos);
        assert expected_byte_pos == actual_byte_pos;
        self.files.push(filemap);
    }

    pub fn mk_substr_filename(@self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(@self, +pos: CharPos) -> Loc<CharPos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_byte_pos(@self, +pos: BytePos) -> Loc<BytePos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.byte.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_char_pos_adj(@self, +pos: CharPos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos.ch))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(@self, sp: span) -> span {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let line = self.lookup_line(sp.lo, lookup);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                    hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(@self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(@self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(@self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    fn lookup_byte_offset(@self, +chpos: CharPos)
        -> {fm: @FileMap, pos: BytePos} {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let {fm, line} = self.lookup_line(chpos, lookup);
        let line_offset = fm.lines[line].byte - fm.start_pos.byte;
        let col = chpos - fm.lines[line].ch;
        let col_offset = str::count_bytes(*fm.src,
                                          line_offset.to_uint(),
                                          col.to_uint());
        {fm: fm, pos: line_offset + BytePos(col_offset)}
    }

    pub fn span_to_snippet(@self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(@self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {
    fn lookup_line<A: Pos>(@self, pos: A, lookup: LookupFn)
        -> {fm: @FileMap, line: uint}
    {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(self.files[m].start_pos) > pos.to_uint() {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }
        let f = self.files[a];
        a = 0u;
        b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(f.lines[m]) > pos.to_uint() { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos<A: Pos Num>(@self, pos: A, lookup: LookupFn) -> Loc<A> {
        let {fm: f, line: a} = self.lookup_line(pos, lookup);
        return Loc {
            file: f,
            line: a + 1u,
            col: pos - from_uint(lookup(f.lines[a]))
        };
    }

    fn span_to_str_no_adj(@self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>Convert CodeMap and FileMap to use &self instead of @self<commit_after>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: CharPos,
    hi: CharPos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

pub struct Loc<A: Pos> {
    file: @FileMap, line: uint, col: A
}

/// An absolute offset within the CodeMap (not a relative offset within a
/// a single FileMap)
pub struct FilePos {
    ch: CharPos, byte: BytePos
}

impl FilePos : cmp::Eq {
    pure fn eq(other: &FilePos) -> bool {
        self.ch == (*other).ch && self.byte == (*other).byte
    }
    pure fn ne(other: &FilePos) -> bool { !self.eq(other) }
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub type LookupFn = pure fn(FilePos) -> uint;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: FilePos,
    mut lines: ~[FilePos]
}

pub impl FileMap {
    static fn new_w_substr(+filename: FileName, +substr: FileSubstr,
                           src: @~str,
                           +start_pos: FilePos)
        -> FileMap {
        return FileMap {
            name: filename, substr: substr, src: src,
            start_pos: start_pos,
            mut lines: ~[]
        };
    }

    static fn new(+filename: FileName, src: @~str,
                  +start_pos: FilePos)
        -> FileMap {
        return FileMap::new_w_substr(filename, FssNone, src,
                                     start_pos);
    }

    fn next_line(&self, +pos: FilePos) {
        self.lines.push(pos);
    }

    pub fn get_line(&self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line].byte - self.start_pos.byte;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    pub fn add_filemap(&self, filemap: @FileMap) {
        let expected_byte_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.byte.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };
        let actual_byte_pos = filemap.start_pos.byte.to_uint();
        debug!("codemap: adding filemap: %s", filemap.name);
        debug!("codemap: expected offset: %u", expected_byte_pos);
        debug!("codemap: actual offset: %u", actual_byte_pos);
        assert expected_byte_pos == actual_byte_pos;
        self.files.push(filemap);
    }

    pub fn mk_substr_filename(&self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(&self, +pos: CharPos) -> Loc<CharPos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_byte_pos(&self, +pos: BytePos) -> Loc<BytePos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.byte.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_char_pos_adj(&self, +pos: CharPos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos.ch))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(&self, sp: span) -> span {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let line = self.lookup_line(sp.lo, lookup);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                    hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(&self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(&self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    fn lookup_byte_offset(&self, +chpos: CharPos)
        -> {fm: @FileMap, pos: BytePos} {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let {fm, line} = self.lookup_line(chpos, lookup);
        let line_offset = fm.lines[line].byte - fm.start_pos.byte;
        let col = chpos - fm.lines[line].ch;
        let col_offset = str::count_bytes(*fm.src,
                                          line_offset.to_uint(),
                                          col.to_uint());
        {fm: fm, pos: line_offset + BytePos(col_offset)}
    }

    pub fn span_to_snippet(&self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(&self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {
    fn lookup_line<A: Pos>(&self, pos: A, lookup: LookupFn)
        -> {fm: @FileMap, line: uint}
    {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(self.files[m].start_pos) > pos.to_uint() {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }
        let f = self.files[a];
        a = 0u;
        b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(f.lines[m]) > pos.to_uint() { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos<A: Pos Num>(&self, pos: A, lookup: LookupFn) -> Loc<A> {
        let {fm: f, line: a} = self.lookup_line(pos, lookup);
        return Loc {
            file: f,
            line: a + 1u,
            col: pos - from_uint(lookup(f.lines[a]))
        };
    }

    fn span_to_str_no_adj(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable reference to the object owned by this UniquePtr if
    /// any, otherwise None.
    pub fn as_mut(&mut self) -> Option<&mut T> {
        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    const __NAME: &'static str;
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    const __NAME: &'static str = "CxxString";
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<commit_msg>Deref and DerefMut for UniquePtr<commit_after>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable reference to the object owned by this UniquePtr if
    /// any, otherwise None.
    pub fn as_mut(&mut self) -> Option<&mut T> {
        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Deref for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        match self.as_ref() {
            Some(target) => target,
            None => panic!("called deref on a null UniquePtr"),
        }
    }
}

impl<T> DerefMut for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self.as_mut() {
            Some(target) => target,
            None => panic!("called deref_mut on a null UniquePtr"),
        }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    const __NAME: &'static str;
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    const __NAME: &'static str = "CxxString";
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<|endoftext|>