<commit_before>use quote::quote;

use crate::parse;

pub fn generate_compile_module(
    parsed: &parse::Items,
) -> Result<proc_macro2::TokenStream, syn::Error> {
    let items = parsed
        .items
        .iter()
        .flat_map(|item| match item {
            parse::Item::Single(item) if item.no_compile.is_none() => {
                Some(generate_single_item(item))
            }
            parse::Item::Group(item) => Some(generate_group(item)),
            parse::Item::Flags(item) => Some(generate_flags(item)),
            _ => None,
        })
        .collect::<Result<Vec<_>, _>>()?;

    let use_paths = parsed.use_stmts.iter().map(|stmt| stmt.compile_use_stmt());
    // we use these types directly, so reexport from compile directory
    let use_manual_impls = parsed.items.iter().filter_map(|item| match item {
        parse::Item::RawEnum(parse::RawEnum { name, .. })
        | parse::Item::Flags(parse::BitFlags { name, .. }) => Some(quote!(super::#name)),
        _ => None,
    });

    let custom_compile_types = &parsed.compile_types;
    Ok(quote! {
        #[cfg(feature = "compile")]
        pub mod compile {
            use crate::compile::*;
            use font_types::*;
            #(use #use_paths;)*
            #(use #use_manual_impls;)*

            #(#custom_compile_types)*

            #(#items)*
        }
    })
}

fn generate_single_item(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;

    let mut field_decls = Vec::new();

    for field in &item.fields {
        if field.is_computed() {
            continue;
        }
        let name = field.name();
        let typ = field.compile_type();
        field_decls.push(quote!(pub #name: #typ));
    }

    let impl_to_owned = item_to_owned(item)?;
    let impl_font_write = item_font_write(item)?;

    Ok(quote! {
        #[derive(Debug, Default, PartialEq)]
        pub struct #name {
            #(#field_decls,)*
        }

        #impl_to_owned

        #impl_font_write

        impl #name {
            pub fn new() -> Self {
                Default::default()
            }
        }
    })
}

fn item_to_owned(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;
    let lifetime = item.lifetime.is_some().then(|| quote!(<'_>));
    let set_offset_bytes = item
        .offset_host
        .is_some()
        .then(|| quote!(let offset_data = self.bytes();));
    let field_inits = item
        .fields
        .iter()
        .filter(|fld| !fld.is_computed())
        .map(|fld| {
            let name = fld.name();
            let expr = fld.to_owned_expr();
            expr.map(|expr| quote!(#name: #expr))
        })
        .collect::<Result<Vec<_>, _>>()?;

    let impl_to_owned_table = item
        .offset_host
        .is_some()
        .then(|| quote!(impl ToOwnedTable for super:: #name #lifetime {}));
    let allow_dead = (item.offset_host.is_some() || !item.has_field_with_lifetime())
        .then(|| quote!(#[allow(unused_variables)]));

    Ok(quote! {
        impl ToOwnedObj for super::#name #lifetime {
            type Owned = #name;
            #allow_dead
            fn to_owned_obj(&self, offset_data: &[u8]) -> Option<Self::Owned> {
                #set_offset_bytes
                Some(#name {
                    #(#field_inits,)*
                })
            }
        }

        #impl_to_owned_table
    })
}

fn item_font_write(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;

    let field_exprs = item.fields.iter().map(|fld| fld.font_write_expr());

    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                #(#field_exprs)*

            }
        }

    })
}

fn generate_group(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let variants = group.variants.iter().map(|variant| {
        let name = &variant.name;
        let typ = &variant.typ;
        quote!(#name(#typ))
    });

    let first_variant = &group
        .variants
        .iter()
        .next()
        .ok_or_else(|| syn::Error::new(name.span(), "empty enums are not allowed"))?
        .name;

    let impl_to_owned = group_to_owned(group)?;
    let impl_font_write = group_font_write(group)?;

    Ok(quote! {
        #[derive(Debug, PartialEq)]
        pub enum #name {
            #(#variants),*
        }

        #impl_to_owned

        #impl_font_write

        impl Default for #name {
            fn default() -> Self {
                Self::#first_variant(Default::default())
            }
        }
    })
}

fn group_to_owned(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let lifetime = group.lifetime.is_some().then(|| quote!(<'_>));
    let match_arms = group.variants.iter().map(|variant| {
        let var_name = &variant.name;
        quote!(super::#name::#var_name(item) => #name::#var_name(item.to_owned_obj(offset_data)?))
    });

    let impl_to_owned_table = group
        .offset_host
        .is_some()
        .then(|| quote!(impl ToOwnedTable for super:: #name #lifetime {}));

    Ok(quote! {
        impl ToOwnedObj for super::#name #lifetime {
            type Owned = #name;
            fn to_owned_obj(&self, offset_data: &[u8]) -> Option<Self::Owned> {
                Some(match self {
                    #(#match_arms,)*
                })
            }
        }

        #impl_to_owned_table
    })
}

fn group_font_write(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let match_arms = group.variants.iter().map(|variant| {
        let var_name = &variant.name;
        quote!( Self::#var_name(item) => item.write_into(writer), )
    });

    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                match self {
                    #(#match_arms)*
                }
            }
        }
    })
}

fn generate_flags(item: &parse::BitFlags) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;
    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                self.bits().write_into(writer)
            }
        }
    })
}
<commit_msg>[codegen] Remove default/new methods<commit_after>use quote::quote;

use crate::parse;

