<commit_before>use stable_deref_trait::StableDeref;

use crate::common::HasLen;
use crate::directory::OwnedBytes;
use std::ops::Range;
use std::sync::{Arc, Weak};
use std::{io, ops::Deref};

pub type ArcBytes = Arc<dyn Deref<Target = [u8]> + Send + Sync + 'static>;
pub type WeakArcBytes = Weak<dyn Deref<Target = [u8]> + Send + Sync + 'static>;

/// Objects that represents files sections in tantivy.
///
/// By contract, whatever happens to the directory file, as long as a FileHandle
/// is alive, the data associated with it cannot be altered or destroyed.
///
/// The underlying behavior is therefore specific to the `Directory` that created it.
/// Despite its name, a `FileSlice` may or may not directly map to an actual file
/// on the filesystem.
pub trait FileHandle: 'static + Send + Sync + HasLen {
    /// Reads a slice of bytes.
    ///
    /// This method may panic if the range requested is invalid.
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes>;
}

impl FileHandle for &'static [u8] {
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        let bytes = &self[range];
        Ok(OwnedBytes::new(bytes))
    }
}

impl<T: Deref<Target = [u8]>> HasLen for T {
    fn len(&self) -> usize {
        self.deref().len()
    }
}

impl<B> From<B> for FileSlice
where
    B: StableDeref + Deref<Target = [u8]> + 'static + Send + Sync,
{
    fn from(bytes: B) -> FileSlice {
        FileSlice::new(Box::new(OwnedBytes::new(bytes)))
    }
}

/// Logical slice of read only file in tantivy.
///
/// It can be cloned and sliced cheaply.
///
#[derive(Clone)]
pub struct FileSlice {
    data: Arc<dyn FileHandle>,
    range: Range<usize>,
}

impl FileSlice {
    /// Wraps a FileHandle.
    pub fn new(file_handle: Box<dyn FileHandle>) -> Self {
        let num_bytes = file_handle.len();
        FileSlice::new_with_num_bytes(file_handle, num_bytes)
    }

    /// Wraps a FileHandle.
    #[doc(hidden)]
    pub fn new_with_num_bytes(file_handle: Box<dyn FileHandle>, num_bytes: usize) -> Self {
        FileSlice {
            data: Arc::from(file_handle),
            range: 0..num_bytes,
        }
    }

    /// Creates a fileslice that is just a view over a slice of the data.
    ///
    /// # Panics
    ///
    /// Panics if `byte_range.end` exceeds the filesize.
    pub fn slice(&self, byte_range: Range<usize>) -> FileSlice {
        assert!(byte_range.end <= self.len());
        FileSlice {
            data: self.data.clone(),
            range: self.range.start + byte_range.start..self.range.start + byte_range.end,
        }
    }

    /// Creates an empty FileSlice
    pub fn empty() -> FileSlice {
        const EMPTY_SLICE: &[u8] = &[];
        FileSlice::from(EMPTY_SLICE)
    }

    /// Returns a `OwnedBytes` with all of the data in the `FileSlice`.
    ///
    /// The behavior is strongly dependant on the implementation of the underlying
    /// `Directory` and the `FileSliceTrait` it creates.
    /// In particular, it is  up to the `Directory` implementation
    /// to handle caching if needed.
    pub fn read_bytes(&self) -> io::Result<OwnedBytes> {
        self.data.read_bytes(self.range.clone())
    }

    /// Reads a specific slice of data.
    ///
    /// This is equivalent to running `file_slice.slice(from, to).read_bytes()`.
    pub fn read_bytes_slice(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        assert!(
            range.end <= self.len(),
            "end of requested range exceeds the fileslice length ({} > {})",
            range.end,
            self.len()
        );
        self.data
            .read_bytes(self.range.start + range.start..self.range.start + range.end)
    }

    /// Splits the FileSlice at the given offset and return two file slices.
    /// `file_slice[..split_offset]` and `file_slice[split_offset..]`.
    ///
    /// This operation is cheap and must not copy any underlying data.
    pub fn split(self, left_len: usize) -> (FileSlice, FileSlice) {
        let left = self.slice_to(left_len);
        let right = self.slice_from(left_len);
        (left, right)
    }

    /// Splits the file slice at the given offset and return two file slices.
    /// `file_slice[..split_offset]` and `file_slice[split_offset..]`.
    pub fn split_from_end(self, right_len: usize) -> (FileSlice, FileSlice) {
        let left_len = self.len() - right_len;
        self.split(left_len)
    }

    /// Like `.slice(...)` but enforcing only the `from`
    /// boundary.
    ///
    /// Equivalent to `.slice(from_offset, self.len())`
    pub fn slice_from(&self, from_offset: usize) -> FileSlice {
        self.slice(from_offset..self.len())
    }

    /// Like `.slice(...)` but enforcing only the `to`
    /// boundary.
    ///
    /// Equivalent to `.slice(0, to_offset)`
    pub fn slice_to(&self, to_offset: usize) -> FileSlice {
        self.slice(0..to_offset)
    }
}

impl FileHandle for FileSlice {
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        self.read_bytes_slice(range)
    }
}

impl HasLen for FileSlice {
    fn len(&self) -> usize {
        self.range.len()
    }
}

#[cfg(test)]
mod tests {
    use super::{FileHandle, FileSlice};
    use crate::common::HasLen;
    use std::io;

    #[test]
    fn test_file_slice() -> io::Result<()> {
        let file_slice = FileSlice::new(Box::new(b"abcdef".as_ref()));
        assert_eq!(file_slice.len(), 6);
        assert_eq!(file_slice.slice_from(2).read_bytes()?.as_slice(), b"cdef");
        assert_eq!(file_slice.slice_to(2).read_bytes()?.as_slice(), b"ab");
        assert_eq!(
            file_slice
                .slice_from(1)
                .slice_to(2)
                .read_bytes()?
                .as_slice(),
            b"bc"
        );
        {
            let (left, right) = file_slice.clone().split(0);
            assert_eq!(left.read_bytes()?.as_slice(), b"");
            assert_eq!(right.read_bytes()?.as_slice(), b"abcdef");
        }
        {
            let (left, right) = file_slice.clone().split(2);
            assert_eq!(left.read_bytes()?.as_slice(), b"ab");
            assert_eq!(right.read_bytes()?.as_slice(), b"cdef");
        }
        {
            let (left, right) = file_slice.clone().split_from_end(0);
            assert_eq!(left.read_bytes()?.as_slice(), b"abcdef");
            assert_eq!(right.read_bytes()?.as_slice(), b"");
        }
        {
            let (left, right) = file_slice.clone().split_from_end(2);
            assert_eq!(left.read_bytes()?.as_slice(), b"abcd");
            assert_eq!(right.read_bytes()?.as_slice(), b"ef");
        }
        Ok(())
    }

    #[test]
    fn test_file_slice_trait_slice_len() {
        let blop: &'static [u8] = b"abc";
        let owned_bytes: Box<dyn FileHandle> = Box::new(blop);
        assert_eq!(owned_bytes.len(), 3);
    }

    #[test]
    fn test_slice_simple_read() -> io::Result<()> {
        let slice = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(slice.len(), 6);
        assert_eq!(slice.read_bytes()?.as_ref(), b"abcdef");
        assert_eq!(slice.slice(1..4).read_bytes()?.as_ref(), b"bcd");
        Ok(())
    }

    #[test]
    fn test_slice_read_slice() -> io::Result<()> {
        let slice_deref = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(slice_deref.read_bytes_slice(1..4)?.as_ref(), b"bcd");
        Ok(())
    }

    #[test]
    #[should_panic(expected = "end of requested range exceeds the fileslice length (10 > 6)")]
    fn test_slice_read_slice_invalid_range_exceeds() {
        let slice_deref = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(
            slice_deref.read_bytes_slice(0..10).unwrap().as_ref(),
            b"bcd"
        );
    }
}
<commit_msg>Added debug to FileHandle<commit_after>use stable_deref_trait::StableDeref;

use crate::common::HasLen;
use crate::directory::OwnedBytes;
use std::fmt;
use std::ops::Range;
use std::sync::{Arc, Weak};
use std::{io, ops::Deref};

pub type ArcBytes = Arc<dyn Deref<Target = [u8]> + Send + Sync + 'static>;
pub type WeakArcBytes = Weak<dyn Deref<Target = [u8]> + Send + Sync + 'static>;

/// Objects that represents files sections in tantivy.
///
/// By contract, whatever happens to the directory file, as long as a FileHandle
/// is alive, the data associated with it cannot be altered or destroyed.
///
/// The underlying behavior is therefore specific to the `Directory` that created it.
/// Despite its name, a `FileSlice` may or may not directly map to an actual file
/// on the filesystem.
pub trait FileHandle: 'static + Send + Sync + HasLen + fmt::Debug {
    /// Reads a slice of bytes.
    ///
    /// This method may panic if the range requested is invalid.
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes>;
}

impl FileHandle for &'static [u8] {
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        let bytes = &self[range];
        Ok(OwnedBytes::new(bytes))
    }
}

impl<T: Deref<Target = [u8]>> HasLen for T {
    fn len(&self) -> usize {
        self.deref().len()
    }
}

