<commit_before>use std::{
    collections::hash_map::DefaultHasher,
    fmt,
    hash::{Hash, Hasher},
    ops::Deref,
    result::Result as StdResult,
    sync::Arc,
};

use serde::{
    Deserialize, Serialize,
    {de::Deserializer, ser::Serializer},
};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

impl Serialize for IVec {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serde_bytes::serialize(self.as_ref(), serializer)
    }
}

impl<'de> Deserialize<'de> for IVec {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> StdResult<Self, D::Error> {
        let bytes: StdResult<Box<[u8]>, D::Error> =
            serde_bytes::deserialize(deserializer);
        bytes.map(IVec::from)
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    fn inline(slice: &[u8]) -> IVec {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        IVec(IVecInner::Inline(slice.len() as u8, data))
    }

    fn remote(arc: Arc<[u8]>) -> IVec {
        IVec(IVecInner::Remote(arc))
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVecInner::Inline(..) = self.0 {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> IVec {
        if is_inline_candidate(b.len()) {
            IVec::inline(&b)
        } else {
            // rely on the Arc From specialization
            // for Box<T>, which may improve
            // over time
            IVec::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> IVec {
        if is_inline_candidate(slice.len()) {
            IVec::inline(slice)
        } else {
            IVec::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> IVec {
        IVec::remote(arc)
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> IVec {
        IVec::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &IVec) -> IVec {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if is_inline_candidate(v.len()) {
            IVec::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            IVec::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> IVec {
                    IVec::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &IVec) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &IVec) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}
<commit_msg>Remove unnecessary import<commit_after>use std::{
    fmt,
    hash::{Hash, Hasher},
    ops::Deref,
    result::Result as StdResult,
    sync::Arc,
};

use serde::{
    Deserialize, Serialize,
    {de::Deserializer, ser::Serializer},
};

const CUTOFF: usize = std::mem::size_of::<&[u8]>() - 1;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

impl Serialize for IVec {
    fn serialize<S: Serializer>(
        &self,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serde_bytes::serialize(self.as_ref(), serializer)
    }
}

impl<'de> Deserialize<'de> for IVec {
    fn deserialize<D: Deserializer<'de>>(
        deserializer: D,
    ) -> StdResult<Self, D::Error> {
        let bytes: StdResult<Box<[u8]>, D::Error> =
            serde_bytes::deserialize(deserializer);
        bytes.map(IVec::from)
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    fn inline(slice: &[u8]) -> IVec {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        IVec(IVecInner::Inline(slice.len() as u8, data))
    }

    fn remote(arc: Arc<[u8]>) -> IVec {
        IVec(IVecInner::Remote(arc))
    }

    #[inline]
    pub(crate) fn size_in_bytes(&self) -> u64 {
        if let IVecInner::Inline(..) = self.0 {
            std::mem::size_of::<IVec>() as u64
        } else {
            let sz = std::mem::size_of::<IVec>() as u64;
            sz.saturating_add(self.len() as u64)
        }
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> IVec {
        if is_inline_candidate(b.len()) {
            IVec::inline(&b)
        } else {
            // rely on the Arc From specialization
            // for Box<T>, which may improve
            // over time
            IVec::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> IVec {
        if is_inline_candidate(slice.len()) {
            IVec::inline(slice)
        } else {
            IVec::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> IVec {
        IVec::remote(arc)
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> IVec {
        IVec::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &IVec) -> IVec {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> IVec {
        if is_inline_candidate(v.len()) {
            IVec::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            IVec::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> IVec {
                    IVec::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &IVec) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &IVec) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}
<|endoftext|>


<commit_before>//! Song analysis module.
//!
//! Use features-extraction functions from other modules
//! e.g. tempo features, spectral features, etc to build an
//! Analysis of a Song
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

extern crate crossbeam;
extern crate ndarray;
extern crate ndarray_npy;

use std::f32::consts::PI;

use ndarray::{arr1, s, Array, Array2};
use rustfft::num_complex::Complex;
use rustfft::num_traits::Zero;
use realfft::RealToComplex;

use crate::chroma::ChromaDesc;
use crate::decode::decode_song;
use crate::misc::LoudnessDesc;
use crate::temporal::BPMDesc;
use crate::timbral::{SpectralDesc, ZeroCrossingRateDesc};
use crate::{Analysis, Song};
use crossbeam::thread;

pub fn decode_and_analyze(path: &str) -> Result<Song, String> {
    // TODO error handling here
    let mut song = decode_song(&path)?;

    song.analysis = analyze(&song);
    Ok(song)
}

pub fn reflect_pad(array: &[f32], pad: usize) -> Vec<f32> {
    let prefix = array[1..=pad].iter().rev().copied().collect::<Vec<f32>>();
    let suffix = array[(array.len() - 2) - pad + 1..array.len() - 1]
        .iter()
        .rev()
        .copied()
        .collect::<Vec<f32>>();
    let mut output = Vec::with_capacity(prefix.len() + array.len() + suffix.len());

    output.extend(prefix);
    output.extend(array);
    output.extend(suffix);
    output
}

pub fn stft(signal: &[f32], window_length: usize, hop_length: usize) -> Array2<f64> {
    let mut stft = Array2::zeros((
        window_length / 2 + 1,
        (signal.len() as f32 / hop_length as f32).ceil() as usize,
    ));
    let signal = reflect_pad(&signal, window_length / 2);

    // TODO actually have it constant - no need to compute it everytime
    // Periodic, so window_size + 1
    let mut hann_window = Array::zeros(window_length + 1);
    for n in 0..window_length {
        hann_window[[n]] = 0.5 - 0.5 * f32::cos(2. * n as f32 * PI / (window_length as f32));
    }
    hann_window = hann_window.slice_move(s![0..window_length]);
    let mut output_window = Array::from_elem(window_length / 2 + 1, Complex::zero());
    let mut r2c = RealToComplex::<f32>::new(window_length).unwrap();

    for (window, mut stft_col) in signal
        .windows(window_length)
        .step_by(hop_length)
        .zip(stft.gencolumns_mut())
    {
        let mut signal = arr1(&window) * &hann_window;
        r2c.process(
            signal.as_slice_mut().unwrap(),
            output_window.as_slice_mut().unwrap(),
        ).unwrap();
        stft_col.assign(
            &output_window
                .slice(s![..window_length / 2 + 1])
                .mapv(|x| x.norm() as f64),
        );
    }
    stft
}

pub fn analyze(song: &Song) -> Analysis {
    thread::scope(|s| {
        let child_chroma = s.spawn(|_| {
            let mut chroma_desc = ChromaDesc::new(song.sample_rate, 12);
            chroma_desc.do_(&song.sample_array);
            chroma_desc.get_values()
        });

        // These descriptors can be streamed
        let child_timbral = s.spawn(|_| {
            let mut spectral_desc = SpectralDesc::new(song.sample_rate);
            let mut zcr_desc = ZeroCrossingRateDesc::default();
            let windows = song
                .sample_array
                .windows(SpectralDesc::WINDOW_SIZE)
                .step_by(SpectralDesc::HOP_SIZE);
            for window in windows {
                spectral_desc.do_(&window);
                zcr_desc.do_(&window);
            }
            let centroid = spectral_desc.get_centroid();
            let rolloff = spectral_desc.get_rolloff();
            let flatness = spectral_desc.get_flatness();
            let zcr = zcr_desc.get_value();
            (centroid, rolloff, flatness, zcr)
        });

        let child_tempo = s.spawn(|_| {
            let mut tempo_desc = BPMDesc::new(song.sample_rate);
            let windows = song
                .sample_array
                .windows(BPMDesc::WINDOW_SIZE)
                .step_by(BPMDesc::HOP_SIZE);

            for window in windows {
                tempo_desc.do_(&window);
            }
            tempo_desc.get_value()
        });

        let child_loudness = s.spawn(|_| {
            let mut loudness_desc = LoudnessDesc::default();
            let windows = song
                .sample_array
                .chunks(LoudnessDesc::WINDOW_SIZE);

            for window in windows {
                loudness_desc.do_(&window);
            }
            loudness_desc.get_value()
        });

        // Non-streaming approach for that one
        let (is_major, fifth) = child_chroma.join().unwrap();
        let (centroid, rolloff, flatness, zcr) = child_timbral.join().unwrap();
        let tempo = child_tempo.join().unwrap();
        let loudness = child_loudness.join().unwrap();

        Analysis {
            tempo,
            spectral_centroid: centroid,
            zero_crossing_rate: zcr,
            spectral_rolloff: rolloff,
            spectral_flatness: flatness,
            loudness,
            is_major,
            fifth,
        }
    })
    .unwrap()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::decode::decode_song;
    use ndarray::Array2;
    use ndarray_npy::ReadNpyExt;
    use std::f32::consts::PI;
    use std::fs::File;

    #[test]
    fn test_analyze() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let expected_analysis = Analysis {
            tempo: 0.37860596,
            spectral_centroid: -0.75483,
            zero_crossing_rate: -0.85036564,
            spectral_rolloff: -0.6326486,
            spectral_flatness: -0.77610075,
            loudness: 0.27126348,
            is_major: -1.,
            fifth: (f32::cos(5. * PI / 3.), f32::sin(5. * PI / 3.)),
        };
        assert!(expected_analysis.approx_eq(&analyze(&song)));
    }

    #[test]
    fn test_compute_stft() {
        let file = File::open("data/librosa-stft.npy").unwrap();
        let expected_stft = Array2::<f32>::read_npy(file).unwrap().mapv(|x| x as f64);

        let song = decode_song("data/piano.flac").unwrap();

        let stft = stft(&song.sample_array, 2048, 512);

        assert!(!stft.is_empty() && !expected_stft.is_empty());
        for (expected, actual) in expected_stft.iter().zip(stft.iter()) {
            assert!(0.0001 > (expected - actual).abs());
        }
    }

    #[test]
    fn test_reflect_pad() {
        let array = Array::range(0., 100000., 1.);

        let output = reflect_pad(array.as_slice().unwrap(), 3);
        assert_eq!(&output[..4], &[3.0, 2.0, 1.0, 0.]);
        assert_eq!(&output[3..100003], array.to_vec());
        assert_eq!(&output[100003..100006], &[99998.0, 99997.0, 99996.0]);
    }
}
<commit_msg>Further optimize stft function<commit_after>//! Song analysis module.
//!
//! Use features-extraction functions from other modules
//! e.g. tempo features, spectral features, etc to build an
//! Analysis of a Song
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

extern crate crossbeam;
extern crate ndarray;
extern crate ndarray_npy;

use std::f32::consts::PI;

use ndarray::{arr1, arr2, s, Array, Array1, Array2};
use realfft::RealToComplex;
use rustfft::num_complex::Complex;
use rustfft::num_traits::Zero;

use crate::chroma::ChromaDesc;
use crate::decode::decode_song;
use crate::misc::LoudnessDesc;
use crate::temporal::BPMDesc;
use crate::timbral::{SpectralDesc, ZeroCrossingRateDesc};
use crate::{Analysis, Song};
use crossbeam::thread;

pub fn decode_and_analyze(path: &str) -> Result<Song, String> {
    // TODO error handling here
    let mut song = decode_song(&path)?;

    song.analysis = analyze(&song);
    Ok(song)
}

pub fn reflect_pad(array: &[f32], pad: usize) -> Vec<f32> {
    let prefix = array[1..=pad].iter().rev().copied().collect::<Vec<f32>>();
    let suffix = array[(array.len() - 2) - pad + 1..array.len() - 1]
        .iter()
        .rev()
        .copied()
        .collect::<Vec<f32>>();
    let mut output = Vec::with_capacity(prefix.len() + array.len() + suffix.len());

    output.extend(prefix);
    output.extend(array);
    output.extend(suffix);
    output
}

pub fn stft(signal: &[f32], window_length: usize, hop_length: usize) -> Array2<f64> {
    // Take advantage of raw-major order to have contiguous window for the
    // `assign`, reversing the axes to have the expected shape at the end only.
    let mut stft = Array2::zeros((
        (signal.len() as f32 / hop_length as f32).ceil() as usize,
        window_length / 2 + 1,
    ));
    let signal = reflect_pad(&signal, window_length / 2);

    // TODO actually have it constant - no need to compute it everytime
    // Periodic, so window_size + 1
    let mut hann_window = Array::zeros(window_length + 1);
    for n in 0..window_length {
        hann_window[[n]] = 0.5 - 0.5 * f32::cos(2. * n as f32 * PI / (window_length as f32));
    }
    hann_window = hann_window.slice_move(s![0..window_length]);
    let mut output_window = Array::from_elem(window_length / 2 + 1, Complex::zero());
    let mut r2c = RealToComplex::<f32>::new(window_length).unwrap();

    for (window, mut stft_col) in signal
        .windows(window_length)
        .step_by(hop_length)
        .zip(stft.genrows_mut())
    {
        let mut signal = arr1(&window) * &hann_window;
        r2c.process(
            signal.as_slice_mut().unwrap(),
            output_window.as_slice_mut().unwrap(),
        )
        .unwrap();
        stft_col.assign(
            &output_window
                .slice(s![..window_length / 2 + 1])
                .mapv(|x| (x.re * x.re + x.im * x.im).sqrt() as f64),
        );
    }
    stft.permuted_axes((1, 0))
}

pub fn analyze(song: &Song) -> Analysis {
    thread::scope(|s| {
        let child_chroma = s.spawn(|_| {
            let mut chroma_desc = ChromaDesc::new(song.sample_rate, 12);
            chroma_desc.do_(&song.sample_array);
            chroma_desc.get_values()
        });

        // These descriptors can be streamed
        let child_timbral = s.spawn(|_| {
            let mut spectral_desc = SpectralDesc::new(song.sample_rate);
            let mut zcr_desc = ZeroCrossingRateDesc::default();
            let windows = song
                .sample_array
                .windows(SpectralDesc::WINDOW_SIZE)
                .step_by(SpectralDesc::HOP_SIZE);
            for window in windows {
                spectral_desc.do_(&window);
                zcr_desc.do_(&window);
            }
            let centroid = spectral_desc.get_centroid();
            let rolloff = spectral_desc.get_rolloff();
            let flatness = spectral_desc.get_flatness();
            let zcr = zcr_desc.get_value();
            (centroid, rolloff, flatness, zcr)
        });

        let child_tempo = s.spawn(|_| {
            let mut tempo_desc = BPMDesc::new(song.sample_rate);
            let windows = song
                .sample_array
                .windows(BPMDesc::WINDOW_SIZE)
                .step_by(BPMDesc::HOP_SIZE);

            for window in windows {
                tempo_desc.do_(&window);
            }
            tempo_desc.get_value()
        });

        let child_loudness = s.spawn(|_| {
            let mut loudness_desc = LoudnessDesc::default();
            let windows = song.sample_array.chunks(LoudnessDesc::WINDOW_SIZE);

            for window in windows {
                loudness_desc.do_(&window);
            }
            loudness_desc.get_value()
        });

        // Non-streaming approach for that one
        let (is_major, fifth) = child_chroma.join().unwrap();
        let (centroid, rolloff, flatness, zcr) = child_timbral.join().unwrap();
        let tempo = child_tempo.join().unwrap();
        let loudness = child_loudness.join().unwrap();

        Analysis {
            tempo,
            spectral_centroid: centroid,
            zero_crossing_rate: zcr,
            spectral_rolloff: rolloff,
            spectral_flatness: flatness,
            loudness,
            is_major,
            fifth,
        }
    })
    .unwrap()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::decode::decode_song;
    use ndarray::Array2;
    use ndarray_npy::ReadNpyExt;
    use std::f32::consts::PI;
    use std::fs::File;

    #[test]
    fn test_analyze() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let expected_analysis = Analysis {
            tempo: 0.37860596,
            spectral_centroid: -0.75483,
            zero_crossing_rate: -0.85036564,
            spectral_rolloff: -0.6326486,
            spectral_flatness: -0.77610075,
            loudness: 0.27126348,
            is_major: -1.,
            fifth: (f32::cos(5. * PI / 3.), f32::sin(5. * PI / 3.)),
        };
        assert!(expected_analysis.approx_eq(&analyze(&song)));
    }

    #[test]
    fn test_compute_stft() {
        let file = File::open("data/librosa-stft.npy").unwrap();
        let expected_stft = Array2::<f32>::read_npy(file).unwrap().mapv(|x| x as f64);

        let song = decode_song("data/piano.flac").unwrap();

        let stft = stft(&song.sample_array, 2048, 512);

        assert!(!stft.is_empty() && !expected_stft.is_empty());
        for (expected, actual) in expected_stft.iter().zip(stft.iter()) {
            assert!(0.0001 > (expected - actual).abs());
        }
    }

    #[test]
    fn test_reflect_pad() {
        let array = Array::range(0., 100000., 1.);

        let output = reflect_pad(array.as_slice().unwrap(), 3);
        assert_eq!(&output[..4], &[3.0, 2.0, 1.0, 0.]);
        assert_eq!(&output[3..100003], array.to_vec());
        assert_eq!(&output[100003..100006], &[99998.0, 99997.0, 99996.0]);
    }
}
<|endoftext|>


<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::file::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command {
    pub name: String,
    pub main: Box<Fn(&Vec<String>)>,
}

impl Command {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo".to_string(),
            main: box |args: &Vec<String>| {
                let mut echo = String::new();
                let mut first = true;
                for i in 1..args.len() {
                    match args.get(i) {
                        Some(arg) => {
                            if first {
                                first = false
                            } else {
                                echo = echo + " ";
                            }
                            echo = echo + arg;
                        }
                        None => (),
                    }
                }
                println!("{}", echo);
            },
        });

        commands.push(Command {
            name: "open".to_string(),
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(arg) => {
                        File::exec(arg);
                    },
                    None => (),
                }
            },
        });

        commands.push(Command {
            name: "run".to_string(),
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(arg) => {
                        let path = arg.clone();
                        println!("URL: {}", path);

                        let mut commands = String::new();
                        if let Some(mut file) = File::open(&path) {
                            file.read_to_string(&mut commands);
                        }

                        for command in commands.split('\n') {
                            exec!(command);
                        }
                    }
                    None => (),
                }
            },
        });

        commands.push(Command {
            name: "send".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    for i in 2..args.len() {
                        if let Some(arg) = args.get(i) {
                            if i >= 3 {
                                string.push_str(" ");
                            }
                            string.push_str(arg);
                        }
                    }
                    string.push_str("\r\n\r\n");

                    match file.write(&string.as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

		let mut command_list = String::new();
		command_list = commands.iter().fold(command_list, |l , n| l + " " + &n.name);

        commands.push(Command {
			name: "help".to_string(),
			main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
			},
		});

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application {
    commands: Vec<Command>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl Application {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &String) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if *command_string == "$" {
            let mut variables = String::new();
            for variable in self.variables.iter() {
                variables = variables + "\n" + &variable.name + "=" + &variable.value;
            }
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if arg.len() > 0 {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        match args.get(0) {
            Some(cmd) => {
                if cmd == "if" {
                    let mut value = false;

                    match args.get(1) {
                        Some(left) => match args.get(2) {
                            Some(cmp) => match args.get(3) {
                                Some(right) => {
                                    if cmp == "==" {
                                        value = *left == *right;
                                    } else if cmp == "!=" {
                                        value = *left != *right;
                                    } else if cmp == ">" {
                                        value = left.to_num_signed() > right.to_num_signed();
                                    } else if cmp == ">=" {
                                        value = left.to_num_signed() >= right.to_num_signed();
                                    } else if cmp == "<" {
                                        value = left.to_num_signed() < right.to_num_signed();
                                    } else if cmp == "<=" {
                                        value = left.to_num_signed() <= right.to_num_signed();
                                    } else {
                                        println!("Unknown comparison: {}", cmp);
                                    }
                                }
                                None => (),
                            },
                            None => (),
                        },
                        None => (),
                    }

                    self.modes.insert(0, Mode { value: value });
                    return;
                }

                if cmd == "else" {
                    let mut syntax_error = false;
                    match self.modes.get_mut(0) {
                        Some(mode) => mode.value = !mode.value,
                        None => syntax_error = true,
                    }
                    if syntax_error {
                        println!("Syntax error: else found with no previous if");
                    }
                    return;
                }

                if cmd == "fi" {
                    let mut syntax_error = false;
                    if self.modes.len() > 0 {
                        self.modes.remove(0);
                    } else {
                        syntax_error = true;
                    }
                    if syntax_error {
                        println!("Syntax error: fi found with no previous if");
                    }
                    return;
                }

                for mode in self.modes.iter() {
                    if !mode.value {
                        return;
                    }
                }

                //Set variables
                match cmd.find('=') {
                    Some(i) => {
                        let name = cmd[0 .. i].to_string();
                        let mut value = cmd[i + 1 .. cmd.len()].to_string();

                        if name.len() == 0 {
                            return;
                        }

                        for i in 1..args.len() {
                            match args.get(i) {
                                Some(arg) => value = value + " " + &arg,
                                None => (),
                            }
                        }

                        if value.len() == 0 {
                            let mut remove = -1;
                            for i in 0..self.variables.len() {
                                match self.variables.get(i) {
                                    Some(variable) => if variable.name == name {
                                        remove = i as isize;
                                        break;
                                    },
                                    None => break,
                                }
                            }

                            if remove >= 0 {
                                self.variables.remove(remove as usize);
                            }
                        } else {
                            for variable in self.variables.iter_mut() {
                                if variable.name == name {
                                    variable.value = value;
                                    return;
                                }
                            }

                            self.variables.push(Variable {
                                name: name,
                                value: value,
                            });
                        }
                        return;
                    }
                    None => (),
                }

                //Commands
                for command in self.commands.iter() {
                    if &command.name == cmd {
                        (*command.main)(&args);
                        return;
                    }
                }

                println!("Unknown command: '{}'", cmd);

            }
            None => (),
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title(&"Terminal".to_string());

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command.len() > 0 {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>formatting<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::file::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command {
    pub name: String,
    pub main: Box<Fn(&Vec<String>)>,
}

impl Command {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo".to_string(),
            main: box |args: &Vec<String>| {
                let mut echo = String::new();
                let mut first = true;
                for i in 1..args.len() {
                    match args.get(i) {
                        Some(arg) => {
                            if first {
                                first = false
                            } else {
                                echo = echo + " ";
                            }
                            echo = echo + arg;
                        }
                        None => (),
                    }
                }
                println!("{}", echo);
            },
        });

        commands.push(Command {
            name: "open".to_string(),
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(arg) => {
                        File::exec(arg);
                    },
                    None => (),
                }
            },
        });

        commands.push(Command {
            name: "run".to_string(),
            main: box |args: &Vec<String>| {
                match args.get(1) {
                    Some(arg) => {
                        let path = arg.clone();
                        println!("URL: {}", path);

                        let mut commands = String::new();
                        if let Some(mut file) = File::open(&path) {
                            file.read_to_string(&mut commands);
                        }

                        for command in commands.split('\n') {
                            exec!(command);
                        }
                    }
                    None => (),
                }
            },
        });

        commands.push(Command {
            name: "send".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    for i in 2..args.len() {
                        if let Some(arg) = args.get(i) {
                            if i >= 3 {
                                string.push_str(" ");
                            }
                            string.push_str(arg);
                        }
                    }
                    string.push_str("\r\n\r\n");

                    match file.write(&string.as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }
                println!("URL: {}", path);

                if let Some(mut file) = File::open(&path) {
                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let mut command_list = String::new();
        command_list = commands.iter().fold(command_list, |l , c| l + " " + &c.name);

        commands.push(Command {
            name: "help".to_string(),
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application {
    commands: Vec<Command>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl Application {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &String) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if *command_string == "$" {
            let mut variables = String::new();
            for variable in self.variables.iter() {
                variables = variables + "\n" + &variable.name + "=" + &variable.value;
            }
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if arg.len() > 0 {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        match args.get(0) {
            Some(cmd) => {
                if cmd == "if" {
                    let mut value = false;

                    match args.get(1) {
                        Some(left) => match args.get(2) {
                            Some(cmp) => match args.get(3) {
                                Some(right) => {
                                    if cmp == "==" {
                                        value = *left == *right;
                                    } else if cmp == "!=" {
                                        value = *left != *right;
                                    } else if cmp == ">" {
                                        value = left.to_num_signed() > right.to_num_signed();
                                    } else if cmp == ">=" {
                                        value = left.to_num_signed() >= right.to_num_signed();
                                    } else if cmp == "<" {
                                        value = left.to_num_signed() < right.to_num_signed();
                                    } else if cmp == "<=" {
                                        value = left.to_num_signed() <= right.to_num_signed();
                                    } else {
                                        println!("Unknown comparison: {}", cmp);
                                    }
                                }
                                None => (),
                            },
                            None => (),
                        },
                        None => (),
                    }

                    self.modes.insert(0, Mode { value: value });
                    return;
                }

                if cmd == "else" {
                    let mut syntax_error = false;
                    match self.modes.get_mut(0) {
                        Some(mode) => mode.value = !mode.value,
                        None => syntax_error = true,
                    }
                    if syntax_error {
                        println!("Syntax error: else found with no previous if");
                    }
                    return;
                }

                if cmd == "fi" {
                    let mut syntax_error = false;
                    if self.modes.len() > 0 {
                        self.modes.remove(0);
                    } else {
                        syntax_error = true;
                    }
                    if syntax_error {
                        println!("Syntax error: fi found with no previous if");
                    }
                    return;
                }

                for mode in self.modes.iter() {
                    if !mode.value {
                        return;
                    }
                }

                //Set variables
                match cmd.find('=') {
                    Some(i) => {
                        let name = cmd[0 .. i].to_string();
                        let mut value = cmd[i + 1 .. cmd.len()].to_string();

                        if name.len() == 0 {
                            return;
                        }

                        for i in 1..args.len() {
                            match args.get(i) {
                                Some(arg) => value = value + " " + &arg,
                                None => (),
                            }
                        }

                        if value.len() == 0 {
                            let mut remove = -1;
                            for i in 0..self.variables.len() {
                                match self.variables.get(i) {
                                    Some(variable) => if variable.name == name {
                                        remove = i as isize;
                                        break;
                                    },
                                    None => break,
                                }
                            }

                            if remove >= 0 {
                                self.variables.remove(remove as usize);
                            }
                        } else {
                            for variable in self.variables.iter_mut() {
                                if variable.name == name {
                                    variable.value = value;
                                    return;
                                }
                            }

                            self.variables.push(Variable {
                                name: name,
                                value: value,
                            });
                        }
                        return;
                    }
                    None => (),
                }

                //Commands
                for command in self.commands.iter() {
                    if &command.name == cmd {
                        (*command.main)(&args);
                        return;
                    }
                }

                println!("Unknown command: '{}'", cmd);

            }
            None => (),
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title(&"Terminal".to_string());

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command.len() > 0 {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

use crate::error::*;
use crate::stream::FramedRead;
use kafka::consumer::{Consumer, FetchOffset};
use std::collections::VecDeque;

/// A consumer from Kafka
pub struct KafkaConsumer {
    consumer: Consumer,
    messages: VecDeque<Vec<u8>>,
}

impl FramedRead for KafkaConsumer {
    fn read_next_frame<'a>(
        &mut self,
        buffer: &'a mut Vec<u8>,
    ) -> std::io::Result<Option<&'a [u8]>> {
        let res = self.next().map(move |mut v| {
            std::mem::swap(&mut v, buffer);
            &buffer[..]
        });
        Ok(res)
    }
}

impl Iterator for KafkaConsumer {
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Vec<u8>> {
        if self.messages.is_empty() {
            let kafka_consumer = &mut self.consumer;
            loop {
                match kafka_consumer.poll() {
                    Ok(mss) => {
                        for ms in mss.iter() {
                            self.messages.append(
                                &mut ms
                                    .messages()
                                    .iter()
                                    .map(|z| z.value.to_vec())
                                    .collect::<VecDeque<_>>(),
                            );
                            kafka_consumer
                                .consume_messageset(ms)
                                .expect("Couldn't mark messageset as consumed");
                        }
                        kafka_consumer
                            .commit_consumed()
                            .expect("Couldn't commit consumption");
                        if !self.messages.is_empty() {
                            break;
                        }
                    }
                    Err(_) => return None,
                }
            }
        }
        self.messages.pop_front()
    }
}

impl KafkaConsumer {
    /// Return a KafkaConsumer with some basic kafka connection properties
    pub fn new(brokers: &str, topic: &str, from_beginning: bool) -> Result<KafkaConsumer> {
        let fetch_offset = if from_beginning {
            FetchOffset::Earliest
        } else {
            FetchOffset::Latest
        };
        match Consumer::from_hosts(
            brokers
                .split(',')
                .map(std::borrow::ToOwned::to_owned)
                .collect::<Vec<String>>(),
        )
        .with_topic(topic.to_owned())
        .with_fallback_offset(fetch_offset)
        .create()
        {
            Ok(consumer) => Ok(KafkaConsumer {
                consumer,
                messages: VecDeque::new(),
            }),
            Err(e) => Err(StreamDelimitError::KafkaInitializeError(e)),
        }
    }
}
<commit_msg>Increase max fetch per partition<commit_after>#![deny(missing_docs)]

use crate::error::*;
use crate::stream::FramedRead;
use kafka::consumer::{Consumer, FetchOffset};
use std::collections::VecDeque;

/// A consumer from Kafka
pub struct KafkaConsumer {
    consumer: Consumer,
    messages: VecDeque<Vec<u8>>,
}

impl FramedRead for KafkaConsumer {
    fn read_next_frame<'a>(
        &mut self,
        buffer: &'a mut Vec<u8>,
    ) -> std::io::Result<Option<&'a [u8]>> {
        let res = self.next().map(move |mut v| {
            std::mem::swap(&mut v, buffer);
            &buffer[..]
        });
        Ok(res)
    }
}

impl Iterator for KafkaConsumer {
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Vec<u8>> {
        if self.messages.is_empty() {
            let kafka_consumer = &mut self.consumer;
            loop {
                match kafka_consumer.poll() {
                    Ok(mss) => {
                        for ms in mss.iter() {
                            self.messages.append(
                                &mut ms
                                    .messages()
                                    .iter()
                                    .map(|z| z.value.to_vec())
                                    .collect::<VecDeque<_>>(),
                            );
                            kafka_consumer
                                .consume_messageset(ms)
                                .expect("Couldn't mark messageset as consumed");
                        }
                        kafka_consumer
                            .commit_consumed()
                            .expect("Couldn't commit consumption");
                        if !self.messages.is_empty() {
                            break;
                        }
                    }
                    Err(e) => {
                        eprintln!("{}", e);
                        return None;
                    }
                }
            }
        }
        self.messages.pop_front()
    }
}

impl KafkaConsumer {
    /// Return a KafkaConsumer with some basic kafka connection properties
    pub fn new(brokers: &str, topic: &str, from_beginning: bool) -> Result<KafkaConsumer> {
        let fetch_offset = if from_beginning {
            FetchOffset::Earliest
        } else {
            FetchOffset::Latest
        };
        match Consumer::from_hosts(
            brokers
                .split(',')
                .map(std::borrow::ToOwned::to_owned)
                .collect::<Vec<String>>(),
        )
        .with_topic(topic.to_owned())
        .with_fallback_offset(fetch_offset)
        .with_fetch_max_bytes_per_partition(1 * 1024 * 1024)
        .create()
        {
            Ok(consumer) => Ok(KafkaConsumer {
                consumer,
                messages: VecDeque::new(),
            }),
            Err(e) => Err(StreamDelimitError::KafkaInitializeError(e)),
        }
    }
}
<|endoftext|>


<commit_before>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype, name: String) -> T;
}

pub struct CellFormat {
    name: String,
    type_: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype, name: String) -> Cell {
        return match type_ {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None), name: name }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<commit_msg>Fix build<commit_after>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype) -> T;
}

pub struct CellFormat {
    name: String,
    type_: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype) -> Cell {
        return match type_ {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None) }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<|endoftext|>


<commit_before>use rand::Rng;

use crate::sys::config;
use crate::sys::taskserver::Control;
use super::SystemModule;
use std::collections::BTreeMap;
use std::time::{SystemTime, UNIX_EPOCH};

pub struct Twitter {
    enabled: bool,
    fake_tweet: Option<bool>,
    consumer_key   : Option<String>,
    consumer_secret: Option<String>,
    access_token   : Option<String>,
    access_secret  : Option<String>,
}

impl Twitter {
    pub fn new() -> Self {
        info!("[twitter] initialize");

        let enabled =
            config::get_bool(&["twitter", "enabled"])
            .expect("config error: twitter.enabled");
        if enabled {
            info!("[twitter] enabled");
        }
        else {
            info!("[twitter] disabled");
        }

        let (fake_tweet,
            consumer_key, consumer_secret,
            access_token, access_secret)
        = if enabled {
            (
                Some(config::get_bool(&["twitter", "fake_tweet"])
                    .expect("config error: twitter.fake_tweet")),
                Some(config::get_string(&["twitter", "consumer_key"])
                    .expect("config error: twitter.consumer_key")),
                Some(config::get_string(&["twitter", "consumer_secret"])
                    .expect("config error: twitter.consumer_secret")),
                Some(config::get_string(&["twitter", "access_token"])
                    .expect("config error: twitter.access_token")),
                Some(config::get_string(&["twitter", "access_secret"])
                    .expect("config error: twitter.access_secret")),
            )
        }
        else {
            (None, None, None, None, None)
        };

        Twitter {
            enabled, fake_tweet,
            consumer_key, consumer_secret, access_token, access_secret
        }
    }

    async fn twitter_task(&self, ctrl: &Control) {
        info!("[twitter] normal task");
    }

    async fn twitter_task_entry(ctrl: Control) {
        ctrl.sysmods().twitter.twitter_task(&ctrl).await;
    }

}

impl SystemModule for Twitter {
    fn on_start(&self, ctrl: &Control) {
        info!("[twitter] on_start");
        ctrl.spawn_oneshot_task("twitter", Twitter::twitter_task_entry);
    }
}

/*
// Twitter API 1.1
const  URL_ACCOUNT_VERIFY_CREDENTIALS: &str =
    "https://api.twitter.com/1.1/account/verify_credentials.json";
const URL_STATUSES_UPDATE: &str =
    "https://api.twitter.com/1.1/statuses/update.json";
const URL_STATUSES_HOME_TIMELINE: &str =
    "https://api.twitter.com/1.1/statuses/home_timeline.json";
const URL_STATUSES_USER_TIMELINE: &str =
    "https://api.twitter.com/1.1/statuses/user_timeline.json";
*/

// Twitter API v2
const URL_USERS_BY_USERNAME: &str =
    "https://api.twitter.com/2/users/by/username/";

/// HTTP header や query を表すデータ構造。
///
/// 署名時にソートを求められるのと、ハッシュテーブルだと最終的なリクエスト内での順番が
/// 一意にならないのが微妙な気がするので二分探索木を使うことにする。
type KeyValue = BTreeMap<String, String>;

/// https://developer.twitter.com/en/docs/authentication/oauth-1-0a/authorizing-a-request
fn create_oauth_field(consumer_key: &str, access_token: &str) -> KeyValue {
    let mut param = KeyValue::new();

    // oauth_consumer_key: アプリの識別子
    param.insert("oauth_consumer_key".into(), consumer_key.into());

    // oauth_nonce: ランダム値 (リプレイ攻撃対策)
    // 暗号学的安全性が必要か判断がつかないので安全な方にしておく
    // Twitter によるとランダムな英数字なら何でもいいらしいが、例に挙げられている
    // 32byte の乱数を BASE64 にして英数字のみを残したものとする
    let mut rng = rand::thread_rng();
    let rnd32: [u8; 4] = rng.gen();
    let rnd32_str = base64::encode(rnd32);
    let mut nonce_str = "".to_string();
    for c in rnd32_str.chars() {
        if c.is_alphanumeric() {
            nonce_str.push(c);
        }
    }
    param.insert("oauth_nonce".into(), nonce_str);

    // 署名は署名以外の o_auth フィールドに対しても行うので後で追加する
    // param.emplace("oauth_signature", sha1(...));

    // oauth_signature_method, oauth_timestamp, oauth_token, oauth_version
    param.insert("oauth_signature_method".to_string(), "HMAC-SHA1".into());
    let unix_epoch_sec = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    param.insert("oauth_timestamp".into(), unix_epoch_sec.to_string());
    param.insert("oauth_token".into(), access_token.into());
    param.insert("oauth_version".into(), "1.0".into());

    param
}

/// https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature
fn create_signature(
    http_method: &str, base_url: &str,
    oauth_param: &KeyValue, query_param: &KeyValue,
    consumer_secret: &str, token_secret: &str)
{

}
<commit_msg>署名の生成まで (未テスト)<commit_after>use crate::sys::config;
use crate::sys::taskserver::Control;
use crate::sys::net;
use super::SystemModule;
use std::collections::BTreeMap;
use std::time::{SystemTime, UNIX_EPOCH};
use rand::Rng;

pub struct Twitter {
    enabled: bool,
    fake_tweet: Option<bool>,
    consumer_key   : Option<String>,
    consumer_secret: Option<String>,
    access_token   : Option<String>,
    access_secret  : Option<String>,
}

impl Twitter {
    pub fn new() -> Self {
        info!("[twitter] initialize");

        let enabled =
            config::get_bool(&["twitter", "enabled"])
            .expect("config error: twitter.enabled");
        if enabled {
            info!("[twitter] enabled");
        }
        else {
            info!("[twitter] disabled");
        }

        let (fake_tweet,
            consumer_key, consumer_secret,
            access_token, access_secret)
        = if enabled {
            (
                Some(config::get_bool(&["twitter", "fake_tweet"])
                    .expect("config error: twitter.fake_tweet")),
                Some(config::get_string(&["twitter", "consumer_key"])
                    .expect("config error: twitter.consumer_key")),
                Some(config::get_string(&["twitter", "consumer_secret"])
                    .expect("config error: twitter.consumer_secret")),
                Some(config::get_string(&["twitter", "access_token"])
                    .expect("config error: twitter.access_token")),
                Some(config::get_string(&["twitter", "access_secret"])
                    .expect("config error: twitter.access_secret")),
            )
        }
        else {
            (None, None, None, None, None)
        };

        Twitter {
            enabled, fake_tweet,
            consumer_key, consumer_secret, access_token, access_secret
        }
    }

    async fn twitter_task(&self, ctrl: &Control) {
        info!("[twitter] normal task");
    }

    async fn twitter_task_entry(ctrl: Control) {
        ctrl.sysmods().twitter.twitter_task(&ctrl).await;
    }

}

impl SystemModule for Twitter {
    fn on_start(&self, ctrl: &Control) {
        info!("[twitter] on_start");
        ctrl.spawn_oneshot_task("twitter", Twitter::twitter_task_entry);
    }
}

/*
// Twitter API 1.1
const  URL_ACCOUNT_VERIFY_CREDENTIALS: &str =
    "https://api.twitter.com/1.1/account/verify_credentials.json";
const URL_STATUSES_UPDATE: &str =
    "https://api.twitter.com/1.1/statuses/update.json";
const URL_STATUSES_HOME_TIMELINE: &str =
    "https://api.twitter.com/1.1/statuses/home_timeline.json";
const URL_STATUSES_USER_TIMELINE: &str =
    "https://api.twitter.com/1.1/statuses/user_timeline.json";
*/

// Twitter API v2
const URL_USERS_BY_USERNAME: &str =
    "https://api.twitter.com/2/users/by/username/";

/// HTTP header や query を表すデータ構造。
///
/// 署名時にソートを求められるのと、ハッシュテーブルだと最終的なリクエスト内での順番が
/// 一意にならないのが微妙な気がするので二分探索木を使うことにする。
type KeyValue = BTreeMap<String, String>;

/// https://developer.twitter.com/en/docs/authentication/oauth-1-0a/authorizing-a-request
fn create_oauth_field(consumer_key: &str, access_token: &str) -> KeyValue {
    let mut param = KeyValue::new();

    // oauth_consumer_key: アプリの識別子
    param.insert("oauth_consumer_key".into(), consumer_key.into());

    // oauth_nonce: ランダム値 (リプレイ攻撃対策)
    // 暗号学的安全性が必要か判断がつかないので安全な方にしておく
    // Twitter によるとランダムな英数字なら何でもいいらしいが、例に挙げられている
    // 32byte の乱数を BASE64 にして英数字のみを残したものとする
    let mut rng = rand::thread_rng();
    let rnd32: [u8; 4] = rng.gen();
    let rnd32_str = base64::encode(rnd32);
    let mut nonce_str = "".to_string();
    for c in rnd32_str.chars() {
        if c.is_alphanumeric() {
            nonce_str.push(c);
        }
    }
    param.insert("oauth_nonce".into(), nonce_str);

    // 署名は署名以外の oauth_* フィールドに対しても行う
    // 今はまだ不明なので後で追加する
    // param.emplace("oauth_signature", sha1(...));

    // oauth_signature_method, oauth_timestamp, oauth_token, oauth_version
    param.insert("oauth_signature_method".to_string(), "HMAC-SHA1".into());
    let unix_epoch_sec = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();
    param.insert("oauth_timestamp".into(), unix_epoch_sec.to_string());
    param.insert("oauth_token".into(), access_token.into());
    param.insert("oauth_version".into(), "1.0".into());

    param
}

/// https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature
///
/// oauth_param, query_param, body_param 内でキーの重複があると panic する。
fn create_signature(
    http_method: &str, base_url: &str,
    oauth_param: &KeyValue, query_param: &KeyValue, body_param: &KeyValue,
    consumer_secret: &str, token_secret: &str)
    -> String
{
    // "Collecting the request method and URL"
    // Example:
    // http_method = POST
    // base_url = https://api.twitter.com/1.1/statuses/update.json

    // "Collecting parameters"
    // 以下の percent encode 前データを percent encode しながら 1つにまとめて
    // キーの辞書順にソートする
    // キーの重複は Twitter では認められていないのでシンプルに考えて OK
    // * URL 末尾の query
    // * request body
    // * HTTP header の oauth_* パラメタ
    //
    // 1. Percent encode every key and value that will be signed.
    // 2. Sort the list of parameters alphabetically [1] by encoded key [2].
    // 3. For each key/value pair:
    // 4. Append the encoded key to the output string.
    // 5. Append the ‘=’ character to the output string.
    // 6. Append the encoded value to the output string.
    // 7. If there are more key/value pairs remaining, append a ‘&’ character to the output string.

    // 1-2
    let mut param = KeyValue::new();
    let encode_add =
    |param: &mut KeyValue, src: &KeyValue| {
        for (k, v) in src.iter() {
            let old = param.insert(
                net::percent_encode(k),
                net::percent_encode(v));
            if old.is_some() {
                panic!("duplicate key: {}", k);
            }
        }
    };
    encode_add(&mut param, oauth_param);
    encode_add(&mut param, query_param);
    encode_add(&mut param, body_param);

    // 3-7
    let mut parameter_string = "".to_string();
    let mut is_first = true;
    for (k, v) in param {
        if is_first {
            is_first = false;
        }
        else {
            parameter_string.push_str(&k);
            parameter_string.push('=');
            parameter_string.push_str(&v);
            parameter_string.push('&');
        }
    }

    // "Creating the signature base string"
    // "signature base string" by OAuth spec
    // 署名対象となる文字列を生成する
    // method, url, param を & でつなげるだけ
    //
    // 1. Convert the HTTP Method to uppercase and set the output string equal to this value.
    // 2. Append the ‘&’ character to the output string.
    // 3. Percent encode the URL and append it to the output string.
    // 4. Append the ‘&’ character to the output string.
    // 5. Percent encode the parameter string and append it to the output string.
    let mut signature_base_string = "".to_string();
    signature_base_string.push_str(&http_method.to_ascii_uppercase());
    signature_base_string.push('&');
    signature_base_string.push_str(&net::percent_encode(base_url));
    signature_base_string.push('&');
    signature_base_string.push_str(&net::percent_encode(&parameter_string));

    // "Getting a signing key"
    // 署名鍵は consumer_secret と token_secret をエスケープして & でつなぐだけ
    let mut signing_key = "".to_string();
    signing_key.push_str(consumer_secret);
    signing_key.push('&');
    signing_key.push_str(token_secret);

    // "Calculating the signature"
    // HMAC SHA1
    let result = net::hmac_sha1(
        signing_key.as_bytes(),
        signature_base_string.as_bytes());

    // base64 encode したものを署名として "oauth_signature" に設定する
    base64::encode(result.into_bytes())
}
<|endoftext|>


<commit_before>use crate::device::physical::{
    ConformanceVersion, DriverId, PhysicalDeviceType, PointClippingBehavior, ShaderCoreProperties,
    ShaderFloatControlsIndependence, SubgroupFeatures,
};
use crate::image::{SampleCount, SampleCounts};
use crate::pipeline::shader::ShaderStages;
use crate::render_pass::ResolveModes;
use crate::Version;
use std::convert::TryInto;
use std::ffi::CStr;

pub use crate::autogen::Properties;
pub(crate) use crate::autogen::PropertiesFfi;

// A bit of a hack...
// TODO: integrate into autogen?
pub(crate) trait FromVulkan<F>
where
    Self: Sized,
{
    fn from_vulkan(val: F) -> Option<Self>;
}

impl FromVulkan<u8> for u8 {
    #[inline]
    fn from_vulkan(val: u8) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[u8; N]> for [u8; N] {
    #[inline]
    fn from_vulkan(val: [u8; N]) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<u32> for u32 {
    #[inline]
    fn from_vulkan(val: u32) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[u32; N]> for [u32; N] {
    #[inline]
    fn from_vulkan(val: [u32; N]) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<u64> for u64 {
    #[inline]
    fn from_vulkan(val: u64) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<usize> for usize {
    #[inline]
    fn from_vulkan(val: usize) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<i32> for i32 {
    #[inline]
    fn from_vulkan(val: i32) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<i64> for i64 {
    #[inline]
    fn from_vulkan(val: i64) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<f32> for f32 {
    #[inline]
    fn from_vulkan(val: f32) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[f32; N]> for [f32; N] {
    #[inline]
    fn from_vulkan(val: [f32; N]) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[std::os::raw::c_char; N]> for String {
    #[inline]
    fn from_vulkan(val: [i8; N]) -> Option<Self> {
        Some(unsafe { CStr::from_ptr(val.as_ptr()).to_string_lossy().into_owned() })
    }
}

impl FromVulkan<u32> for Version {
    #[inline]
    fn from_vulkan(val: u32) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::Bool32> for bool {
    #[inline]
    fn from_vulkan(val: ash::vk::Bool32) -> Option<Self> {
        Some(val != 0)
    }
}

impl FromVulkan<ash::vk::ConformanceVersion> for ConformanceVersion {
    #[inline]
    fn from_vulkan(val: ash::vk::ConformanceVersion) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::DriverId> for DriverId {
    #[inline]
    fn from_vulkan(val: ash::vk::DriverId) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::Extent2D> for [u32; 2] {
    #[inline]
    fn from_vulkan(val: ash::vk::Extent2D) -> Option<Self> {
        Some([val.width, val.height])
    }
}

impl FromVulkan<ash::vk::PhysicalDeviceType> for PhysicalDeviceType {
    #[inline]
    fn from_vulkan(val: ash::vk::PhysicalDeviceType) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::PointClippingBehavior> for PointClippingBehavior {
    #[inline]
    fn from_vulkan(val: ash::vk::PointClippingBehavior) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ResolveModeFlags> for ResolveModes {
    #[inline]
    fn from_vulkan(val: ash::vk::ResolveModeFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SampleCountFlags> for SampleCounts {
    #[inline]
    fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SampleCountFlags> for SampleCount {
    #[inline]
    fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ShaderCorePropertiesFlagsAMD> for ShaderCoreProperties {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::ShaderFloatControlsIndependence> for ShaderFloatControlsIndependence {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderFloatControlsIndependence) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ShaderStageFlags> for ShaderStages {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderStageFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SubgroupFeatureFlags> for SubgroupFeatures {
    #[inline]
    fn from_vulkan(val: ash::vk::SubgroupFeatureFlags) -> Option<Self> {
        Some(val.into())
    }
}
<commit_msg>Fixed #1678 (#1679)<commit_after>use crate::device::physical::{
    ConformanceVersion, DriverId, PhysicalDeviceType, PointClippingBehavior, ShaderCoreProperties,
    ShaderFloatControlsIndependence, SubgroupFeatures,
};
use crate::image::{SampleCount, SampleCounts};
use crate::pipeline::shader::ShaderStages;
use crate::render_pass::ResolveModes;
use crate::Version;
use std::convert::TryInto;
use std::ffi::CStr;

pub use crate::autogen::Properties;
pub(crate) use crate::autogen::PropertiesFfi;

// A bit of a hack...
// TODO: integrate into autogen?
pub(crate) trait FromVulkan<F>
where
    Self: Sized,
{
    fn from_vulkan(val: F) -> Option<Self>;
}

impl FromVulkan<u8> for u8 {
    #[inline]
    fn from_vulkan(val: u8) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[u8; N]> for [u8; N] {
    #[inline]
    fn from_vulkan(val: [u8; N]) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<u32> for u32 {
    #[inline]
    fn from_vulkan(val: u32) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[u32; N]> for [u32; N] {
    #[inline]
    fn from_vulkan(val: [u32; N]) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<u64> for u64 {
    #[inline]
    fn from_vulkan(val: u64) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<usize> for usize {
    #[inline]
    fn from_vulkan(val: usize) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<i32> for i32 {
    #[inline]
    fn from_vulkan(val: i32) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<i64> for i64 {
    #[inline]
    fn from_vulkan(val: i64) -> Option<Self> {
        Some(val)
    }
}

impl FromVulkan<f32> for f32 {
    #[inline]
    fn from_vulkan(val: f32) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[f32; N]> for [f32; N] {
    #[inline]
    fn from_vulkan(val: [f32; N]) -> Option<Self> {
        Some(val)
    }
}

impl<const N: usize> FromVulkan<[std::os::raw::c_char; N]> for String {
    #[inline]
    fn from_vulkan(val: [std::os::raw::c_char; N]) -> Option<Self> {
        Some(unsafe { CStr::from_ptr(val.as_ptr()).to_string_lossy().into_owned() })
    }
}

impl FromVulkan<u32> for Version {
    #[inline]
    fn from_vulkan(val: u32) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::Bool32> for bool {
    #[inline]
    fn from_vulkan(val: ash::vk::Bool32) -> Option<Self> {
        Some(val != 0)
    }
}

impl FromVulkan<ash::vk::ConformanceVersion> for ConformanceVersion {
    #[inline]
    fn from_vulkan(val: ash::vk::ConformanceVersion) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::DriverId> for DriverId {
    #[inline]
    fn from_vulkan(val: ash::vk::DriverId) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::Extent2D> for [u32; 2] {
    #[inline]
    fn from_vulkan(val: ash::vk::Extent2D) -> Option<Self> {
        Some([val.width, val.height])
    }
}

impl FromVulkan<ash::vk::PhysicalDeviceType> for PhysicalDeviceType {
    #[inline]
    fn from_vulkan(val: ash::vk::PhysicalDeviceType) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::PointClippingBehavior> for PointClippingBehavior {
    #[inline]
    fn from_vulkan(val: ash::vk::PointClippingBehavior) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ResolveModeFlags> for ResolveModes {
    #[inline]
    fn from_vulkan(val: ash::vk::ResolveModeFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SampleCountFlags> for SampleCounts {
    #[inline]
    fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SampleCountFlags> for SampleCount {
    #[inline]
    fn from_vulkan(val: ash::vk::SampleCountFlags) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ShaderCorePropertiesFlagsAMD> for ShaderCoreProperties {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderCorePropertiesFlagsAMD) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::ShaderFloatControlsIndependence> for ShaderFloatControlsIndependence {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderFloatControlsIndependence) -> Option<Self> {
        val.try_into().ok()
    }
}

impl FromVulkan<ash::vk::ShaderStageFlags> for ShaderStages {
    #[inline]
    fn from_vulkan(val: ash::vk::ShaderStageFlags) -> Option<Self> {
        Some(val.into())
    }
}

impl FromVulkan<ash::vk::SubgroupFeatureFlags> for SubgroupFeatures {
    #[inline]
    fn from_vulkan(val: ash::vk::SubgroupFeatureFlags) -> Option<Self> {
        Some(val.into())
    }
}
<|endoftext|>


<commit_before>/// Declare a new alias for a table
///
/// Example usage
/// -------------
/// ```rust
/// # include!("../../doctest_setup.rs");
/// fn main() {
///     use schema::users;
///     let connection = &mut establish_connection();
///     let (users1, users2) = diesel::alias!(schema::users as user1, schema::users as user2);
///     let res = users1
///         .inner_join(users2.on(users1.field(users::id).eq(users2.field(users::id))))
///         .select((users1.fields((users::id, users::name)), users2.field(users::name)))
///         .order_by(users2.field(users::id))
///         .load::<((i32, String), String)>(connection);
///     assert_eq!(
///         res,
///         Ok(vec![
///             ((1, "Sean".to_owned()), "Sean".to_owned()),
///             ((2, "Tess".to_owned()), "Tess".to_owned()),
///         ]),
///     );
/// }
/// ```
///
///
/// Make type expressable
/// ---------------------
/// It may sometimes be useful to declare an alias at the module level, in such a way that the type
/// of a query using it can be expressed (to not declare it anonymously).
///
/// This can be achieved in the following way
/// ```rust
/// # include!("../../doctest_setup.rs");
/// use diesel::{query_source::Alias, dsl};
///
/// diesel::alias!(schema::users as users_alias: UsersAlias);
/// // or
/// diesel::alias!{
///     const USERS_ALIAS_2: Alias<UsersAlias2> = schema::users as users_alias_2;
/// }
///
/// fn some_function_that_returns_a_query_fragment(
/// ) -> dsl::InnerJoin<schema::posts::table, Alias<UsersAlias>>
/// {
///     schema::posts::table.inner_join(users_alias)
/// }
/// # fn main() {
/// #     some_function_that_returns_a_query_fragment();
/// #     schema::posts::table.inner_join(USERS_ALIAS_2);
/// # }
/// ```
///
/// Note that you may also use this form within a function, in the following way:
/// ```rust
/// # include!("../../doctest_setup.rs");
/// fn main() {
///     diesel::alias!(schema::users as users_alias: UsersAlias);
///     users_alias.inner_join(schema::posts::table);
/// }
/// ```
///
/// Troubleshooting and limitations
/// -------------------------------
/// If you encounter a **compilation error** where "the trait
/// `AppearsInFromClause<Alias<your_alias>>` is not implemented", when trying to use two aliases to
/// the same table within a single query note the following two limitations:
///  - You will need to declare these in a single `alias!` call.
///  - The path to the table module will have to be expressed in the exact same
///    manner. (That is, you can do `alias!(schema::users as user1, schema::users as user2)`
///    or `alias!(users as user1, users as user2)`, but not
///    `alias!(schema::users as user1, users as user2)`)
#[macro_export]
macro_rules! alias {
    ($($($table: ident)::+ as $alias: ident),* $(,)?) => {{
        $crate::alias!(NoConst $($($table)::+ as $alias: $alias,)*);
        ($($crate::query_source::Alias::<$alias>::default()),*)
    }};
    ($($($table: ident)::+ as $alias_name: ident: $alias_ty: ident),* $(,)?) => {
        $crate::alias! {
            $(
                const $alias_name: Alias<$alias_ty> = $($table)::+ as $alias_name;
            )*
        }
    };
    ($(const $const_name: ident: Alias<$alias_ty: ident> = $($table: ident)::+ as $alias_sql_name: ident);* $(;)?) => {
        $crate::alias!(NoConst $($($table)::+ as $alias_sql_name: $alias_ty,)*);
        $(
            #[allow(non_upper_case_globals)]
            const $const_name: $crate::query_source::Alias::<$alias_ty> = $crate::query_source::Alias::new($alias_ty);
        )*
    };
    (NoConst $($($table: ident)::+ as $alias_sql_name: ident: $alias_ty: ident),* $(,)?) => {
        $(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Clone, Copy, Default)]
            struct $alias_ty;

            impl $crate::query_source::aliasing::AliasSource for $alias_ty {
                const NAME: &'static str = stringify!($alias_sql_name);
                type Table = $($table)::+::table;
            }

            // impl AppearsInFromClause<Alias<$alias>> for Alias<$alias>
            impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$($table)::+::table, $alias_ty, $alias_ty> for $($table)::+::table {
                type Count = $crate::query_source::Once;
            }
        )*
        $crate::__internal_alias_helper!($(table_ty = $($table)::+::table, table_tt = ($($table)::+), alias_ty = $alias_ty;)*);
    };
}

#[macro_export]
#[doc(hidden)]
/// This only exists to hide internals from the doc
macro_rules! __internal_alias_helper {
    (
        table_ty = $left_table_ty: ty, table_tt = $left_table_tt: tt, alias_ty = $left_alias: ident;
        $(table_ty = $right_table_ty: ty, table_tt = $right_table_tt: tt, alias_ty = $right_alias: ident;)+
    ) => {
        $(
            $crate::static_cond!{if ($left_table_tt) == ($right_table_tt) {
                impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$left_table_ty, $right_alias, $left_alias>
                    for $right_table_ty
                {
                    type Count = $crate::query_source::Never;
                }
                impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$right_table_ty, $left_alias, $right_alias>
                    for $left_table_ty
                {
                    type Count = $crate::query_source::Never;
                }
            }}
        )*
        $crate::__internal_alias_helper!($(table_ty = $right_table_ty, table_tt = $right_table_tt, alias_ty = $right_alias;)+);
    };

    (table_ty = $left_table_ty: ty, table_tt = $left_table_tt: tt, alias_ty = $left_alias: ident;) => {};
    () => {};
}
<commit_msg>Prevent two aliases to be declared with the same SQL name for use within a single query<commit_after>/// Declare a new alias for a table
///
/// Example usage
/// -------------
/// ```rust
/// # include!("../../doctest_setup.rs");
/// fn main() {
///     use schema::users;
///     let connection = &mut establish_connection();
///     let (users1, users2) = diesel::alias!(schema::users as user1, schema::users as user2);
///     let res = users1
///         .inner_join(users2.on(users1.field(users::id).eq(users2.field(users::id))))
///         .select((users1.fields((users::id, users::name)), users2.field(users::name)))
///         .order_by(users2.field(users::id))
///         .load::<((i32, String), String)>(connection);
///     assert_eq!(
///         res,
///         Ok(vec![
///             ((1, "Sean".to_owned()), "Sean".to_owned()),
///             ((2, "Tess".to_owned()), "Tess".to_owned()),
///         ]),
///     );
/// }
/// ```
///
///
/// Make type expressable
/// ---------------------
/// It may sometimes be useful to declare an alias at the module level, in such a way that the type
/// of a query using it can be expressed (to not declare it anonymously).
///
/// This can be achieved in the following way
/// ```rust
/// # include!("../../doctest_setup.rs");
/// use diesel::{query_source::Alias, dsl};
///
/// diesel::alias!(schema::users as users_alias: UsersAlias);
/// // or
/// diesel::alias!{
///     const USERS_ALIAS_2: Alias<UsersAlias2> = schema::users as users_alias_2;
/// }
///
/// fn some_function_that_returns_a_query_fragment(
/// ) -> dsl::InnerJoin<schema::posts::table, Alias<UsersAlias>>
/// {
///     schema::posts::table.inner_join(users_alias)
/// }
/// # fn main() {
/// #     some_function_that_returns_a_query_fragment();
/// #     schema::posts::table.inner_join(USERS_ALIAS_2);
/// # }
/// ```
///
/// Note that you may also use this form within a function, in the following way:
/// ```rust
/// # include!("../../doctest_setup.rs");
/// fn main() {
///     diesel::alias!(schema::users as users_alias: UsersAlias);
///     users_alias.inner_join(schema::posts::table);
/// }
/// ```
///
/// Troubleshooting and limitations
/// -------------------------------
/// If you encounter a **compilation error** where "the trait
/// `AppearsInFromClause<Alias<your_alias>>` is not implemented", when trying to use two aliases to
/// the same table within a single query note the following two limitations:
///  - You will need to declare these in a single `alias!` call.
///  - The path to the table module will have to be expressed in the exact same
///    manner. (That is, you can do `alias!(schema::users as user1, schema::users as user2)`
///    or `alias!(users as user1, users as user2)`, but not
///    `alias!(schema::users as user1, users as user2)`)
#[macro_export]
macro_rules! alias {
    ($($($table: ident)::+ as $alias: ident),* $(,)?) => {{
        $crate::alias!(NoConst $($($table)::+ as $alias: $alias,)*);
        ($($crate::query_source::Alias::<$alias>::default()),*)
    }};
    ($($($table: ident)::+ as $alias_name: ident: $alias_ty: ident),* $(,)?) => {
        $crate::alias! {
            $(
                const $alias_name: Alias<$alias_ty> = $($table)::+ as $alias_name;
            )*
        }
    };
    ($(const $const_name: ident: Alias<$alias_ty: ident> = $($table: ident)::+ as $alias_sql_name: ident);* $(;)?) => {
        $crate::alias!(NoConst $($($table)::+ as $alias_sql_name: $alias_ty,)*);
        $(
            #[allow(non_upper_case_globals)]
            const $const_name: $crate::query_source::Alias::<$alias_ty> = $crate::query_source::Alias::new($alias_ty);
        )*
    };
    (NoConst $($($table: ident)::+ as $alias_sql_name: ident: $alias_ty: ident),* $(,)?) => {
        $(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Clone, Copy, Default)]
            struct $alias_ty;

            impl $crate::query_source::aliasing::AliasSource for $alias_ty {
                const NAME: &'static str = stringify!($alias_sql_name);
                type Table = $($table)::+::table;
            }

            // impl AppearsInFromClause<Alias<$alias>> for Alias<$alias>
            impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$($table)::+::table, $alias_ty, $alias_ty> for $($table)::+::table {
                type Count = $crate::query_source::Once;
            }
        )*
        $crate::__internal_alias_helper!($(table_ty = $($table)::+::table, table_tt = ($($table)::+), alias_ty = $alias_ty, alias_sql_name = $alias_sql_name;)*);
    };
}

#[macro_export]
#[doc(hidden)]
/// This only exists to hide internals from the doc
// The `($left_sql_name) != ($right_sql_name)` condition is not perfect because a user could still
// cause runtime errors by declaring two aliases to different tables with the same name then use
// them in the same query, but that would almost have to be voluntary, so this alone should prevent
// most mistakes.
macro_rules! __internal_alias_helper {
    (
        table_ty = $left_table_ty: ty, table_tt = $left_table_tt: tt, alias_ty = $left_alias: ident, alias_sql_name = $left_sql_name: ident;
        $(table_ty = $right_table_ty: ty, table_tt = $right_table_tt: tt, alias_ty = $right_alias: ident, alias_sql_name = $right_sql_name: ident;)+
    ) => {
        $(
            $crate::static_cond!{if ($left_table_tt) == ($right_table_tt) {
                $crate::static_cond!{if ($left_sql_name) != ($right_sql_name) {
                    impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$left_table_ty, $right_alias, $left_alias>
                        for $right_table_ty
                    {
                        type Count = $crate::query_source::Never;
                    }
                    impl $crate::query_source::aliasing::AliasAliasAppearsInFromClause<$right_table_ty, $left_alias, $right_alias>
                        for $left_table_ty
                    {
                        type Count = $crate::query_source::Never;
                    }
                }}
            }}
        )*
        $crate::__internal_alias_helper!($(table_ty = $right_table_ty, table_tt = $right_table_tt, alias_ty = $right_alias, alias_sql_name = $right_sql_name;)+);
    };

    (table_ty = $left_table_ty: ty, table_tt = $left_table_tt: tt, alias_ty = $left_alias: ident, alias_sql_name = $left_sql_name: ident;) => {};
    () => {};
}
<|endoftext|>