pub fn generate_compile_module(
    parsed: &parse::Items,
) -> Result<proc_macro2::TokenStream, syn::Error> {
    let items = parsed
        .items
        .iter()
        .flat_map(|item| match item {
            parse::Item::Single(item) if item.no_compile.is_none() => {
                Some(generate_single_item(item))
            }
            parse::Item::Group(item) => Some(generate_group(item)),
            parse::Item::Flags(item) => Some(generate_flags(item)),
            _ => None,
        })
        .collect::<Result<Vec<_>, _>>()?;

    let use_paths = parsed.use_stmts.iter().map(|stmt| stmt.compile_use_stmt());
    // we use these types directly, so reexport from compile directory
    let use_manual_impls = parsed.items.iter().filter_map(|item| match item {
        parse::Item::RawEnum(parse::RawEnum { name, .. })
        | parse::Item::Flags(parse::BitFlags { name, .. }) => Some(quote!(super::#name)),
        _ => None,
    });

    let custom_compile_types = &parsed.compile_types;
    Ok(quote! {
        #[cfg(feature = "compile")]
        pub mod compile {
            use crate::compile::*;
            use font_types::*;
            #(use #use_paths;)*
            #(use #use_manual_impls;)*

            #(#custom_compile_types)*

            #(#items)*
        }
    })
}

fn generate_single_item(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;

    let mut field_decls = Vec::new();

    for field in &item.fields {
        if field.is_computed() {
            continue;
        }
        let name = field.name();
        let typ = field.compile_type();
        field_decls.push(quote!(pub #name: #typ));
    }

    let impl_to_owned = item_to_owned(item)?;
    let impl_font_write = item_font_write(item)?;

    Ok(quote! {
        #[derive(Debug, PartialEq)]
        pub struct #name {
            #(#field_decls,)*
        }

        #impl_to_owned

        #impl_font_write
    })
}

fn item_to_owned(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;
    let lifetime = item.lifetime.is_some().then(|| quote!(<'_>));
    let set_offset_bytes = item
        .offset_host
        .is_some()
        .then(|| quote!(let offset_data = self.bytes();));
    let field_inits = item
        .fields
        .iter()
        .filter(|fld| !fld.is_computed())
        .map(|fld| {
            let name = fld.name();
            let expr = fld.to_owned_expr();
            expr.map(|expr| quote!(#name: #expr))
        })
        .collect::<Result<Vec<_>, _>>()?;

    let impl_to_owned_table = item
        .offset_host
        .is_some()
        .then(|| quote!(impl ToOwnedTable for super:: #name #lifetime {}));
    let allow_dead = (item.offset_host.is_some() || !item.has_field_with_lifetime())
        .then(|| quote!(#[allow(unused_variables)]));

    Ok(quote! {
        impl ToOwnedObj for super::#name #lifetime {
            type Owned = #name;
            #allow_dead
            fn to_owned_obj(&self, offset_data: &[u8]) -> Option<Self::Owned> {
                #set_offset_bytes
                Some(#name {
                    #(#field_inits,)*
                })
            }
        }

        #impl_to_owned_table
    })
}

fn item_font_write(item: &parse::SingleItem) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;

    let field_exprs = item.fields.iter().map(|fld| fld.font_write_expr());

    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                #(#field_exprs)*

            }
        }

    })
}

fn generate_group(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let variants = group.variants.iter().map(|variant| {
        let name = &variant.name;
        let typ = &variant.typ;
        quote!(#name(#typ))
    });

    let impl_to_owned = group_to_owned(group)?;
    let impl_font_write = group_font_write(group)?;

    Ok(quote! {
        #[derive(Debug, PartialEq)]
        pub enum #name {
            #(#variants),*
        }

        #impl_to_owned

        #impl_font_write

    })
}

fn group_to_owned(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let lifetime = group.lifetime.is_some().then(|| quote!(<'_>));
    let match_arms = group.variants.iter().map(|variant| {
        let var_name = &variant.name;
        quote!(super::#name::#var_name(item) => #name::#var_name(item.to_owned_obj(offset_data)?))
    });

    let impl_to_owned_table = group
        .offset_host
        .is_some()
        .then(|| quote!(impl ToOwnedTable for super:: #name #lifetime {}));

    Ok(quote! {
        impl ToOwnedObj for super::#name #lifetime {
            type Owned = #name;
            fn to_owned_obj(&self, offset_data: &[u8]) -> Option<Self::Owned> {
                Some(match self {
                    #(#match_arms,)*
                })
            }
        }

        #impl_to_owned_table
    })
}

fn group_font_write(group: &parse::ItemGroup) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &group.name;
    let match_arms = group.variants.iter().map(|variant| {
        let var_name = &variant.name;
        quote!( Self::#var_name(item) => item.write_into(writer), )
    });

    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                match self {
                    #(#match_arms)*
                }
            }
        }
    })
}

fn generate_flags(item: &parse::BitFlags) -> Result<proc_macro2::TokenStream, syn::Error> {
    let name = &item.name;
    Ok(quote! {
        impl FontWrite for #name {
            fn write_into(&self, writer: &mut TableWriter) {
                self.bits().write_into(writer)
            }
        }
    })
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use internal::prelude::*;
use serde_json;
use std::{
    ffi::OsStr,
    fs::File,
    io::{
        BufReader,
        ErrorKind as IoErrorKind,
        Read,
        Result as IoResult
    },
    process::{
        Child,
        Command,
        Stdio
    },
    result::Result as StdResult
};
use super::{
    AudioSource,
    AudioType,
    DcaError,
    DcaMetadata,
    VoiceError
};

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

impl Drop for ChildContainer {
    fn drop (&mut self) {
        if let Err(e) = self.0.kill() {
            debug!("[Voice] Error awaiting child process: {:?}", e);
        }
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => if e.kind() == IoErrorKind::UnexpectedEof {
                Some(Vec::new())
            } else {
                None
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    _ffmpeg(path.as_ref())
}

fn _ffmpeg(path: &OsStr) -> Result<Box<AudioSource>> {
    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    ffmpeg_optioned(path, &[
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ])
}

/// Opens an audio file through `ffmpeg` and creates an audio source, with
/// user-specified arguments to pass to ffmpeg.
///
/// Note that this does _not_ build on the arguments passed by the [`ffmpeg`]
/// function.
///
/// # Examples
///
/// Pass options to create a custom ffmpeg streamer:
///
/// ```rust,no_run
/// use serenity::voice;
///
/// let stereo_val = "2";
///
/// let streamer = voice::ffmpeg_optioned("./some_file.mp3", &[
///     "-f",
///     "s16le",
///     "-ac",
///     stereo_val,
///     "-ar",
///     "48000",
///     "-acodec",
///     "pcm_s16le",
///     "-",
/// ]);
pub fn ffmpeg_optioned<P: AsRef<OsStr>>(
    path: P,
    args: &[&str],
) -> Result<Box<AudioSource>> {
    _ffmpeg_optioned(path.as_ref(), args)
}

fn _ffmpeg_optioned(path: &OsStr, args: &[&str]) -> Result<Box<AudioSource>> {
    let is_stereo = is_stereo(path).unwrap_or(false);

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    _dca(path.as_ref())
}

fn _dca(path: &OsStr) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source. This makes certain assumptions: namely, that the input stream
/// is composed ONLY of opus frames of the variety that Discord expects.
///
/// If you want to decode a `.opus` file, use [`ffmpeg`]
///
/// [`ffmpeg`]: fn.ffmpeg.html
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => match v {
            Value::String(uri) => uri,
            other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream
            .as_object()
            .and_then(|m| m.get("channels").and_then(|v| v.as_i64()));

        channels == Some(2)
    });

    Ok(check)
}
<commit_msg>Fewer ffprobe calls when playing audio through ffmpeg. (#472)<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use internal::prelude::*;
use serde_json;
use std::{
    ffi::OsStr,
    fs::File,
    io::{
        BufReader,
        ErrorKind as IoErrorKind,
        Read,
        Result as IoResult
    },
    process::{
        Child,
        Command,
        Stdio
    },
    result::Result as StdResult
};
use super::{
    AudioSource,
    AudioType,
    DcaError,
    DcaMetadata,
    VoiceError
};

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

impl Drop for ChildContainer {
    fn drop (&mut self) {
        if let Err(e) = self.0.kill() {
            debug!("[Voice] Error awaiting child process: {:?}", e);
        }
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => if e.kind() == IoErrorKind::UnexpectedEof {
                Some(Vec::new())
            } else {
                None
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    _ffmpeg(path.as_ref())
}

fn _ffmpeg(path: &OsStr) -> Result<Box<AudioSource>> {
    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    _ffmpeg_optioned(path, &[
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ], Some(is_stereo))
}

/// Opens an audio file through `ffmpeg` and creates an audio source, with
/// user-specified arguments to pass to ffmpeg.
///
/// Note that this does _not_ build on the arguments passed by the [`ffmpeg`]
/// function.
///
/// # Examples
///
/// Pass options to create a custom ffmpeg streamer:
///
/// ```rust,no_run
/// use serenity::voice;
///
/// let stereo_val = "2";
///
/// let streamer = voice::ffmpeg_optioned("./some_file.mp3", &[
///     "-f",
///     "s16le",
///     "-ac",
///     stereo_val,
///     "-ar",
///     "48000",
///     "-acodec",
///     "pcm_s16le",
///     "-",
/// ]);
pub fn ffmpeg_optioned<P: AsRef<OsStr>>(
    path: P,
    args: &[&str],
) -> Result<Box<AudioSource>> {
    _ffmpeg_optioned(path.as_ref(), args, None)
}

fn _ffmpeg_optioned(path: &OsStr, args: &[&str], is_stereo_known: Option<bool>) -> Result<Box<AudioSource>> {
    let is_stereo = is_stereo_known
        .or_else(|| is_stereo(path).ok())
        .unwrap_or(false);

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    _dca(path.as_ref())
}

fn _dca(path: &OsStr) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source. This makes certain assumptions: namely, that the input stream
/// is composed ONLY of opus frames of the variety that Discord expects.
///
/// If you want to decode a `.opus` file, use [`ffmpeg`]
///
/// [`ffmpeg`]: fn.ffmpeg.html
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => match v {
            Value::String(uri) => uri,
            other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream
            .as_object()
            .and_then(|m| m.get("channels").and_then(|v| v.as_i64()));

        channels == Some(2)
    });

    Ok(check)
}
<|endoftext|>


<commit_before>
use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct Var(Rc<RefCell<i32>>);

impl Var {
   fn new() -> Var {
      Var(Rc::new(RefCell::new(0)))
   }

   pub fn set(&self, value: i32) {
      *self.0.borrow_mut() = value;
   }

   pub fn get(&self) -> i32 {
      *self.0.borrow()
   }
}

pub struct Function {

}

pub struct Cmd {
   vars: RefCell<HashMap<String, Var>>,
}

impl Cmd {
   pub fn new() -> Cmd {
      Cmd {
         vars: RefCell::new(HashMap::new()),
      }
   }

   pub fn register_var(&self, name: String) -> Result<(), String> {
      let mut vars = self.vars.borrow_mut();

      if vars.contains_key(&name) {
         return Err("Variable already pressent".to_string());
      }

      vars.insert(name, Var::new());
      Ok(())
   }

   pub fn register_func(&self, _name: String) -> Result<(), String> {
      Ok(())
   }

   pub fn exec(&self, _line: String) -> Result<(), String> {
      Ok(())
   }
}<commit_msg>Return the newly created variable.<commit_after>
use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct Var(Rc<RefCell<i32>>);

impl Var {
   fn new() -> Var {
      Var(Rc::new(RefCell::new(0)))
   }

   pub fn set(&self, value: i32) {
      *self.0.borrow_mut() = value;
   }

   pub fn get(&self) -> i32 {
      *self.0.borrow()
   }
}

pub struct Function {

}

pub struct Cmd {
   vars: RefCell<HashMap<String, Var>>,
}

impl Cmd {
   pub fn new() -> Cmd {
      Cmd {
         vars: RefCell::new(HashMap::new()),
      }
   }

   pub fn register_var(&self, name: String) -> Result<Var, String> {
      let mut vars = self.vars.borrow_mut();

      if vars.contains_key(&name) {
         return Err("Variable already pressent".to_string());
      }

      let var = Var::new();
      vars.insert(name, var.clone());
      Ok(var.clone())
   }

   pub fn register_func(&self, _name: String) -> Result<(), String> {
      Ok(())
   }

   pub fn exec(&self, _line: String) -> Result<(), String> {
      Ok(())
   }
}<|endoftext|>


<commit_before>use std::io::File;
use std::io::IoErrorKind::EndOfFile;
use std::cmp::max;
use self::Action::*;

macro_rules! get_memory {
    ($foo: ident, $addr: expr) => {
        match $foo.memory.memory_space.get($addr as uint) {
            Some(&x) => x,
            None => return None,
        }
    };
    ($foo: ident, $addr: expr, $rval: expr) => {
        match $foo.memory.memory_space.get($addr as uint) {
            Some(&x) => x,
            None => return $rval,
        }
    };
}

struct Memory {
    data_stack: Vec<i32>,
    address_stack: Vec<i32>,
    memory_space: Vec<i32>,
}

impl Memory {
    fn new(path: &Path) -> Memory {
        let mut file = File::open(path).unwrap();
        let size = file.stat().unwrap().size / 4;
        let mut memory = Vec::with_capacity(max(size as uint, 1024*1024)); // 4MB or image size

        loop {
            match file.read_le_i32() {
                Ok(x) => memory.push(x),
                Err(ref e) if e.kind == EndOfFile => break,
                Err(e) => panic!(e),
            }
        }
        Memory {
            data_stack: Vec::new(),
            address_stack: Vec::new(),
            memory_space: memory
        }
    }
}

pub struct Ports<'a> {
    ports: &'a mut [i32]
}

#[unsafe_destructor]
impl<'a> Drop for Ports<'a> {
    fn drop(&mut self) {
        self.ports.get_mut(0).map(|x| *x = 1);
    }
}

impl<'a> Deref<[i32]> for Ports<'a> {
    fn deref(&self) -> &[i32] {
        &*self.ports
    }
}

impl<'a> DerefMut<[i32]> for Ports<'a> {
    fn deref_mut(&mut self) -> &mut [i32] {
        self.ports
    }
}

pub struct Info {
    pub memory_size: i32,
    pub data_stack_depth: i32,
    pub address_stack_depth: i32,
}

pub struct CPU {
    memory: Memory,
    ip: i32,
    ports: [i32, ..12]
}

impl CPU {
    pub fn new(path: &Path) -> CPU {
        CPU {
            memory: Memory::new(path),
            ip: 0,
            ports: [0, ..12],
        }
    }

    pub fn ports_and_stack<'a>(&'a mut self) -> (Ports<'a>, &'a mut Vec<i32>) {
        let ports = Ports { ports: self.ports.as_mut_slice() };
        let stack = &mut self.memory.data_stack;
        (ports, stack)
    }

    pub fn get_info(&self) -> Info {
        Info {
            memory_size: self.memory.memory_space.len() as i32,
            data_stack_depth: self.memory.data_stack.len() as i32,
            address_stack_depth: self.memory.address_stack.len() as i32,
        }
    }

    pub fn pop_data(&mut self) -> i32 {
        self.memory.data_stack.pop().expect("Data stack underflow.")
    }

    pub fn push_data(&mut self, data: i32) {
        self.memory.data_stack.push(data)
    }

    fn pop_address(&mut self) -> i32 {
        self.memory.address_stack.pop().expect("Address stack underflow.")
    }

    fn push_address(&mut self, data: i32) {
        self.memory.address_stack.push(data)
    }

    fn jump(&mut self) {
        self.ip += 1;
        self.ip = get_memory!(self, self.ip, panic!("Jump out of bounds.")) - 1;
    }

    fn cond_stack_jump(&mut self, cond: |i32, i32| -> bool) {
        let (a, b) = (self.pop_data(), self.pop_data());
        if cond(a,b) { self.jump() } else { self.ip += 1; }
    }

    fn pop_2_push_1(&mut self, func: |i32, i32| -> i32) {
        let (a, b) = (self.pop_data(), self.pop_data());
        self.push_data(func(a,b));
    }
}

impl Iterator<Action> for CPU {
    fn next(&mut self) -> Option<Action> {
        let mut stderr = ::std::io::stdio::stderr();
        let mut stderr = &mut stderr;
        let mut result = Empty;
//        writeln!(stderr, "IP: {} Data: {} Address: {}", self.ip, self.memory.data_stack, self.memory.address_stack);
        let instruction = get_memory!(self, self.ip);
//        writeln!(stderr, "Instruction: {}", debug::opcode_to_name(instruction));
        match instruction {
            0 => { } // NOP
            1 => { // LIT X
                self.ip += 1;
                let data = get_memory!(self, self.ip);
                self.push_data(data);
            }
            2 => { // DUP
                let item = self.pop_data();
                self.push_data(item);
                self.push_data(item);
            }
            3 => { // DROP
                self.pop_data();
            }
            4 => { // SWAP
                let (a, b) = (self.pop_data(), self.pop_data());
                self.push_data(a);
                self.push_data(b);
            }
            5 => { // PUSH
                let data = self.pop_data();
                self.push_address(data);
            }
            6 => { // POP
                let data = self.pop_address();
                self.push_data(data);
            }
            7 => { // LOOP A
                let mut data = self.pop_data();
                self.ip += 1;
                data -= 1;
                if data > 0 {
                    self.jump();
                    self.push_data(data);
                }
            }
            8 => { // JUMP A
                self.jump();
            }
            9 => { // RETURN
                let addr = self.pop_address();
                self.ip = addr;
            }
            10 => { // GT_JUMP
                self.cond_stack_jump(|a, b| b > a);
            }
            11 => { // LT_JUMP
                self.cond_stack_jump(|a, b| b < a);
            }
            12 => { // NE_JUMP
                self.cond_stack_jump(|a, b| a != b);
            }
            13 => { // EQ_JUMP
                self.cond_stack_jump(|a, b| a == b);
            }
            14 => { // FETCH
                let addr = self.pop_data();
                let data = *self.memory.memory_space.get(addr as uint).expect("FETCH beyond bounds.");
                self.push_data(data);
            }
            15 => { // STORE
                let (addr, data) = (self.pop_data(), self.pop_data());
                *self.memory.memory_space.get_mut(addr as uint).expect("STORE beyond bounds.") = data;
            }
            16 => { // ADD
                self.pop_2_push_1(|a, b| a+b);
            }
            17 => { // SUBTRACT
                self.pop_2_push_1(|a, b| b-a);
            }
            18 => { // MULTIPLY
                self.pop_2_push_1(|a, b| a*b);
            }
            19 => { // DIVMOD
                let (a, b) = (self.pop_data(), self.pop_data());
                self.push_data(b % a);
                self.push_data(b / a);
            }
            20 => { // AND
                self.pop_2_push_1(|a, b| a&b);
            }
            21 => { // OR
                self.pop_2_push_1(|a, b| a|b);
            }
            22 => { // XOR
                self.pop_2_push_1(|a, b| a^b);
            }
            23 => { // SHL
                self.pop_2_push_1(|a, b| b<<(a as uint));
            }
            24 => { // SHR
                self.pop_2_push_1(|a, b| (b as u32>>(a as uint)) as i32);
            }
            25 => { // ZERO_EXIT
                let data = self.pop_data();
                if data == 0 {
                    self.ip = self.pop_address();
                } else {
                    self.push_data(data);
                }
            }
            26 => { // INC
                let data = self.pop_data();
                self.push_data(data+1);
            }
            27 => { // DEC
                let data = self.pop_data();
                self.push_data(data-1);
            }
            28 => { // IN
                let port = self.pop_data();
                let data = self.ports.get(port as uint).map_or(0, |&x| x);
                self.push_data(data);
                self.ports.get_mut(port as uint).map(|x| *x = 0);
            }
            29 => { // OUT
                let (port, data) = (self.pop_data(), self.pop_data());
                self.ports.get_mut(port as uint).map(|x| *x = data);
            }
            30 => { // WAIT
                if self.ports.get(0).map_or(false, |&x| x == 0) {
                    result = Wait;
                }
            }
            x => { // Implicit call
                let ip = self.ip;
                self.push_address(ip);
                self.ip = x - 1;
            }
        };
        self.ip += 1;
        return Some(result);
    }
}

pub enum Action {
    Empty,
    Wait,
}

#[allow(dead_code)]
mod debug {
    pub fn opcode_to_name(opcode: i32) -> &'static str {
        const NAMES: &'static [&'static str] = &[
            "NOP",
            "LIT",
            "DUP",
            "DROP",
            "SWAP",
            "PUSH",
            "POP",
            "LOOP",
            "JUMP",
            "RETURN",
            "LT_JUMP",
            "GT_JUMP",
            "NE_JUMP",
            "EQ_JUMP",
            "FETCH",
            "STORE",
            "ADD",
            "SUBTRACT",
            "MULTIPLY",
            "DIVMOD",
            "AND",
            "OR",
            "XOR",
            "SHL",
            "SHR",
            "ZERO_EXIT",
            "INC",
            "DEC",
            "IN",
            "OUT",
            "WAIT",
                ];
        NAMES.get(opcode as uint).map_or("CALL", |&x| x)
    }
}
<commit_msg>Fix the behaviour of the LOOP instruction, and make sure all the memory is accessible.<commit_after>use std::io::File;
use std::io::IoErrorKind::EndOfFile;
use std::cmp::max;
use self::Action::*;

macro_rules! get_memory {
    ($foo: ident, $addr: expr) => {
        match $foo.memory.memory_space.get($addr as uint) {
            Some(&x) => x,
            None => return None,
        }
    };
    ($foo: ident, $addr: expr, $rval: expr) => {
        match $foo.memory.memory_space.get($addr as uint) {
            Some(&x) => x,
            None => return $rval,
        }
    };
}

struct Memory {
    data_stack: Vec<i32>,
    address_stack: Vec<i32>,
    memory_space: Vec<i32>,
}

impl Memory {
    fn new(path: &Path) -> Memory {
        let mut file = File::open(path).unwrap();
        let size = file.stat().unwrap().size / 4;
        let mut memory = Vec::with_capacity(max(size as uint, 1024*1024)); // 4MB or image size

        loop {
            match file.read_le_i32() {
                Ok(x) => memory.push(x),
                Err(ref e) if e.kind == EndOfFile => break,
                Err(e) => panic!(e),
            }
        }

        while memory.capacity() > memory.len() {
            memory.push(0);
        }

        Memory {
            data_stack: Vec::new(),
            address_stack: Vec::new(),
            memory_space: memory
        }
    }
}

pub struct Ports<'a> {
    ports: &'a mut [i32]
}