impl<B> From<B> for FileSlice
where
    B: StableDeref + Deref<Target = [u8]> + 'static + Send + Sync,
{
    fn from(bytes: B) -> FileSlice {
        FileSlice::new(Box::new(OwnedBytes::new(bytes)))
    }
}

/// Logical slice of read only file in tantivy.
///
/// It can be cloned and sliced cheaply.
///
#[derive(Clone)]
pub struct FileSlice {
    data: Arc<dyn FileHandle>,
    range: Range<usize>,
}

impl fmt::Debug for FileSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FileSlice({:?}, {:?})", &self.data, self.range)
    }
}

impl FileSlice {
    /// Wraps a FileHandle.
    pub fn new(file_handle: Box<dyn FileHandle>) -> Self {
        let num_bytes = file_handle.len();
        FileSlice::new_with_num_bytes(file_handle, num_bytes)
    }

    /// Wraps a FileHandle.
    #[doc(hidden)]
    pub fn new_with_num_bytes(file_handle: Box<dyn FileHandle>, num_bytes: usize) -> Self {
        FileSlice {
            data: Arc::from(file_handle),
            range: 0..num_bytes,
        }
    }

    /// Creates a fileslice that is just a view over a slice of the data.
    ///
    /// # Panics
    ///
    /// Panics if `byte_range.end` exceeds the filesize.
    pub fn slice(&self, byte_range: Range<usize>) -> FileSlice {
        assert!(byte_range.end <= self.len());
        FileSlice {
            data: self.data.clone(),
            range: self.range.start + byte_range.start..self.range.start + byte_range.end,
        }
    }

    /// Creates an empty FileSlice
    pub fn empty() -> FileSlice {
        const EMPTY_SLICE: &[u8] = &[];
        FileSlice::from(EMPTY_SLICE)
    }

    /// Returns a `OwnedBytes` with all of the data in the `FileSlice`.
    ///
    /// The behavior is strongly dependant on the implementation of the underlying
    /// `Directory` and the `FileSliceTrait` it creates.
    /// In particular, it is  up to the `Directory` implementation
    /// to handle caching if needed.
    pub fn read_bytes(&self) -> io::Result<OwnedBytes> {
        self.data.read_bytes(self.range.clone())
    }

    /// Reads a specific slice of data.
    ///
    /// This is equivalent to running `file_slice.slice(from, to).read_bytes()`.
    pub fn read_bytes_slice(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        assert!(
            range.end <= self.len(),
            "end of requested range exceeds the fileslice length ({} > {})",
            range.end,
            self.len()
        );
        self.data
            .read_bytes(self.range.start + range.start..self.range.start + range.end)
    }

    /// Splits the FileSlice at the given offset and return two file slices.
    /// `file_slice[..split_offset]` and `file_slice[split_offset..]`.
    ///
    /// This operation is cheap and must not copy any underlying data.
    pub fn split(self, left_len: usize) -> (FileSlice, FileSlice) {
        let left = self.slice_to(left_len);
        let right = self.slice_from(left_len);
        (left, right)
    }

    /// Splits the file slice at the given offset and return two file slices.
    /// `file_slice[..split_offset]` and `file_slice[split_offset..]`.
    pub fn split_from_end(self, right_len: usize) -> (FileSlice, FileSlice) {
        let left_len = self.len() - right_len;
        self.split(left_len)
    }

    /// Like `.slice(...)` but enforcing only the `from`
    /// boundary.
    ///
    /// Equivalent to `.slice(from_offset, self.len())`
    pub fn slice_from(&self, from_offset: usize) -> FileSlice {
        self.slice(from_offset..self.len())
    }

    /// Like `.slice(...)` but enforcing only the `to`
    /// boundary.
    ///
    /// Equivalent to `.slice(0, to_offset)`
    pub fn slice_to(&self, to_offset: usize) -> FileSlice {
        self.slice(0..to_offset)
    }
}

impl FileHandle for FileSlice {
    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
        self.read_bytes_slice(range)
    }
}

impl HasLen for FileSlice {
    fn len(&self) -> usize {
        self.range.len()
    }
}

#[cfg(test)]
mod tests {
    use super::{FileHandle, FileSlice};
    use crate::common::HasLen;
    use std::io;

    #[test]
    fn test_file_slice() -> io::Result<()> {
        let file_slice = FileSlice::new(Box::new(b"abcdef".as_ref()));
        assert_eq!(file_slice.len(), 6);
        assert_eq!(file_slice.slice_from(2).read_bytes()?.as_slice(), b"cdef");
        assert_eq!(file_slice.slice_to(2).read_bytes()?.as_slice(), b"ab");
        assert_eq!(
            file_slice
                .slice_from(1)
                .slice_to(2)
                .read_bytes()?
                .as_slice(),
            b"bc"
        );
        {
            let (left, right) = file_slice.clone().split(0);
            assert_eq!(left.read_bytes()?.as_slice(), b"");
            assert_eq!(right.read_bytes()?.as_slice(), b"abcdef");
        }
        {
            let (left, right) = file_slice.clone().split(2);
            assert_eq!(left.read_bytes()?.as_slice(), b"ab");
            assert_eq!(right.read_bytes()?.as_slice(), b"cdef");
        }
        {
            let (left, right) = file_slice.clone().split_from_end(0);
            assert_eq!(left.read_bytes()?.as_slice(), b"abcdef");
            assert_eq!(right.read_bytes()?.as_slice(), b"");
        }
        {
            let (left, right) = file_slice.clone().split_from_end(2);
            assert_eq!(left.read_bytes()?.as_slice(), b"abcd");
            assert_eq!(right.read_bytes()?.as_slice(), b"ef");
        }
        Ok(())
    }

    #[test]
    fn test_file_slice_trait_slice_len() {
        let blop: &'static [u8] = b"abc";
        let owned_bytes: Box<dyn FileHandle> = Box::new(blop);
        assert_eq!(owned_bytes.len(), 3);
    }

    #[test]
    fn test_slice_simple_read() -> io::Result<()> {
        let slice = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(slice.len(), 6);
        assert_eq!(slice.read_bytes()?.as_ref(), b"abcdef");
        assert_eq!(slice.slice(1..4).read_bytes()?.as_ref(), b"bcd");
        Ok(())
    }

    #[test]
    fn test_slice_read_slice() -> io::Result<()> {
        let slice_deref = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(slice_deref.read_bytes_slice(1..4)?.as_ref(), b"bcd");
        Ok(())
    }