#[unsafe_destructor]
impl<'a> Drop for Ports<'a> {
    fn drop(&mut self) {
        self.ports.get_mut(0).map(|x| *x = 1);
    }
}

impl<'a> Deref<[i32]> for Ports<'a> {
    fn deref(&self) -> &[i32] {
        &*self.ports
    }
}

impl<'a> DerefMut<[i32]> for Ports<'a> {
    fn deref_mut(&mut self) -> &mut [i32] {
        self.ports
    }
}

pub struct Info {
    pub memory_size: i32,
    pub data_stack_depth: i32,
    pub address_stack_depth: i32,
}

pub struct CPU {
    memory: Memory,
    ip: i32,
    ports: [i32, ..12]
}

impl CPU {
    pub fn new(path: &Path) -> CPU {
        CPU {
            memory: Memory::new(path),
            ip: 0,
            ports: [0, ..12],
        }
    }

    pub fn ports_and_stack<'a>(&'a mut self) -> (Ports<'a>, &'a mut Vec<i32>) {
        let ports = Ports { ports: self.ports.as_mut_slice() };
        let stack = &mut self.memory.data_stack;
        (ports, stack)
    }

    pub fn get_info(&self) -> Info {
        Info {
            memory_size: self.memory.memory_space.len() as i32,
            data_stack_depth: self.memory.data_stack.len() as i32,
            address_stack_depth: self.memory.address_stack.len() as i32,
        }
    }

    pub fn pop_data(&mut self) -> i32 {
        self.memory.data_stack.pop().expect("Data stack underflow.")
    }

    pub fn push_data(&mut self, data: i32) {
        self.memory.data_stack.push(data)
    }

    fn pop_address(&mut self) -> i32 {
        self.memory.address_stack.pop().expect("Address stack underflow.")
    }

    fn push_address(&mut self, data: i32) {
        self.memory.address_stack.push(data)
    }

    fn jump(&mut self) {
        self.ip += 1;
        self.ip = get_memory!(self, self.ip, panic!("Jump out of bounds.")) - 1;
    }

    fn cond_stack_jump(&mut self, cond: |i32, i32| -> bool) {
        let (a, b) = (self.pop_data(), self.pop_data());
        if cond(a,b) { self.jump() } else { self.ip += 1; }
    }

    fn pop_2_push_1(&mut self, func: |i32, i32| -> i32) {
        let (a, b) = (self.pop_data(), self.pop_data());
        self.push_data(func(a,b));
    }
}

impl Iterator<Action> for CPU {
    fn next(&mut self) -> Option<Action> {
        let mut stderr = ::std::io::stdio::stderr();
        let mut stderr = &mut stderr;
        let mut result = Empty;
//        writeln!(stderr, "IP: {} Data: {} Address: {}", self.ip, self.memory.data_stack, self.memory.address_stack);
        let instruction = get_memory!(self, self.ip);
//        writeln!(stderr, "Instruction: {}", debug::opcode_to_name(instruction));
        match instruction {
            0 => { } // NOP
            1 => { // LIT X
                self.ip += 1;
                let data = get_memory!(self, self.ip);
                self.push_data(data);
            }
            2 => { // DUP
                let item = self.pop_data();
                self.push_data(item);
                self.push_data(item);
            }
            3 => { // DROP
                self.pop_data();
            }
            4 => { // SWAP
                let (a, b) = (self.pop_data(), self.pop_data());
                self.push_data(a);
                self.push_data(b);
            }
            5 => { // PUSH
                let data = self.pop_data();
                self.push_address(data);
            }
            6 => { // POP
                let data = self.pop_address();
                self.push_data(data);
            }
            7 => { // LOOP A
                let mut data = self.pop_data();
                data -= 1;
                if data > 0 {
                    self.jump();
                    self.push_data(data);
                } else {
                    self.ip += 1;
                }
            }
            8 => { // JUMP A
                self.jump();
            }
            9 => { // RETURN
                let addr = self.pop_address();
                self.ip = addr;
            }
            10 => { // GT_JUMP
                self.cond_stack_jump(|a, b| b > a);
            }
            11 => { // LT_JUMP
                self.cond_stack_jump(|a, b| b < a);
            }
            12 => { // NE_JUMP
                self.cond_stack_jump(|a, b| a != b);
            }
            13 => { // EQ_JUMP
                self.cond_stack_jump(|a, b| a == b);
            }
            14 => { // FETCH
                let addr = self.pop_data();
                let data = *self.memory.memory_space.get(addr as uint).expect("FETCH beyond bounds.");
                self.push_data(data);
            }
            15 => { // STORE
                let (addr, data) = (self.pop_data(), self.pop_data());
                *self.memory.memory_space.get_mut(addr as uint).expect("STORE beyond bounds.") = data;
            }
            16 => { // ADD
                self.pop_2_push_1(|a, b| a+b);
            }
            17 => { // SUBTRACT
                self.pop_2_push_1(|a, b| b-a);
            }
            18 => { // MULTIPLY
                self.pop_2_push_1(|a, b| a*b);
            }
            19 => { // DIVMOD
                let (a, b) = (self.pop_data(), self.pop_data());
                self.push_data(b % a);
                self.push_data(b / a);
            }
            20 => { // AND
                self.pop_2_push_1(|a, b| a&b);
            }
            21 => { // OR
                self.pop_2_push_1(|a, b| a|b);
            }
            22 => { // XOR
                self.pop_2_push_1(|a, b| a^b);
            }
            23 => { // SHL
                self.pop_2_push_1(|a, b| b<<(a as uint));
            }
            24 => { // SHR
                self.pop_2_push_1(|a, b| (b as u32>>(a as uint)) as i32);
            }
            25 => { // ZERO_EXIT
                let data = self.pop_data();
                if data == 0 {
                    self.ip = self.pop_address();
                } else {
                    self.push_data(data);
                }
            }
            26 => { // INC
                let data = self.pop_data();
                self.push_data(data+1);
            }
            27 => { // DEC
                let data = self.pop_data();
                self.push_data(data-1);
            }
            28 => { // IN
                let port = self.pop_data();
                let data = self.ports.get(port as uint).map_or(0, |&x| x);
                self.push_data(data);
                self.ports.get_mut(port as uint).map(|x| *x = 0);
            }
            29 => { // OUT
                let (port, data) = (self.pop_data(), self.pop_data());
                self.ports.get_mut(port as uint).map(|x| *x = data);
            }
            30 => { // WAIT
                if self.ports.get(0).map_or(false, |&x| x == 0) {
                    result = Wait;
                }
            }
            x => { // Implicit call
                let ip = self.ip;
                self.push_address(ip);
                self.ip = x - 1;
            }
        };
        self.ip += 1;
        return Some(result);
    }
}