    #[test]
    #[should_panic(expected = "end of requested range exceeds the fileslice length (10 > 6)")]
    fn test_slice_read_slice_invalid_range_exceeds() {
        let slice_deref = FileSlice::new(Box::new(&b"abcdef"[..]));
        assert_eq!(
            slice_deref.read_bytes_slice(0..10).unwrap().as_ref(),
            b"bcd"
        );
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate ryu;

use std::mem;

use rand::{Rng, SeedableRng};

const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;

struct MeanAndVariance {
    n: i64,
    mean: f64,
    m2: f64,
}

impl MeanAndVariance {
    fn new() -> Self {
        MeanAndVariance {
            n: 0,
            mean: 0.0,
            m2: 0.0,
        }
    }

    fn update(&mut self, x: f64) {
        self.n += 1;
        let d = x - self.mean;
        self.mean += d / self.n as f64;
        let d2 = x - self.mean;
        self.m2 += d * d2;
    }

    fn variance(&self) -> f64 {
        self.m2 / (self.n - 1) as f64
    }
}

macro_rules! benchmark {
    ($name:ident, |$var:ident: $ty:ident| $computation:expr) => {
        fn $name() -> usize {
            let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
            let mut mv = MeanAndVariance::new();
            let mut throwaway = 0;
            for _ in 0..SAMPLES {
                let $var = $ty::from_bits(rng.gen());

                let t1 = std::time::SystemTime::now();
                for _ in 0..ITERATIONS {
                    throwaway += $computation;
                }
                let duration = t1.elapsed().unwrap();
                let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
                mv.update(nanos as f64 / ITERATIONS as f64);
            }
            println!(
                "{:12} {:8.3} {:8.3}",
                concat!(stringify!($name), ":"),
                mv.mean,
                mv.variance().sqrt()
            );
            throwaway
        }
    };
}

benchmark!(original32, |f: f32| unsafe {
    let mut buffer: [u8; 15] = mem::uninitialized();
    ryu::raw::f2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty32, |f: f32| ryu::Buffer::new().format(f).len());

benchmark!(original64, |f: f64| unsafe {
    let mut buffer: [u8; 24] = mem::uninitialized();
    ryu::raw::d2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty64, |f: f64| ryu::Buffer::new().format(f).len());

fn main() {
    println!("{:>20}{:>9}", "Average", "Stddev");
    let mut throwaway = 0;
    throwaway += original32();
    throwaway += pretty32();
    throwaway += original64();
    throwaway += pretty64();
    if std::env::var_os("ryu-benchmark").is_some() {
        // Prevent the compiler from optimizing the code away.
        println!("{}", throwaway);
    }
}
<commit_msg>Restrict benchmark to finite numbers<commit_after>extern crate rand;
extern crate ryu;

use std::mem;

use rand::{Rng, SeedableRng};

const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;

struct MeanAndVariance {
    n: i64,
    mean: f64,
    m2: f64,
}

impl MeanAndVariance {
    fn new() -> Self {
        MeanAndVariance {
            n: 0,
            mean: 0.0,
            m2: 0.0,
        }
    }

    fn update(&mut self, x: f64) {
        self.n += 1;
        let d = x - self.mean;
        self.mean += d / self.n as f64;
        let d2 = x - self.mean;
        self.m2 += d * d2;
    }

    fn variance(&self) -> f64 {
        self.m2 / (self.n - 1) as f64
    }
}

macro_rules! benchmark {
    ($name:ident, |$var:ident: $ty:ident| $computation:expr) => {
        fn $name() -> usize {
            let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
            let mut mv = MeanAndVariance::new();
            let mut throwaway = 0;
            for _ in 0..SAMPLES {
                let $var = loop {
                    let f = $ty::from_bits(rng.gen());
                    if f.is_finite() {
                        break f;
                    }
                };

                let t1 = std::time::SystemTime::now();
                for _ in 0..ITERATIONS {
                    throwaway += $computation;
                }
                let duration = t1.elapsed().unwrap();
                let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
                mv.update(nanos as f64 / ITERATIONS as f64);
            }
            println!(
                "{:12} {:8.3} {:8.3}",
                concat!(stringify!($name), ":"),
                mv.mean,
                mv.variance().sqrt()
            );
            throwaway
        }
    };
}

benchmark!(original32, |f: f32| unsafe {
    let mut buffer: [u8; 15] = mem::uninitialized();
    ryu::raw::f2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty32, |f: f32| ryu::Buffer::new().format(f).len());

benchmark!(original64, |f: f64| unsafe {
    let mut buffer: [u8; 24] = mem::uninitialized();
    ryu::raw::d2s_buffered_n(f, &mut buffer[0])
});

benchmark!(pretty64, |f: f64| ryu::Buffer::new().format(f).len());

fn main() {
    println!("{:>20}{:>9}", "Average", "Stddev");
    let mut throwaway = 0;
    throwaway += original32();
    throwaway += pretty32();
    throwaway += original64();
    throwaway += pretty64();
    if std::env::var_os("ryu-benchmark").is_some() {
        // Prevent the compiler from optimizing the code away.
        println!("{}", throwaway);
    }
}
<|endoftext|>


<commit_before>extern crate vec2;

use num::Num;

#[inline(always)]
pub fn compose<T: Num>(out: &mut [T; 6], position: [T; 3], scale: [T; 3], rotation: T) -> &mut [T; 6] {
    let sx = scale[0];
    let sy = scale[1];
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = c * sx;
    out[1] = s * sx;
    out[2] = -s * sy;
    out[3] = c * sy;
    out[4] = position[0];
    out[5] = position[1];
    out
}

#[inline(always)]
pub fn decompose<T: Num>(out: [T; 6], position: &mut [T; 3], scale: &mut [T; 3]) -> T {
    let m11 = out[0];
    let m12 = out[1];
    let sx = vec2::length_values(m11, m12);
    let sy = vec2::length_values(out[2], out[3]);

    position[0] = out[4];
    position[1] = out[5];

    scale[0] = sx;
    scale[1] = sy;

    m12.atan2(m11)
}

#[inline(always)]
pub fn look_at<T: Num>(out: &mut [T; 6], eye: [T; 3], target: [T; 3]) -> &mut [T; 6] {
    let x = target[0] - eye[0];
    let y = target[1] - eye[1];
    let a = y.atan2(x) - T::half_pi();
    let c = a.cos();
    let s = a.sin();

    out[0] = c;
    out[1] = s;
    out[2] = -s;
    out[3] = c;
    out
}

#[inline(always)]
pub fn set_rotation<T: Num>(out: &mut [T; 6], rotation: T) -> &mut [T; 6] {
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = c;
    out[1] = s;
    out[2] = -s;
    out[3] = c;
    out
}

#[inline(always)]
pub fn get_rotation<T: Num>(out: [T; 6]) -> T {
    out[1].atan2(out[0])
}

#[inline(always)]
pub fn set_position<T: Num>(out: &mut [T; 6], v: [T; 3]) -> &mut [T; 6] {
    out[4] = v[0];
    out[5] = v[1];
    out
}

#[inline(always)]
pub fn get_position<T: Num>(out: [T; 6], v: &mut [T; 3]) -> &mut [T; 3] {
    v[0] = out[4];
    v[1] = out[5];
    v
}

#[inline(always)]
pub fn extract_position<T: Num>(out: &mut [T; 6], a: [T; 6]) -> &mut [T; 6] {
    out[4] = a[4];
    out[5] = a[5];
    out
}

#[inline(always)]
pub fn extract_rotation<T: Num>(out: &mut [T; 6], a: [T; 6]) -> &mut [T; 6] {
    let m11 = a[0];
    let m12 = a[2];
    let m21 = a[1];
    let m22 = a[3];

    let x = m11 * m11 + m21 * m21;
    let y = m12 * m12 + m22 * m22;

    let sx = if x != T::zero() {T::one() / x.sqrt()} else {T::zero()};
    let sy = if y != T::zero() {T::one() / y.sqrt()} else {T::zero()};

    out[0] = m11 * sx;
    out[1] = m21 * sx;
    out[2] = m12 * sy;
    out[3] = m22 * sy;
    out
}

#[inline(always)]
pub fn translate<T: Num>(out: &mut [T; 6], a: [T; 6], v: [T; 3]) -> &mut [T; 6] {
    out[4] = a[0] * v[0] + a[2] * v[1] + a[4];
    out[5] = a[1] * v[0] + a[3] * v[1] + a[5];
    out
}

#[inline(always)]
pub fn rotate<T: Num>(out: &mut [T; 6], a: [T; 6], rotation: T) -> &mut [T; 6] {
    let m11 = a[0];
    let m12 = a[2];
    let m21 = a[1];
    let m22 = a[3];
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = m11 * c + m12 * s;
    out[1] = m11 * -s + m12 * c;
    out[2] = m21 * c + m22 * s;
    out[3] = m21 * -s + m22 * c;
    out
}

#[inline(always)]
pub fn scale<T: Num>(out: &mut [T; 6], a: [T; 6], v: [T; 3]) -> &mut [T; 6] {
    let x = v[0];
    let y = v[1];

    out[0] = a[0] * x;
    out[1] = a[1] * x;
    out[4] = a[4] * x;

    out[2] = a[2] * y;
    out[3] = a[3] * y;
    out[5] = a[5] * y;
    out
}

#[inline(always)]
pub fn orthographic<T: Num>(out: &mut [T; 6], left: T, right: T, top: T, bottom: T) -> &mut [T; 6] {
    let w = right - left;
    let h = top - bottom;

    let x = (right + left) / w;
    let y = (top + bottom) / h;

    out[0] = T::from_isize(2isize) / w;
    out[1] = T::zero();
    out[2] = T::zero();
    out[3] = T::from_isize(2isize) / h;
    out[4] = -x;
    out[5] = -y;
    out
}
<commit_msg>Num trait bug fix<commit_after>extern crate vec2;

use num::Num;

#[inline(always)]
pub fn compose<T: Num>(out: &mut [T; 6], position: [T; 3], scale: [T; 3], rotation: T) -> &mut [T; 6] {
    let sx = scale[0];
    let sy = scale[1];
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = c * sx;
    out[1] = s * sx;
    out[2] = -s * sy;
    out[3] = c * sy;
    out[4] = position[0];
    out[5] = position[1];
    out
}

#[inline(always)]
pub fn decompose<T: Num>(out: [T; 6], position: &mut [T; 3], scale: &mut [T; 3]) -> T {
    let m11 = out[0];
    let m12 = out[1];
    let sx = vec2::length_values(m11, m12);
    let sy = vec2::length_values(out[2], out[3]);

    position[0] = out[4];
    position[1] = out[5];

    scale[0] = sx;
    scale[1] = sy;

    m12.atan2(m11)
}

#[inline(always)]
pub fn look_at<T: Num>(out: &mut [T; 6], eye: [T; 3], target: [T; 3]) -> &mut [T; 6] {
    let x = target[0] - eye[0];
    let y = target[1] - eye[1];
    let a = y.atan2(x) - T::half_pi();
    let c = a.cos();
    let s = a.sin();

    out[0] = c;
    out[1] = s;
    out[2] = -s;
    out[3] = c;
    out
}

#[inline(always)]
pub fn set_rotation<T: Num>(out: &mut [T; 6], rotation: T) -> &mut [T; 6] {
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = c;
    out[1] = s;
    out[2] = -s;
    out[3] = c;
    out
}

#[inline(always)]
pub fn get_rotation<T: Num>(out: [T; 6]) -> T {
    out[1].atan2(out[0])
}

#[inline(always)]
pub fn set_position<T: Num>(out: &mut [T; 6], v: [T; 3]) -> &mut [T; 6] {
    out[4] = v[0];
    out[5] = v[1];
    out
}

#[inline(always)]
pub fn get_position<T: Num>(out: [T; 6], v: &mut [T; 3]) -> &mut [T; 3] {
    v[0] = out[4];
    v[1] = out[5];
    v
}

#[inline(always)]
pub fn extract_position<T: Num>(out: &mut [T; 6], a: [T; 6]) -> &mut [T; 6] {
    out[4] = a[4];
    out[5] = a[5];
    out
}

#[inline(always)]
pub fn extract_rotation<T: Num>(out: &mut [T; 6], a: [T; 6]) -> &mut [T; 6] {
    let m11 = a[0];
    let m12 = a[2];
    let m21 = a[1];
    let m22 = a[3];

    let x = m11 * m11 + m21 * m21;
    let y = m12 * m12 + m22 * m22;

    let sx = if x != T::zero() {T::one() / x.sqrt()} else {T::zero()};
    let sy = if y != T::zero() {T::one() / y.sqrt()} else {T::zero()};

    out[0] = m11 * sx;
    out[1] = m21 * sx;
    out[2] = m12 * sy;
    out[3] = m22 * sy;
    out
}

#[inline(always)]
pub fn translate<T: Num>(out: &mut [T; 6], a: [T; 6], v: [T; 3]) -> &mut [T; 6] {
    out[4] = a[0] * v[0] + a[2] * v[1] + a[4];
    out[5] = a[1] * v[0] + a[3] * v[1] + a[5];
    out
}

#[inline(always)]
pub fn rotate<T: Num>(out: &mut [T; 6], a: [T; 6], rotation: T) -> &mut [T; 6] {
    let m11 = a[0];
    let m12 = a[2];
    let m21 = a[1];
    let m22 = a[3];
    let c = rotation.cos();
    let s = rotation.sin();

    out[0] = m11 * c + m12 * s;
    out[1] = m11 * -s + m12 * c;
    out[2] = m21 * c + m22 * s;
    out[3] = m21 * -s + m22 * c;
    out
}

#[inline(always)]
pub fn scale<T: Num>(out: &mut [T; 6], a: [T; 6], v: [T; 3]) -> &mut [T; 6] {
    let x = v[0];
    let y = v[1];

    out[0] = a[0] * x;
    out[1] = a[1] * x;
    out[4] = a[4] * x;

    out[2] = a[2] * y;
    out[3] = a[3] * y;
    out[5] = a[5] * y;
    out
}

#[inline(always)]
pub fn orthographic<T: Num>(out: &mut [T; 6], left: T, right: T, top: T, bottom: T) -> &mut [T; 6] {
    let w = right - left;
    let h = top - bottom;

    let x = (right + left) / w;
    let y = (top + bottom) / h;

    out[0] = T::from_isize(2isize) / w;
    out[1] = T::zero();
    out[2] = T::zero();
    out[3] = T::from_isize(2isize) / h;
    out[4] = -x;
    out[5] = -y;
    out
}
<|endoftext|>


<commit_before>//! The types modules describes all the structures to express FITS files.

use std::str::FromStr;

#[derive(Debug, PartialEq)]
/// Representation of a FITS file.
pub struct Fits {
    /// The primary header
    pub primary_header: PrimaryHeader
}

impl Fits {
    /// Create a Fits structure with a given primary header
    pub fn new(primary_header: PrimaryHeader) -> Fits {
        Fits { primary_header: primary_header }
    }
}

#[derive(Debug, PartialEq)]
/// The primary header of a FITS file.
pub struct PrimaryHeader {
    /// The keyword records of the primary header.
    pub keyword_records: Vec<KeywordRecord>,
}

impl PrimaryHeader {
    /// Create a PrimaryHeader with a given set of keyword_records
    pub fn new(keyword_records: Vec<KeywordRecord>) -> PrimaryHeader {
        PrimaryHeader { keyword_records: keyword_records }
    }
}

#[derive(Debug, PartialEq)]
/// A keyword record contains information about a FITS header.
pub struct KeywordRecord {
    /// The keyword of this record.
    keyword: Keyword,
}

impl KeywordRecord {
    /// Create a `KeywordRecord` from a specific `Keyword`.
    pub fn new(keyword: Keyword) -> KeywordRecord {
        KeywordRecord { keyword : keyword }
    }
}

#[derive(Debug, PartialEq)]
/// A unit tuple that will act as a placeholder for blank records.
pub struct BlankRecord;

#[derive(Debug, PartialEq)]
#[allow(non_camel_case_types, missing_docs)]
/// The various keywords that can be found in headers.
pub enum Keyword {
    SIMPLE,
    BITPIX,
    NAXIS,
    NAXISn(u8),
    EXTEND,
    NEXTEND,
    EXTNAME,
    EXTVER,
    ORIGIN,
    DATE,
    CREATOR,
    PROCVER,
    FILEVER,
    TIMVERSN,
    TELESCOP,
    INSTRUME,
    OBJECT,
    KEPLERID,
    CHANNEL,
    MODULE,
    OUTPUT,
    CAMPAIGN,
    DATA_REL,
    OBSMODE,
    MISSION,
    TTABLEID,
    RADESYS,
    RA_OBJ,
    DEC_OBJ,
    EQUINOX,
    PMRA,
    PMDEC,
    PMTOTAL,
    PARALLAX,
    GLON,
    GLAT,
    GMAG,
    RMAG,
    IMAG,
    ZMAG,
    JMAG,
    HMAG,
    KMAG,
    KEPMAG,
    GRCOLOR,
    JKCOLOR,
    GKCOLOR,
    TEFF,
    LOGG,
    FEH,
    EBMINUSV,
    AV,
    RADIUS,
    TMINDEX,
    CHECKSUM,
    DATASUM,
    END,
}

/// Problems that could occur when parsing a `str` are enumerated here.
#[derive(Debug)]
pub enum ParseKeywordError {
    /// When a str can not be recognized as a keyword, this error will be returned
    UnknownKeyword
}

impl FromStr for Keyword {
    type Err = ParseKeywordError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // TODO parse NAXIS1 correctly
        match s.trim_right() {
            "SIMPLE" => Ok(Keyword::SIMPLE),
            "BITPIX" => Ok(Keyword::BITPIX),
            "NAXIS" => Ok(Keyword::NAXIS),
            "EXTEND" => Ok(Keyword::EXTEND),
            "NEXTEND" => Ok(Keyword::NEXTEND),
            "EXTNAME" => Ok(Keyword::EXTNAME),
            "EXTVER" => Ok(Keyword::EXTVER),
            "ORIGIN" => Ok(Keyword::ORIGIN),
            "DATE" => Ok(Keyword::DATE),
            "CREATOR" => Ok(Keyword::CREATOR),
            "PROCVER" => Ok(Keyword::PROCVER),
            "FILEVER" => Ok(Keyword::FILEVER),
            "TIMVERSN" => Ok(Keyword::TIMVERSN),
            "TELESCOP" => Ok(Keyword::TELESCOP),
            "INSTRUME" => Ok(Keyword::INSTRUME),
            "OBJECT" => Ok(Keyword::OBJECT),
            "KEPLERID" => Ok(Keyword::KEPLERID),
            "CHANNEL" => Ok(Keyword::CHANNEL),
            "MODULE" => Ok(Keyword::MODULE),
            "OUTPUT" => Ok(Keyword::OUTPUT),
            "CAMPAIGN" => Ok(Keyword::CAMPAIGN),
            "DATA_REL" => Ok(Keyword::DATA_REL),
            "OBSMODE" => Ok(Keyword::OBSMODE),
            "MISSION" => Ok(Keyword::MISSION),
            "TTABLEID" => Ok(Keyword::TTABLEID),
            "RADESYS" => Ok(Keyword::RADESYS),
            "RA_OBJ" => Ok(Keyword::RA_OBJ),
            "DEC_OBJ" => Ok(Keyword::DEC_OBJ),
            "EQUINOX" => Ok(Keyword::EQUINOX),
            "PMRA" => Ok(Keyword::PMRA),
            "PMDEC" => Ok(Keyword::PMDEC),
            "PMTOTAL" => Ok(Keyword::PMTOTAL),
            "PARALLAX" => Ok(Keyword::PARALLAX),
            "GLON" => Ok(Keyword::GLON),
            "GLAT" => Ok(Keyword::GLAT),
            "GMAG" => Ok(Keyword::GMAG),
            "RMAG" => Ok(Keyword::RMAG),
            "IMAG" => Ok(Keyword::IMAG),
            "ZMAG" => Ok(Keyword::ZMAG),
            "JMAG" => Ok(Keyword::JMAG),
            "HMAG" => Ok(Keyword::HMAG),
            "KMAG" => Ok(Keyword::KMAG),
            "KEPMAG" => Ok(Keyword::KEPMAG),
            "GRCOLOR" => Ok(Keyword::GRCOLOR),
            "JKCOLOR" => Ok(Keyword::JKCOLOR),
            "GKCOLOR" => Ok(Keyword::GKCOLOR),
            "TEFF" => Ok(Keyword::TEFF),
            "LOGG" => Ok(Keyword::LOGG),
            "FEH" => Ok(Keyword::FEH),
            "EBMINUSV" => Ok(Keyword::EBMINUSV),
            "AV" => Ok(Keyword::AV),
            "RADIUS" => Ok(Keyword::RADIUS),
            "TMINDEX" => Ok(Keyword::TMINDEX),
            "CHECKSUM" => Ok(Keyword::CHECKSUM),
            "DATASUM" => Ok(Keyword::DATASUM),
            "END" => Ok(Keyword::END),
            _ => Err(ParseKeywordError::UnknownKeyword)
        }
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;
    use super::*;

    fn fits_constructed_from_the_new_function_should_eq_hand_construction() {
        assert_eq!(
            Fits { primary_header: PrimaryHeader::new(vec!()) },
            Fits::new(PrimaryHeader::new(vec!()))
        );
    }

    fn primary_header_constructed_from_the_new_function_shoul_eq_hand_construction() {
        assert_eq!(
            PrimaryHeader { keyword_records: vec!(
                KeywordRecord::new(Keyword::SIMPLE),
                KeywordRecord::new(Keyword::NEXTEND),
            )},
            PrimaryHeader::new(vec!(
                KeywordRecord::new(Keyword::SIMPLE),
                KeywordRecord::new(Keyword::NEXTEND),
            ))
        );
    }

    #[test]
    fn keyword_record_constructed_from_the_new_function_should_eq_hand_construction() {
        assert_eq!(
            KeywordRecord { keyword: Keyword::ORIGIN },
            KeywordRecord::new(Keyword::ORIGIN));
    }

    #[test]
    fn keywords_could_be_constructed_from_str() {
        let data = vec!(
            ("SIMPLE", Keyword::SIMPLE),
            ("BITPIX", Keyword::BITPIX),
            ("NAXIS", Keyword::NAXIS),
            ("EXTEND", Keyword::EXTEND),
            ("NEXTEND", Keyword::NEXTEND),
            ("EXTVER", Keyword::EXTVER),
            ("ORIGIN", Keyword::ORIGIN),
            ("DATE", Keyword::DATE),
            ("CREATOR", Keyword::CREATOR),
            ("PROCVER", Keyword::PROCVER),
            ("FILEVER", Keyword::FILEVER),
            ("TIMVERSN", Keyword::TIMVERSN),
            ("TELESCOP", Keyword::TELESCOP),
            ("INSTRUME", Keyword::INSTRUME),
            ("OBJECT", Keyword::OBJECT),
            ("KEPLERID", Keyword::KEPLERID),
            ("CHANNEL", Keyword::CHANNEL),
            ("MODULE", Keyword::MODULE),
            ("OUTPUT", Keyword::OUTPUT),
            ("CAMPAIGN", Keyword::CAMPAIGN),
            ("DATA_REL", Keyword::DATA_REL),
            ("OBSMODE", Keyword::OBSMODE),
            ("MISSION", Keyword::MISSION),
            ("TTABLEID", Keyword::TTABLEID),
            ("RADESYS", Keyword::RADESYS),
            ("RA_OBJ", Keyword::RA_OBJ),
            ("DEC_OBJ", Keyword::DEC_OBJ),
            ("EQUINOX", Keyword::EQUINOX),
            ("PMRA", Keyword::PMRA),
            ("PMDEC", Keyword::PMDEC),
            ("PMTOTAL", Keyword::PMTOTAL),
            ("PARALLAX", Keyword::PARALLAX),
            ("GLON", Keyword::GLON),
            ("GLAT", Keyword::GLAT),
            ("GMAG", Keyword::GMAG),
            ("RMAG", Keyword::RMAG),
            ("IMAG", Keyword::IMAG),
            ("ZMAG", Keyword::ZMAG),
            ("JMAG", Keyword::JMAG),
            ("HMAG", Keyword::HMAG),
            ("KMAG", Keyword::KMAG),
            ("KEPMAG", Keyword::KEPMAG),
            ("GRCOLOR", Keyword::GRCOLOR),
            ("JKCOLOR", Keyword::JKCOLOR),
            ("GKCOLOR", Keyword::GKCOLOR),
            ("TEFF", Keyword::TEFF),
            ("LOGG", Keyword::LOGG),
            ("FEH", Keyword::FEH),
            ("EBMINUSV", Keyword::EBMINUSV),
            ("AV", Keyword::AV),
            ("RADIUS", Keyword::RADIUS),
            ("TMINDEX", Keyword::TMINDEX),
            ("CHECKSUM", Keyword::CHECKSUM),
            ("DATASUM", Keyword::DATASUM),
            ("END", Keyword::END),
        );

        for (input, expected) in data {
            assert_eq!(Keyword::from_str(input).unwrap(), expected);
        }
    }

    #[test]
    fn should_also_parse_whitespace_keywords() {
        assert_eq!(Keyword::from_str("SIMPLE  ").unwrap(), Keyword::SIMPLE);
    }
}
<commit_msg>Place directives closer to type definition<commit_after>//! The types modules describes all the structures to express FITS files.

use std::str::FromStr;

/// Representation of a FITS file.
#[derive(Debug, PartialEq)]
pub struct Fits {
    /// The primary header
    pub primary_header: PrimaryHeader
}

impl Fits {
    /// Create a Fits structure with a given primary header
    pub fn new(primary_header: PrimaryHeader) -> Fits {
        Fits { primary_header: primary_header }
    }
}

/// The primary header of a FITS file.
#[derive(Debug, PartialEq)]
pub struct PrimaryHeader {
    /// The keyword records of the primary header.
    pub keyword_records: Vec<KeywordRecord>,
}

impl PrimaryHeader {
    /// Create a PrimaryHeader with a given set of keyword_records
    pub fn new(keyword_records: Vec<KeywordRecord>) -> PrimaryHeader {
        PrimaryHeader { keyword_records: keyword_records }
    }
}

/// A keyword record contains information about a FITS header.
#[derive(Debug, PartialEq)]
pub struct KeywordRecord {
    /// The keyword of this record.
    keyword: Keyword,
}

impl KeywordRecord {
    /// Create a `KeywordRecord` from a specific `Keyword`.
    pub fn new(keyword: Keyword) -> KeywordRecord {
        KeywordRecord { keyword : keyword }
    }
}

/// A unit tuple that will act as a placeholder for blank records.
#[derive(Debug, PartialEq)]
pub struct BlankRecord;

/// The various keywords that can be found in headers.
#[derive(Debug, PartialEq)]
#[allow(non_camel_case_types, missing_docs)]
pub enum Keyword {
    SIMPLE,
    BITPIX,
    NAXIS,
    NAXISn(u8),
    EXTEND,
    NEXTEND,
    EXTNAME,
    EXTVER,
    ORIGIN,
    DATE,
    CREATOR,
    PROCVER,
    FILEVER,
    TIMVERSN,
    TELESCOP,
    INSTRUME,
    OBJECT,
    KEPLERID,
    CHANNEL,
    MODULE,
    OUTPUT,
    CAMPAIGN,
    DATA_REL,
    OBSMODE,
    MISSION,
    TTABLEID,
    RADESYS,
    RA_OBJ,
    DEC_OBJ,
    EQUINOX,
    PMRA,
    PMDEC,
    PMTOTAL,
    PARALLAX,
    GLON,
    GLAT,
    GMAG,
    RMAG,
    IMAG,
    ZMAG,
    JMAG,
    HMAG,
    KMAG,
    KEPMAG,
    GRCOLOR,
    JKCOLOR,
    GKCOLOR,
    TEFF,
    LOGG,
    FEH,
    EBMINUSV,
    AV,
    RADIUS,
    TMINDEX,
    CHECKSUM,
    DATASUM,
    END,
}

/// Problems that could occur when parsing a `str` are enumerated here.
#[derive(Debug)]
pub enum ParseKeywordError {
    /// When a str can not be recognized as a keyword, this error will be returned
    UnknownKeyword
}

impl FromStr for Keyword {
    type Err = ParseKeywordError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // TODO parse NAXIS1 correctly
        match s.trim_right() {
            "SIMPLE" => Ok(Keyword::SIMPLE),
            "BITPIX" => Ok(Keyword::BITPIX),
            "NAXIS" => Ok(Keyword::NAXIS),
            "EXTEND" => Ok(Keyword::EXTEND),
            "NEXTEND" => Ok(Keyword::NEXTEND),
            "EXTNAME" => Ok(Keyword::EXTNAME),
            "EXTVER" => Ok(Keyword::EXTVER),
            "ORIGIN" => Ok(Keyword::ORIGIN),
            "DATE" => Ok(Keyword::DATE),
            "CREATOR" => Ok(Keyword::CREATOR),
            "PROCVER" => Ok(Keyword::PROCVER),
            "FILEVER" => Ok(Keyword::FILEVER),
            "TIMVERSN" => Ok(Keyword::TIMVERSN),
            "TELESCOP" => Ok(Keyword::TELESCOP),
            "INSTRUME" => Ok(Keyword::INSTRUME),
            "OBJECT" => Ok(Keyword::OBJECT),
            "KEPLERID" => Ok(Keyword::KEPLERID),
            "CHANNEL" => Ok(Keyword::CHANNEL),
            "MODULE" => Ok(Keyword::MODULE),
            "OUTPUT" => Ok(Keyword::OUTPUT),
            "CAMPAIGN" => Ok(Keyword::CAMPAIGN),
            "DATA_REL" => Ok(Keyword::DATA_REL),
            "OBSMODE" => Ok(Keyword::OBSMODE),
            "MISSION" => Ok(Keyword::MISSION),
            "TTABLEID" => Ok(Keyword::TTABLEID),
            "RADESYS" => Ok(Keyword::RADESYS),
            "RA_OBJ" => Ok(Keyword::RA_OBJ),
            "DEC_OBJ" => Ok(Keyword::DEC_OBJ),
            "EQUINOX" => Ok(Keyword::EQUINOX),
            "PMRA" => Ok(Keyword::PMRA),
            "PMDEC" => Ok(Keyword::PMDEC),
            "PMTOTAL" => Ok(Keyword::PMTOTAL),
            "PARALLAX" => Ok(Keyword::PARALLAX),
            "GLON" => Ok(Keyword::GLON),
            "GLAT" => Ok(Keyword::GLAT),
            "GMAG" => Ok(Keyword::GMAG),
            "RMAG" => Ok(Keyword::RMAG),
            "IMAG" => Ok(Keyword::IMAG),
            "ZMAG" => Ok(Keyword::ZMAG),
            "JMAG" => Ok(Keyword::JMAG),
            "HMAG" => Ok(Keyword::HMAG),
            "KMAG" => Ok(Keyword::KMAG),
            "KEPMAG" => Ok(Keyword::KEPMAG),
            "GRCOLOR" => Ok(Keyword::GRCOLOR),
            "JKCOLOR" => Ok(Keyword::JKCOLOR),
            "GKCOLOR" => Ok(Keyword::GKCOLOR),
            "TEFF" => Ok(Keyword::TEFF),
            "LOGG" => Ok(Keyword::LOGG),
            "FEH" => Ok(Keyword::FEH),
            "EBMINUSV" => Ok(Keyword::EBMINUSV),
            "AV" => Ok(Keyword::AV),
            "RADIUS" => Ok(Keyword::RADIUS),
            "TMINDEX" => Ok(Keyword::TMINDEX),
            "CHECKSUM" => Ok(Keyword::CHECKSUM),
            "DATASUM" => Ok(Keyword::DATASUM),
            "END" => Ok(Keyword::END),
            _ => Err(ParseKeywordError::UnknownKeyword)
        }
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;
    use super::*;

    fn fits_constructed_from_the_new_function_should_eq_hand_construction() {
        assert_eq!(
            Fits { primary_header: PrimaryHeader::new(vec!()) },
            Fits::new(PrimaryHeader::new(vec!()))
        );
    }

    fn primary_header_constructed_from_the_new_function_shoul_eq_hand_construction() {
        assert_eq!(
            PrimaryHeader { keyword_records: vec!(
                KeywordRecord::new(Keyword::SIMPLE),
                KeywordRecord::new(Keyword::NEXTEND),
            )},
            PrimaryHeader::new(vec!(
                KeywordRecord::new(Keyword::SIMPLE),
                KeywordRecord::new(Keyword::NEXTEND),
            ))
        );
    }

    #[test]
    fn keyword_record_constructed_from_the_new_function_should_eq_hand_construction() {
        assert_eq!(
            KeywordRecord { keyword: Keyword::ORIGIN },
            KeywordRecord::new(Keyword::ORIGIN));
    }

    #[test]
    fn keywords_could_be_constructed_from_str() {
        let data = vec!(
            ("SIMPLE", Keyword::SIMPLE),
            ("BITPIX", Keyword::BITPIX),
            ("NAXIS", Keyword::NAXIS),
            ("EXTEND", Keyword::EXTEND),
            ("NEXTEND", Keyword::NEXTEND),
            ("EXTVER", Keyword::EXTVER),
            ("ORIGIN", Keyword::ORIGIN),
            ("DATE", Keyword::DATE),
            ("CREATOR", Keyword::CREATOR),
            ("PROCVER", Keyword::PROCVER),
            ("FILEVER", Keyword::FILEVER),
            ("TIMVERSN", Keyword::TIMVERSN),
            ("TELESCOP", Keyword::TELESCOP),
            ("INSTRUME", Keyword::INSTRUME),
            ("OBJECT", Keyword::OBJECT),
            ("KEPLERID", Keyword::KEPLERID),
            ("CHANNEL", Keyword::CHANNEL),
            ("MODULE", Keyword::MODULE),
            ("OUTPUT", Keyword::OUTPUT),
            ("CAMPAIGN", Keyword::CAMPAIGN),
            ("DATA_REL", Keyword::DATA_REL),
            ("OBSMODE", Keyword::OBSMODE),
            ("MISSION", Keyword::MISSION),
            ("TTABLEID", Keyword::TTABLEID),
            ("RADESYS", Keyword::RADESYS),
            ("RA_OBJ", Keyword::RA_OBJ),
            ("DEC_OBJ", Keyword::DEC_OBJ),
            ("EQUINOX", Keyword::EQUINOX),
            ("PMRA", Keyword::PMRA),
            ("PMDEC", Keyword::PMDEC),
            ("PMTOTAL", Keyword::PMTOTAL),
            ("PARALLAX", Keyword::PARALLAX),
            ("GLON", Keyword::GLON),
            ("GLAT", Keyword::GLAT),
            ("GMAG", Keyword::GMAG),
            ("RMAG", Keyword::RMAG),
            ("IMAG", Keyword::IMAG),
            ("ZMAG", Keyword::ZMAG),
            ("JMAG", Keyword::JMAG),
            ("HMAG", Keyword::HMAG),
            ("KMAG", Keyword::KMAG),
            ("KEPMAG", Keyword::KEPMAG),
            ("GRCOLOR", Keyword::GRCOLOR),
            ("JKCOLOR", Keyword::JKCOLOR),
            ("GKCOLOR", Keyword::GKCOLOR),
            ("TEFF", Keyword::TEFF),
            ("LOGG", Keyword::LOGG),
            ("FEH", Keyword::FEH),
            ("EBMINUSV", Keyword::EBMINUSV),
            ("AV", Keyword::AV),
            ("RADIUS", Keyword::RADIUS),
            ("TMINDEX", Keyword::TMINDEX),
            ("CHECKSUM", Keyword::CHECKSUM),
            ("DATASUM", Keyword::DATASUM),
            ("END", Keyword::END),
        );

        for (input, expected) in data {
            assert_eq!(Keyword::from_str(input).unwrap(), expected);
        }
    }

    #[test]
    fn should_also_parse_whitespace_keywords() {
        assert_eq!(Keyword::from_str("SIMPLE  ").unwrap(), Keyword::SIMPLE);
    }
}
<|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 http://mozilla.org/MPL/2.0/. */

use eutil::slice_to_str;
use libc::{self, size_t, c_int, c_ushort, c_void};
use libc::types::os::arch::c95::wchar_t;
use std::char;
use std::cmp::Ordering;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf8_dtor(str: *mut u8) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
    cef_string_wide_clear(cs);
    unsafe {
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
    unsafe {
        cef_string_utf8_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: cef_string_userfree_utf16_t) {
    unsafe {
        cef_string_utf16_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf8_t>() as u64) as *mut cef_string_utf8_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, src_len + 1) as *mut u8;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf8_dtor as extern "C" fn(*mut u8));
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const u8;
        let bstr = (*b).str as *const u8;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        match string::String::from_utf16(ustr) {
            Ok(str) => {
                cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                1 as c_int
            },
            _ =>  0 as c_int
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf16_t>() as u64) as *mut cef_string_utf16_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<c_ushort>() as u64) as
                 *mut u16;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf16_dtor as extern "C" fn(*mut c_ushort));
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const _;
        let bstr = (*b).str as *const _;
        let astr: &[u16] = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr: &[u16] = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_wide_t>() as u64) as *mut cef_string_wide_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<wchar_t>() as u64) as
                 *mut wchar_t;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_wide_dtor as extern "C" fn(*mut wchar_t));
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const wchar_t;
        let bstr = (*b).str as *const wchar_t;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\u{FFFD}')).collect::<String>();
        cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| c as u8).collect::<Vec<u8>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    }
}