pub enum Action {
    Empty,
    Wait,
}

#[allow(dead_code)]
mod debug {
    pub fn opcode_to_name(opcode: i32) -> &'static str {
        const NAMES: &'static [&'static str] = &[
            "NOP",
            "LIT",
            "DUP",
            "DROP",
            "SWAP",
            "PUSH",
            "POP",
            "LOOP",
            "JUMP",
            "RETURN",
            "LT_JUMP",
            "GT_JUMP",
            "NE_JUMP",
            "EQ_JUMP",
            "FETCH",
            "STORE",
            "ADD",
            "SUBTRACT",
            "MULTIPLY",
            "DIVMOD",
            "AND",
            "OR",
            "XOR",
            "SHL",
            "SHR",
            "ZERO_EXIT",
            "INC",
            "DEC",
            "IN",
            "OUT",
            "WAIT",
                ];
        NAMES.get(opcode as uint).map_or("CALL", |&x| x)
    }
}
<|endoftext|>


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

/*!

Operations on the ubiquitous `Option` type.

Type `Option` represents an optional value.

Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.

Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.

# Example

~~~
let msg = Some(~"howdy");

// Take a reference to the contained string
match msg {
    Some(ref m) => io::println(m),
    None => ()
}

// Remove the contained string, destroying the Option
let unwrapped_msg = match msg {
    Some(m) => m,
    None => ~"default message"
};
~~~

*/

use cmp::{Eq,Ord};
use ops::Add;
use kinds::Copy;
use util;
use num::Zero;
use iterator::Iterator;
use str::StrSlice;
use clone::DeepClone;

#[cfg(test)] use str;
#[cfg(test)] use iterator::IteratorUtil;

/// The option type
#[deriving(Clone, DeepClone, Eq)]
pub enum Option<T> {
    None,
    Some(T),
}

impl<T:Ord> Ord for Option<T> {
    fn lt(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => false,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a < *b
        }
    }

    fn le(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => true,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a <= *b
        }
    }

    fn ge(&self, other: &Option<T>) -> bool {
        !(self < other)
    }

    fn gt(&self, other: &Option<T>) -> bool {
        !(self <= other)
    }
}

impl<T: Copy+Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
    #[inline]
    fn add(&self, other: &Option<T>) -> Option<T> {
        match (&*self, &*other) {
            (&None, &None) => None,
            (_, &None) => copy *self,
            (&None, _) => copy *other,
            (&Some(ref lhs), &Some(ref rhs)) => Some(*lhs + *rhs)
        }
    }
}

impl<T> Option<T> {
    /// Return an iterator over the possibly contained value
    #[inline]
    pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
        match *self {
            Some(ref x) => OptionIterator{opt: Some(x)},
            None => OptionIterator{opt: None}
        }
    }

    /// Return a mutable iterator over the possibly contained value
    #[inline]
    pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
        match *self {
            Some(ref mut x) => OptionMutIterator{opt: Some(x)},
            None => OptionMutIterator{opt: None}
        }
    }

    /// Returns true if the option equals `none`
    #[inline]
    pub fn is_none(&self) -> bool {
        match *self { None => true, Some(_) => false }
    }

    /// Returns true if the option contains some value
    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    /// Update an optional value by optionally running its content through a
    /// function that returns an option.
    #[inline]
    pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
        match self {
            Some(t) => f(t),
            None => None
        }
    }

    /// Returns the leftmost Some() value, or None if both are None.
    #[inline]
    pub fn or(self, optb: Option<T>) -> Option<T> {
        match self {
            Some(opta) => Some(opta),
            _ => optb
        }
    }

    /// Update an optional value by optionally running its content by reference
    /// through a function that returns an option.
    #[inline]
    pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>)
                            -> Option<U> {
        match *self {
            Some(ref x) => f(x),
            None => None
        }
    }

    /// Filters an optional value using given function.
    #[inline(always)]
    pub fn filtered(self, f: &fn(t: &T) -> bool) -> Option<T> {
        match self {
            Some(x) => if(f(&x)) {Some(x)} else {None},
            None => None
        }
    }

    /// Maps a `some` value from one type to another by reference
    #[inline]
    pub fn map<'a, U>(&'a self, f: &fn(&'a T) -> U) -> Option<U> {
        match *self { Some(ref x) => Some(f(x)), None => None }
    }

    /// Maps a `some` value from one type to another by a mutable reference
    #[inline]
    pub fn map_mut<'a, U>(&'a mut self, f: &fn(&'a mut T) -> U) -> Option<U> {
        match *self { Some(ref mut x) => Some(f(x)), None => None }
    }

    /// As `map`, but consumes the option and gives `f` ownership to avoid
    /// copying.
    #[inline]
    pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
        match self { None => None, Some(v) => Some(f(v)) }
    }

    /// Applies a function to the contained value or returns a default
    #[inline]
    pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
        match *self { None => def, Some(ref t) => f(t) }
    }

    /// As `map_default`, but consumes the option and gives `f`
    /// ownership to avoid copying.
    #[inline]
    pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
        match self { None => def, Some(v) => f(v) }
    }

    /// Apply a function to the contained value or do nothing
    pub fn mutate(&mut self, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        }
    }

    /// Apply a function to the contained value or set it to a default
    pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        } else {
            *self = Some(def);
        }
    }

    /**
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
          Some(ref x) => x,
          None => fail!("option::get_ref none")
        }
    }

    /**
    Gets a mutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        match *self {
          Some(ref mut x) => x,
          None => fail!("option::get_mut_ref none")
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        /*!
        Moves a value out of an option type and returns it.

        Useful primarily for getting strings, vectors and unique pointers out
        of option types without copying them.

        # Failure

        Fails if the value equals `None`.

        # Safety note

        In general, because this function may fail, its use is discouraged.
        Instead, prefer to use pattern matching and handle the `None`
        case explicitly.
         */
        match self {
          Some(x) => x,
          None => fail!("option::unwrap none")
        }
    }

    /**
     * The option dance. Moves a value out of an option type and returns it,
     * replacing the original with `None`.
     *
     * # Failure
     *
     * Fails if the value equals `None`.
     */
    #[inline]
    pub fn swap_unwrap(&mut self) -> T {
        if self.is_none() { fail!("option::swap_unwrap none") }
        util::replace(self, None).unwrap()
    }

    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    #[inline]
    pub fn expect(self, reason: &str) -> T {
        match self {
          Some(val) => val,
          None => fail!(reason.to_owned()),
        }
    }
}