pub fn empty_utf16_string() -> cef_string_utf16_t {
    cef_string_utf16_t {
        str: ptr::null_mut(),
        length: 0,
        dtor: None,
    }
}

pub fn string_to_userfree_string(string: cef_string_utf16_t) -> cef_string_userfree_utf16_t {
    unsafe {
        let allocation: cef_string_userfree_utf16_t =
            mem::transmute(libc::malloc(mem::size_of::<cef_string_utf16_t>() as size_t));
        ptr::write(allocation, string);
        allocation
    }
}

pub fn empty_utf16_userfree_string() -> cef_string_userfree_utf16_t {
    string_to_userfree_string(empty_utf16_string())
}

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

use eutil::slice_to_str;
use libc::{self, size_t, c_int, c_ushort, c_void};
use libc::types::os::arch::c95::wchar_t;
use std::char;
use std::cmp::Ordering;
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf8_dtor(str: *mut u8) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
#[allow(private_no_mangle_fns)]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
    unsafe {
        libc::free(str as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
    cef_string_wide_clear(cs);
    unsafe {
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
    unsafe {
        cef_string_utf8_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: cef_string_userfree_utf16_t) {
    unsafe {
        cef_string_utf16_clear(cs);
        libc::free(cs as *mut c_void)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf8_t>() as u64) as *mut cef_string_utf8_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, src_len + 1) as *mut u8;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf8_dtor as extern "C" fn(*mut u8));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_cmp(a: *const cef_string_utf8_t, b: *const cef_string_utf8_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const u8;
        let bstr = (*b).str as *const u8;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
        1
    })
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        match string::String::from_utf16(ustr) {
            Ok(str) => {
                cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                1 as c_int
            },
            _ =>  0 as c_int
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_utf16_t>() as u64) as *mut cef_string_utf16_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<c_ushort>() as u64) as
                 *mut u16;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_utf16_dtor as extern "C" fn(*mut c_ushort));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const _;
        let bstr = (*b).str as *const _;
        let astr: &[u16] = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr: &[u16] = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        (*cs).dtor.map(|dtor| dtor((*cs).str));
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = None;
    }
}

#[inline(never)]
#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    unsafe {
        libc::calloc(1, mem::size_of::<cef_string_wide_t>() as u64) as *mut cef_string_wide_t
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = libc::calloc(1, (src_len + 1) * mem::size_of::<wchar_t>() as u64) as
                 *mut wchar_t;
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy(src, (*output).str, src_len as usize);
             (*output).length = src_len;
             (*output).dtor = Some(string_wide_dtor as extern "C" fn(*mut wchar_t));
           }
       } else {
         (*output).str = src as *mut _;
         (*output).length = src_len;
         (*output).dtor = None;
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_cmp(a: *const cef_string_wide_t, b: *const cef_string_wide_t) -> c_int {
    unsafe {
        let astr = (*a).str as *const wchar_t;
        let bstr = (*b).str as *const wchar_t;
        let astr = slice::from_raw_parts(astr, (*a).length as usize);
        let bstr = slice::from_raw_parts(bstr, (*b).length as usize);
        match astr.cmp(bstr) {
            Ordering::Less => -1,
            Ordering::Equal => 0,
            Ordering::Greater => 1
        }
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf8_to_utf16(src, src_len, output as *mut cef_string_utf16_t);
    }
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.chars().map(|c| c as u32).collect::<Vec<u32>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_wide_to_utf8(src: *const wchar_t, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    if mem::size_of::<wchar_t>() == mem::size_of::<u16>() {
         return cef_string_utf16_to_utf8(src as *const u16, src_len, output);
    }
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| char::from_u32(c as u32).unwrap_or('\u{FFFD}')).collect::<String>();
        cef_string_utf8_set(conv.as_bytes().as_ptr(), conv.len() as size_t, output, 1)
    }
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    slice_to_str(src, src_len as usize, |result| {
        let conv = result.utf16_units().collect::<Vec<u16>>();
        cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1)
    })
}