impl<T:Copy> Option<T> {
    /**
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */
    #[inline]
    pub fn get(self) -> T {
        match self {
          Some(x) => return x,
          None => fail!("option::get none")
        }
    }

    /// Returns the contained value or a default
    #[inline]
    pub fn get_or_default(self, def: T) -> T {
        match self { Some(x) => x, None => def }
    }

    /// Applies a function zero or more times until the result is none.
    #[inline]
    pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
        let mut opt = self;
        while opt.is_some() {
            opt = blk(opt.unwrap());
        }
    }
}

impl<T:Copy + Zero> Option<T> {
    /// Returns the contained value or zero (for this type)
    #[inline]
    pub fn get_or_zero(self) -> T {
        match self {
            Some(x) => x,
            None => Zero::zero()
        }
    }
}

impl<T> Zero for Option<T> {
    fn zero() -> Option<T> { None }
    fn is_zero(&self) -> bool { self.is_none() }
}

/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
    priv opt: Option<&'self A>
}

impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
    fn next(&mut self) -> Option<&'self A> {
        util::replace(&mut self.opt, None)
    }
}

/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
    priv opt: Option<&'self mut A>
}

impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
    fn next(&mut self) -> Option<&'self mut A> {
        util::replace(&mut self.opt, None)
    }
}

#[test]
fn test_unwrap_ptr() {
    unsafe {
        let x = ~0;
        let addr_x: *int = ::cast::transmute(&*x);
        let opt = Some(x);
        let y = opt.unwrap();
        let addr_y: *int = ::cast::transmute(&*y);
        assert_eq!(addr_x, addr_y);
    }
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(x);
    let y = opt.unwrap();
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert_eq!(addr_x, addr_y);
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
    }

    #[unsafe_destructor]
    impl ::ops::Drop for R {
       fn drop(&self) { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = opt.unwrap();
    }
    assert_eq!(*i, 1);
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    for x.iter().advance |_x| {
        y2 = y.swap_unwrap();
    }
    assert_eq!(y2, 5);
    assert!(y.is_none());
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable);
    let _y2 = y.swap_unwrap();
    let _y3 = y.swap_unwrap();
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert_eq!(i, 11);
}

#[test]
fn test_get_or_zero() {
    let some_stuff = Some(42);
    assert_eq!(some_stuff.get_or_zero(), 42);
    let no_stuff: Option<int> = None;
    assert_eq!(no_stuff.get_or_zero(), 0);
}

#[test]
fn test_filtered() {
    let some_stuff = Some(42);
    let modified_stuff = some_stuff.filtered(|&x| {x < 10});
    assert_eq!(some_stuff.get(), 42);
    assert!(modified_stuff.is_none());
}
<commit_msg>std: Implement `Iterator::size_hint` method for `Option` iterators<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

Operations on the ubiquitous `Option` type.

Type `Option` represents an optional value.

Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.

Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.

# Example

~~~
let msg = Some(~"howdy");

// Take a reference to the contained string
match msg {
    Some(ref m) => io::println(m),
    None => ()
}

// Remove the contained string, destroying the Option
let unwrapped_msg = match msg {
    Some(m) => m,
    None => ~"default message"
};
~~~

*/

use cmp::{Eq,Ord};
use ops::Add;
use kinds::Copy;
use util;
use num::Zero;
use iterator::Iterator;
use str::StrSlice;
use clone::DeepClone;

#[cfg(test)] use str;
#[cfg(test)] use iterator::IteratorUtil;

/// The option type
#[deriving(Clone, DeepClone, Eq)]
pub enum Option<T> {
    None,
    Some(T),
}

impl<T:Ord> Ord for Option<T> {
    fn lt(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => false,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a < *b
        }
    }

    fn le(&self, other: &Option<T>) -> bool {
        match (self, other) {
            (&None, &None) => true,
            (&None, &Some(_)) => true,
            (&Some(_), &None) => false,
            (&Some(ref a), &Some(ref b)) => *a <= *b
        }
    }

    fn ge(&self, other: &Option<T>) -> bool {
        !(self < other)
    }

    fn gt(&self, other: &Option<T>) -> bool {
        !(self <= other)
    }
}

impl<T: Copy+Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
    #[inline]
    fn add(&self, other: &Option<T>) -> Option<T> {
        match (&*self, &*other) {
            (&None, &None) => None,
            (_, &None) => copy *self,
            (&None, _) => copy *other,
            (&Some(ref lhs), &Some(ref rhs)) => Some(*lhs + *rhs)
        }
    }
}