#[no_mangle]
pub extern "C" fn cef_string_ascii_to_wide(src: *const u8, src_len: size_t, output: *mut cef_string_wide_t) -> c_int {
    unsafe {
        let ustr = slice::from_raw_parts(src, src_len as usize);
        let conv = ustr.iter().map(|&c| c as u8).collect::<Vec<u8>>();
        cef_string_wide_set(conv.as_ptr() as *const wchar_t, conv.len() as size_t, output, 1)
    }
}

pub fn empty_utf16_string() -> cef_string_utf16_t {
    cef_string_utf16_t {
        str: ptr::null_mut(),
        length: 0,
        dtor: None,
    }
}

pub fn string_to_userfree_string(string: cef_string_utf16_t) -> cef_string_userfree_utf16_t {
    unsafe {
        let allocation = libc::malloc(mem::size_of::<cef_string_utf16_t>() as size_t)
            as cef_string_userfree_utf16_t;
        ptr::write(allocation, string);
        allocation
    }
}

pub fn empty_utf16_userfree_string() -> cef_string_userfree_utf16_t {
    string_to_userfree_string(empty_utf16_string())
}

<|endoftext|>


<commit_before>use std::fmt;

#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

/*impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(this: {:#?}, \nleft: {:#?}, \nright: {:#?})",
            self.enter, self.left, self.right
        )
    }
}*/