impl<T> Option<T> {
    /// Return an iterator over the possibly contained value
    #[inline]
    pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
        match *self {
            Some(ref x) => OptionIterator{opt: Some(x)},
            None => OptionIterator{opt: None}
        }
    }

    /// Return a mutable iterator over the possibly contained value
    #[inline]
    pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
        match *self {
            Some(ref mut x) => OptionMutIterator{opt: Some(x)},
            None => OptionMutIterator{opt: None}
        }
    }

    /// Returns true if the option equals `none`
    #[inline]
    pub fn is_none(&self) -> bool {
        match *self { None => true, Some(_) => false }
    }

    /// Returns true if the option contains some value
    #[inline]
    pub fn is_some(&self) -> bool { !self.is_none() }

    /// Update an optional value by optionally running its content through a
    /// function that returns an option.
    #[inline]
    pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
        match self {
            Some(t) => f(t),
            None => None
        }
    }

    /// Returns the leftmost Some() value, or None if both are None.
    #[inline]
    pub fn or(self, optb: Option<T>) -> Option<T> {
        match self {
            Some(opta) => Some(opta),
            _ => optb
        }
    }

    /// Update an optional value by optionally running its content by reference
    /// through a function that returns an option.
    #[inline]
    pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>)
                            -> Option<U> {
        match *self {
            Some(ref x) => f(x),
            None => None
        }
    }

    /// Filters an optional value using given function.
    #[inline(always)]
    pub fn filtered(self, f: &fn(t: &T) -> bool) -> Option<T> {
        match self {
            Some(x) => if(f(&x)) {Some(x)} else {None},
            None => None
        }
    }

    /// Maps a `some` value from one type to another by reference
    #[inline]
    pub fn map<'a, U>(&'a self, f: &fn(&'a T) -> U) -> Option<U> {
        match *self { Some(ref x) => Some(f(x)), None => None }
    }

    /// Maps a `some` value from one type to another by a mutable reference
    #[inline]
    pub fn map_mut<'a, U>(&'a mut self, f: &fn(&'a mut T) -> U) -> Option<U> {
        match *self { Some(ref mut x) => Some(f(x)), None => None }
    }

    /// As `map`, but consumes the option and gives `f` ownership to avoid
    /// copying.
    #[inline]
    pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
        match self { None => None, Some(v) => Some(f(v)) }
    }

    /// Applies a function to the contained value or returns a default
    #[inline]
    pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
        match *self { None => def, Some(ref t) => f(t) }
    }

    /// As `map_default`, but consumes the option and gives `f`
    /// ownership to avoid copying.
    #[inline]
    pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
        match self { None => def, Some(v) => f(v) }
    }

    /// Apply a function to the contained value or do nothing
    pub fn mutate(&mut self, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        }
    }

    /// Apply a function to the contained value or set it to a default
    pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) {
        if self.is_some() {
            *self = Some(f(self.swap_unwrap()));
        } else {
            *self = Some(def);
        }
    }

    /**
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        match *self {
          Some(ref x) => x,
          None => fail!("option::get_ref none")
        }
    }

    /**
    Gets a mutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        match *self {
          Some(ref mut x) => x,
          None => fail!("option::get_mut_ref none")
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        /*!
        Moves a value out of an option type and returns it.

        Useful primarily for getting strings, vectors and unique pointers out
        of option types without copying them.

        # Failure

        Fails if the value equals `None`.

        # Safety note

        In general, because this function may fail, its use is discouraged.
        Instead, prefer to use pattern matching and handle the `None`
        case explicitly.
         */
        match self {
          Some(x) => x,
          None => fail!("option::unwrap none")
        }
    }

    /**
     * The option dance. Moves a value out of an option type and returns it,
     * replacing the original with `None`.
     *
     * # Failure
     *
     * Fails if the value equals `None`.
     */
    #[inline]
    pub fn swap_unwrap(&mut self) -> T {
        if self.is_none() { fail!("option::swap_unwrap none") }
        util::replace(self, None).unwrap()
    }

    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    #[inline]
    pub fn expect(self, reason: &str) -> T {
        match self {
          Some(val) => val,
          None => fail!(reason.to_owned()),
        }
    }
}

impl<T:Copy> Option<T> {
    /**
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */
    #[inline]
    pub fn get(self) -> T {
        match self {
          Some(x) => return x,
          None => fail!("option::get none")
        }
    }

    /// Returns the contained value or a default
    #[inline]
    pub fn get_or_default(self, def: T) -> T {
        match self { Some(x) => x, None => def }
    }

    /// Applies a function zero or more times until the result is none.
    #[inline]
    pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
        let mut opt = self;
        while opt.is_some() {
            opt = blk(opt.unwrap());
        }
    }
}

impl<T:Copy + Zero> Option<T> {
    /// Returns the contained value or zero (for this type)
    #[inline]
    pub fn get_or_zero(self) -> T {
        match self {
            Some(x) => x,
            None => Zero::zero()
        }
    }
}

impl<T> Zero for Option<T> {
    fn zero() -> Option<T> { None }
    fn is_zero(&self) -> bool { self.is_none() }
}

/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
    priv opt: Option<&'self A>
}

impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
    fn next(&mut self) -> Option<&'self A> {
        util::replace(&mut self.opt, None)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        match self.opt {
            Some(_) => (1, Some(1)),
            None => (0, Some(0)),
        }
    }
}

/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
    priv opt: Option<&'self mut A>
}

impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
    fn next(&mut self) -> Option<&'self mut A> {
        util::replace(&mut self.opt, None)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        match self.opt {
            Some(_) => (1, Some(1)),
            None => (0, Some(0)),
        }
    }
}

#[test]
fn test_unwrap_ptr() {
    unsafe {
        let x = ~0;
        let addr_x: *int = ::cast::transmute(&*x);
        let opt = Some(x);
        let y = opt.unwrap();
        let addr_y: *int = ::cast::transmute(&*y);
        assert_eq!(addr_x, addr_y);
    }
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(x);
    let y = opt.unwrap();
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert_eq!(addr_x, addr_y);
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
    }

    #[unsafe_destructor]
    impl ::ops::Drop for R {
       fn drop(&self) { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = opt.unwrap();
    }
    assert_eq!(*i, 1);
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    for x.iter().advance |_x| {
        y2 = y.swap_unwrap();
    }
    assert_eq!(y2, 5);
    assert!(y.is_none());
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable);
    let _y2 = y.swap_unwrap();
    let _y3 = y.swap_unwrap();
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert_eq!(i, 11);
}

#[test]
fn test_get_or_zero() {
    let some_stuff = Some(42);
    assert_eq!(some_stuff.get_or_zero(), 42);
    let no_stuff: Option<int> = None;
    assert_eq!(no_stuff.get_or_zero(), 0);
}

#[test]
fn test_filtered() {
    let some_stuff = Some(42);
    let modified_stuff = some_stuff.filtered(|&x| {x < 10});
    assert_eq!(some_stuff.get(), 42);
    assert!(modified_stuff.is_none());
}

#[test]
fn test_iter() {
    let val = 5;

    let x = Some(val);
    let mut it = x.iter();

    assert_eq!(it.size_hint(), (1, Some(1)));
    assert_eq!(it.next(), Some(&val));
    assert_eq!(it.size_hint(), (0, Some(0)));
    assert!(it.next().is_none());
}

#[test]
fn test_mut_iter() {
    let val = 5;
    let new_val = 11;

    let mut x = Some(val);
    let mut it = x.mut_iter();

    assert_eq!(it.size_hint(), (1, Some(1)));

    match it.next() {
        Some(interior) => {
            assert_eq!(*interior, val);
            *interior = new_val;
            assert_eq!(x, Some(new_val));
        }
        None => assert!(false),
    }

    assert_eq!(it.size_hint(), (0, Some(0)));
    assert!(it.next().is_none());
}
<|endoftext|>