//for red-black tree
#[derive(Debug, Clone, PartialEq)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }

    fn new_black(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_black();
        n
    }
    fn new_red(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_red();
        n
    }
    fn make_black(&mut self) {
        self.color = Color::Black;
    }

    fn make_red(&mut self) {
        self.color = Color::Red;
    }

    fn change_color(&mut self) {
        if self.color == Color::Black {
            self.color = Color::Red
        } else {
            self.color = Color::Black
        }
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        let mut root = Node::new(v);
        root.make_black();
        Tree {
            enter: root,
            left: None,
            right: None,
        }
    }

    //fix color at ending of insert method
    fn insert(&mut self, v: &i32) {
        if *v == self.enter.val {
            println!("{}", "duplicate value");
            return;
        }

        {
            //need drop target which hold self ownship..
            //we need this ownship to fix color at endding of this method.
            let target = if *v > self.enter.val {
                &mut self.right
            } else {
                &mut self.left
            };

            match target {
                Some(next) => next.insert(v),
                None => {
                    let mut new_node = Node::new(v);
                    new_node.make_red();
                    let new_tree = Tree {
                        enter: new_node,
                        left: None,
                        right: None,
                    };
                    *target = Some(Box::new(new_tree));
                }
            }
        }

        //self.fix(v);
    }

    fn look_up_recursive(&mut self, v: &i32) -> ReTr {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, &'static str) {
        let mut this: &mut Self = self;
        let mut result: &str = "None";
        let mut next: &str = "None";
        loop {
            if *v == this.enter.val {
                return (Err("no father".to_string()), "this");
            }

            match (this.right.as_ref(), this.left.as_ref()) {
                (Some(r), Some(l)) => {
                    if r.enter.val == *v {
                        result = "right";
                    } else if l.enter.val == *v {
                        result = "left"
                    }
                }
                (Some(r), None) => {
                    if r.enter.val == *v {
                        result = "right";
                    }
                }
                (None, Some(l)) => {
                    if l.enter.val == *v {
                        result = "left";
                    }
                }
                _ => (),
            }

            if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error");
                }
                next = "right";
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error");
                }
                next = "left";
            }

            if result != "None" {
                return (Ok(this), result);
            } else if next == "right" {
                this = { this }.right.as_mut().unwrap();
            } else if next == "left" {
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    //find father, grandfather, and uncle
    fn look_up_family(
        &mut self,
        v: &i32,
    ) -> (
        Result<i32, &'static str>,
        Result<i32, &'static str>,
        Result<i32, &'static str>,
    ) {
        let this: &mut Self = self;
        let grandfather: i32;
        let father: i32;

        match this.look_up_father(v).0 {
            Ok(n) => {
                father = n.enter.val;
            }
            Err(_) => {
                return (
                    Err("father not find"),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        let uncle_option: &Option<Box<Tree>>;
        match this.look_up_father(&father) {
            (Ok(n), s) => {
                grandfather = n.enter.val;
                match s {
                    "left" => uncle_option = &n.right,
                    _ => uncle_option = &n.left,
                };
            }
            (Err(_), _) => {
                return (
                    Ok(father),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        match uncle_option {
            Some(un) => return (Ok(father), Ok(grandfather), Ok(un.enter.val)),
            _ => return (Ok(father), Ok(grandfather), Err("uncle not find")),
        }
    }

    fn cut_left_tree(&self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_left_tree().unwrap();
                let mut son = this.cut_right_tree().unwrap();
                let grand_son = son.cut_left_tree().unwrap();

                this.right = Some(grand_son);
                son.left = Some(this);
                father.left = Some(son);
                return;
            }
            _ => (),
        }

        let left = self.cut_left_tree().unwrap();
        let mut new_left = Tree::new(&self.enter.val);
        new_left.left = Some(left);

        let right = self.cut_right_tree().unwrap();
        let right_left = right.cut_left_tree().unwrap();
        let right_right = right.cut_right_tree().unwrap();
        new_left.right = Some(right_left);

        self.enter = Node::new_black(&right.enter.val);

        self.right = Some(right_right);

        self.left = Some(Box::new(new_left));
    }

    fn right_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_right_tree().unwrap();
                let mut son = this.cut_left_tree().unwrap();
                let grand_son = son.cut_right_tree();

                this.left = grand_son;
                son.right = Some(this);
                father.right = Some(son);
                return;
            }
            _ => (),
        }

        let right = self.cut_right_tree().unwrap();
        let left = self.cut_left_tree().unwrap();
        let left_left = left.cut_left_tree().unwrap();
        let left_right = left.cut_left_tree().unwrap();

        let mut new_right = Tree::new(&self.enter.val);
        new_right.left = Some(left_right);
        new_right.right = Some(right);

        self.enter = Node::new_black(&left.enter.val);
        self.left = Some(left_left);
        self.right = Some(Box::new(new_right));
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    let mut b = Tree::new(&10);
    b.insert(&2);
    b.insert(&1);
    b.insert(&5);
    b.insert(&3);
    b.insert(&6);
    b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    let mut c = b.cut_left_tree().unwrap();
    //println!("{:#?}", c);
    c.left_shift(&2);
    println!("{:#?}", c);

    //let mut c = Tree::new(&2);
    //c.insert(&8);
    //c.insert(&1);
    //c.insert(&5);
    //c.insert(&4);
    //c.insert(&7);
    //c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    //c.right_shift(&8);
    //println!("{:#?}", c);
}
<commit_msg>add fix function<commit_after>use std::fmt;

#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

/*impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(this: {:#?}, \nleft: {:#?}, \nright: {:#?})",
            self.enter, self.left, self.right
        )
    }
}*/

//for red-black tree
#[derive(Debug, Clone, PartialEq)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }

    fn new_black(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_black();
        n
    }
    fn new_red(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_red();
        n
    }
    fn make_black(&mut self) {
        self.color = Color::Black;
    }

    fn make_red(&mut self) {
        self.color = Color::Red;
    }

    fn change_color(&mut self) {
        if self.color == Color::Black {
            self.color = Color::Red
        } else {
            self.color = Color::Black
        }
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        let mut root = Node::new(v);
        root.make_black();
        Tree {
            enter: root,
            left: None,
            right: None,
        }
    }

    //fix color at ending of insert method
    fn insert(&mut self, v: &i32) {
        if *v == self.enter.val {
            println!("{}", "duplicate value");
            return;
        }

        {
            //need drop target which hold self ownship..
            //we need this ownship to fix color at endding of this method.
            let target = if *v > self.enter.val {
                &mut self.right
            } else {
                &mut self.left
            };

            match target {
                Some(next) => next.insert(v),
                None => {
                    let mut new_node = Node::new(v);
                    new_node.make_red();
                    let new_tree = Tree {
                        enter: new_node,
                        left: None,
                        right: None,
                    };
                    *target = Some(Box::new(new_tree));
                }
            }
        }

        //self.fix(v);
    }

    fn look_up_recursive(&mut self, v: &i32) -> ReTr {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, &'static str) {
        let mut this: &mut Self = self;
        let mut result: &str = "None";
        let mut next: &str = "None";
        loop {
            if *v == this.enter.val {
                return (Err("no father".to_string()), "this");
            }

            match (this.right.as_ref(), this.left.as_ref()) {
                (Some(r), Some(l)) => {
                    if r.enter.val == *v {
                        result = "right";
                    } else if l.enter.val == *v {
                        result = "left"
                    }
                }
                (Some(r), None) => {
                    if r.enter.val == *v {
                        result = "right";
                    }
                }
                (None, Some(l)) => {
                    if l.enter.val == *v {
                        result = "left";
                    }
                }
                _ => (),
            }

            if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error");
                }
                next = "right";
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error");
                }
                next = "left";
            }

            if result != "None" {
                return (Ok(this), result);
            } else if next == "right" {
                this = { this }.right.as_mut().unwrap();
            } else if next == "left" {
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    //find father, grandfather, and uncle
    fn look_up_family(
        &mut self,
        v: &i32,
    ) -> (
        Result<i32, &'static str>,
        Result<i32, &'static str>,
        Result<i32, &'static str>,
    ) {
        let this: &mut Self = self;
        let grandfather: i32;
        let father: i32;

        match this.look_up_father(v).0 {
            Ok(n) => {
                father = n.enter.val;
            }
            Err(_) => {
                return (
                    Err("father not find"),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        let uncle_option: &Option<Box<Tree>>;
        match this.look_up_father(&father) {
            (Ok(n), s) => {
                grandfather = n.enter.val;
                match s {
                    "left" => uncle_option = &n.right,
                    _ => uncle_option = &n.left,
                };
            }
            (Err(_), _) => {
                return (
                    Ok(father),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        match uncle_option {
            Some(un) => return (Ok(father), Ok(grandfather), Ok(un.enter.val)),
            _ => return (Ok(father), Ok(grandfather), Err("uncle not find")),
        }
    }

    fn cut_left_tree(&self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_left_tree().unwrap();
                let mut son = this.cut_right_tree().unwrap();
                let grand_son = son.cut_left_tree().unwrap();

                this.right = Some(grand_son);
                son.left = Some(this);
                father.left = Some(son);
                return;
            }
            _ => (),
        }

        let left = self.cut_left_tree().unwrap();
        let mut new_left = Tree::new(&self.enter.val);
        new_left.left = Some(left);

        let right = self.cut_right_tree().unwrap();
        let right_left = right.cut_left_tree().unwrap();
        let right_right = right.cut_right_tree().unwrap();
        new_left.right = Some(right_left);

        self.enter = Node::new_black(&right.enter.val);

        self.right = Some(right_right);

        self.left = Some(Box::new(new_left));
    }

    fn right_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_right_tree().unwrap();
                let mut son = this.cut_left_tree().unwrap();
                let grand_son = son.cut_right_tree();

                this.left = grand_son;
                son.right = Some(this);
                father.right = Some(son);
                return;
            }
            _ => (),
        }

        let right = self.cut_right_tree();
        let left = self.cut_left_tree().unwrap();
        let left_left = left.cut_left_tree().unwrap();
        let left_right = left.cut_right_tree().unwrap();

        let mut new_right = Tree::new(&self.enter.val);
        new_right.left = Some(left_right);
        new_right.right = right;

        self.enter = Node::new_black(&left.enter.val);
        self.left = Some(left_left);
        self.right = Some(Box::new(new_right));
    }

    //this fix method might not very efficiency because look_up_father..
    //always look from top of tree
    fn fix(&mut self, v: &i32) {
        //step 1
        let mut this: i32 = 0;
        match self.look_up_family(v) {
            (Ok(father), Ok(grandfather), Ok(uncle)) => {
                if let Ok(fff) = self.look_up_father(&grandfather).0 {
                    this = fff.enter.val;
                } else {
                    println!("{}", "no great-grandfather");
                    return;
                }

                if let Ok(ff) = self.look_up(&father) {
                    ff.enter.make_black();
                }

                if let Ok(un) = self.look_up(&uncle) {
                    un.enter.make_black();
                }

                if let Ok(ff) = self.look_up(&grandfather) {
                    ff.enter.make_red();
                }
            }
            (a, b, c) => println!("{:#?}, {:#?}, {:#?}", a, b, c),
        }

        //step 2
        self.left_shift(&this);
        this = self
            .look_up(&{ this })
            .unwrap()
            .left
            .as_mut()
            .unwrap()
            .enter
            .val;

        //stap3
        match self.look_up_family(&this) {
            (Ok(father), Ok(grandfather), _) => {
                if let Ok(ff) = self.look_up(&father) {
                    ff.enter.make_black();
                }

                if let Ok(gf) = self.look_up(&grandfather) {
                    gf.enter.make_red();
                    this = gf.enter.val;
                }
            }
            _ => (),
        }

        this = self.look_up_father(&this).0.unwrap().enter.val;
        self.right_shift(&this);
        self.enter.make_black();
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    let mut b = Tree::new(&10);
    b.insert(&2);
    b.insert(&1);
    b.insert(&5);
    b.insert(&3);
    b.insert(&6);
    b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    let mut c = b.cut_left_tree().unwrap();
    //println!("{:#?}", c);
    c.left_shift(&2);
    println!("{:#?}", c);

    //let mut c = Tree::new(&2);
    //c.insert(&8);
    //c.insert(&1);
    //c.insert(&5);
    //c.insert(&4);
    //c.insert(&7);
    //c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    //c.right_shift(&8);
    //println!("{:#?}", c);
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Result};

generate_csi_struct!(AfterCursor, "K");
generate_csi_struct!(BeforeCursor, "1K");
generate_csi_struct!(Line, "2K");

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn after_cursor() {
        assert_eq!(format!("{}", AfterCursor), "\x1b[K");
    }

    #[test]
    fn before_cursor() {
        assert_eq!(format!("{}", BeforeCursor), "\x1b[1K");
    }

    #[test]
    fn line() {
        assert_eq!(format!("{}", Line), "\x1b[2K");
    }
}
<commit_msg>Add screen-after-cursor clear code<commit_after>use std::fmt::{Display, Formatter, Result};

generate_csi_struct!(AfterCursor, "K");
generate_csi_struct!(BeforeCursor, "1K");
generate_csi_struct!(Line, "2K");
generate_csi_struct!(Screen, "J");

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn after_cursor() {
        assert_eq!(format!("{}", AfterCursor), "\x1b[K");
    }

    #[test]
    fn before_cursor() {
        assert_eq!(format!("{}", BeforeCursor), "\x1b[1K");
    }

    #[test]
    fn line() {
        assert_eq!(format!("{}", Line), "\x1b[2K");
    }

    #[test]
    fn screen() {
        assert_eq!(format!("{}", Screen), "\x1b[J");
    }
}
<|endoftext|>