<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use gleam::gl;
use image::RgbImage;
use servo_geometry::DeviceUintLength;

#[derive(Default)]
pub struct RenderTargetInfo {
    framebuffer_ids: Vec<gl::GLuint>,
    renderbuffer_ids: Vec<gl::GLuint>,
    texture_ids: Vec<gl::GLuint>,
}

pub fn initialize_png(
    gl: &dyn gl::Gl,
    width: DeviceUintLength,
    height: DeviceUintLength,
) -> RenderTargetInfo {
    let framebuffer_ids = gl.gen_framebuffers(1);
    gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);

    let texture_ids = gl.gen_textures(1);
    gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]);

    gl.tex_image_2d(
        gl::TEXTURE_2D,
        0,
        gl::RGB as gl::GLint,
        width.get() as gl::GLsizei,
        height.get() as gl::GLsizei,
        0,
        gl::RGB,
        gl::UNSIGNED_BYTE,
        None,
    );
    gl.tex_parameter_i(
        gl::TEXTURE_2D,
        gl::TEXTURE_MAG_FILTER,
        gl::NEAREST as gl::GLint,
    );
    gl.tex_parameter_i(
        gl::TEXTURE_2D,
        gl::TEXTURE_MIN_FILTER,
        gl::NEAREST as gl::GLint,
    );

    gl.framebuffer_texture_2d(
        gl::FRAMEBUFFER,
        gl::COLOR_ATTACHMENT0,
        gl::TEXTURE_2D,
        texture_ids[0],
        0,
    );

    gl.bind_texture(gl::TEXTURE_2D, 0);

    let renderbuffer_ids = gl.gen_renderbuffers(1);
    let depth_rb = renderbuffer_ids[0];
    gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
    gl.renderbuffer_storage(
        gl::RENDERBUFFER,
        gl::DEPTH_COMPONENT24,
        width.get() as gl::GLsizei,
        height.get() as gl::GLsizei,
    );
    gl.framebuffer_renderbuffer(
        gl::FRAMEBUFFER,
        gl::DEPTH_ATTACHMENT,
        gl::RENDERBUFFER,
        depth_rb,
    );

    RenderTargetInfo {
        framebuffer_ids,
        renderbuffer_ids,
        texture_ids,
    }
}

pub fn draw_img(
    gl: &dyn gl::Gl,
    render_target_info: RenderTargetInfo,
    width: DeviceUintLength,
    height: DeviceUintLength,
) -> RgbImage {
    let width = width.get() as usize;
    let height = height.get() as usize;
    // For some reason, OSMesa fails to render on the 3rd
    // attempt in headless mode, under some conditions.
    // I think this can only be some kind of synchronization
    // bug in OSMesa, but explicitly un-binding any vertex
    // array here seems to work around that bug.
    // See https://github.com/servo/servo/issues/18606.
    gl.bind_vertex_array(0);

    let mut pixels = gl.read_pixels(
        0,
        0,
        width as gl::GLsizei,
        height as gl::GLsizei,
        gl::RGB,
        gl::UNSIGNED_BYTE,
    );

    gl.bind_framebuffer(gl::FRAMEBUFFER, 0);

    gl.delete_buffers(&render_target_info.texture_ids);
    gl.delete_renderbuffers(&render_target_info.renderbuffer_ids);
    gl.delete_framebuffers(&render_target_info.framebuffer_ids);

    // flip image vertically (texture is upside down)
    let orig_pixels = pixels.clone();
    let stride = width * 3;
    for y in 0..height {
        let dst_start = y * stride;
        let src_start = (height - y - 1) * stride;
        let src_slice = &orig_pixels[src_start..src_start + stride];
        (&mut pixels[dst_start..dst_start + stride]).clone_from_slice(&src_slice[..stride]);
    }

    RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!")
}
<commit_msg>Delete texture when taking a screenshot, not a buffer.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use gleam::gl;
use image::RgbImage;
use servo_geometry::DeviceUintLength;

#[derive(Default)]
pub struct RenderTargetInfo {
    framebuffer_ids: Vec<gl::GLuint>,
    renderbuffer_ids: Vec<gl::GLuint>,
    texture_ids: Vec<gl::GLuint>,
}

pub fn initialize_png(
    gl: &dyn gl::Gl,
    width: DeviceUintLength,
    height: DeviceUintLength,
) -> RenderTargetInfo {
    let framebuffer_ids = gl.gen_framebuffers(1);
    gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);

    let texture_ids = gl.gen_textures(1);
    gl.bind_texture(gl::TEXTURE_2D, texture_ids[0]);

    gl.tex_image_2d(
        gl::TEXTURE_2D,
        0,
        gl::RGB as gl::GLint,
        width.get() as gl::GLsizei,
        height.get() as gl::GLsizei,
        0,
        gl::RGB,
        gl::UNSIGNED_BYTE,
        None,
    );
    gl.tex_parameter_i(
        gl::TEXTURE_2D,
        gl::TEXTURE_MAG_FILTER,
        gl::NEAREST as gl::GLint,
    );
    gl.tex_parameter_i(
        gl::TEXTURE_2D,
        gl::TEXTURE_MIN_FILTER,
        gl::NEAREST as gl::GLint,
    );

    gl.framebuffer_texture_2d(
        gl::FRAMEBUFFER,
        gl::COLOR_ATTACHMENT0,
        gl::TEXTURE_2D,
        texture_ids[0],
        0,
    );

    gl.bind_texture(gl::TEXTURE_2D, 0);

    let renderbuffer_ids = gl.gen_renderbuffers(1);
    let depth_rb = renderbuffer_ids[0];
    gl.bind_renderbuffer(gl::RENDERBUFFER, depth_rb);
    gl.renderbuffer_storage(
        gl::RENDERBUFFER,
        gl::DEPTH_COMPONENT24,
        width.get() as gl::GLsizei,
        height.get() as gl::GLsizei,
    );
    gl.framebuffer_renderbuffer(
        gl::FRAMEBUFFER,
        gl::DEPTH_ATTACHMENT,
        gl::RENDERBUFFER,
        depth_rb,
    );

    RenderTargetInfo {
        framebuffer_ids,
        renderbuffer_ids,
        texture_ids,
    }
}

pub fn draw_img(
    gl: &dyn gl::Gl,
    render_target_info: RenderTargetInfo,
    width: DeviceUintLength,
    height: DeviceUintLength,
) -> RgbImage {
    let width = width.get() as usize;
    let height = height.get() as usize;
    // For some reason, OSMesa fails to render on the 3rd
    // attempt in headless mode, under some conditions.
    // I think this can only be some kind of synchronization
    // bug in OSMesa, but explicitly un-binding any vertex
    // array here seems to work around that bug.
    // See https://github.com/servo/servo/issues/18606.
    gl.bind_vertex_array(0);

    let mut pixels = gl.read_pixels(
        0,
        0,
        width as gl::GLsizei,
        height as gl::GLsizei,
        gl::RGB,
        gl::UNSIGNED_BYTE,
    );

    gl.bind_framebuffer(gl::FRAMEBUFFER, 0);

    gl.delete_textures(&render_target_info.texture_ids);
    gl.delete_renderbuffers(&render_target_info.renderbuffer_ids);
    gl.delete_framebuffers(&render_target_info.framebuffer_ids);

    // flip image vertically (texture is upside down)
    let orig_pixels = pixels.clone();
    let stride = width * 3;
    for y in 0..height {
        let dst_start = y * stride;
        let src_start = (height - y - 1) * stride;
        let src_slice = &orig_pixels[src_start..src_start + stride];
        (&mut pixels[dst_start..dst_start + stride]).clone_from_slice(&src_slice[..stride]);
    }

    RgbImage::from_raw(width as u32, height as u32, pixels).expect("Flipping image failed!")
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate lapin_futures as lapin;
extern crate futures;
extern crate tokio_core;
extern crate env_logger;

use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;

use lapin::types::FieldTable;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,BasicPublishOptions,BasicQosOption,BasicProperties,QueueDeclareOptions,QueueDeleteOptions,QueuePurgeOptions};

#[test]
fn connection() {
  env_logger::init().unwrap();
  let mut core = Core::new().unwrap();

  let handle = core.handle();
  let addr = "127.0.0.1:5672".parse().unwrap();

  core.run(
    TcpStream::connect(&addr, &handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &ConnectionOptions::default())
    }).and_then(|(client, _)| {

      client.create_channel().and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        channel.queue_declare("hello", &QueueDeclareOptions::default(), &FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          channel.queue_purge("hello", &QueuePurgeOptions::default()).and_then(move |_| {
            channel.basic_publish("", "hello", b"hello from tokio", &BasicPublishOptions::default(), BasicProperties::default())
          })
        })
      }).and_then(move |_| {
        client.create_channel()
      }).and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        let ch1 = channel.clone();
        let ch2 = channel.clone();
        channel.basic_qos(&BasicQosOption { prefetch_count: 16, ..Default::default() }).and_then(move |_| {
          info!("channel QoS specified");
          channel.queue_declare("hello", &QueueDeclareOptions::default(), &FieldTable::new()).map(move |()| channel)
        }).and_then(move |channel| {
          info!("channel {} declared queue {}", id, "hello");

          channel.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default(), &FieldTable::new())
        }).and_then(move |stream| {
          info!("got consumer stream");

          stream.into_future().map_err(|(err, _)| err).and_then(move |(message, _)| {
            let msg = message.unwrap();
            info!("got message: {:?}", msg);
            assert_eq!(msg.data, b"hello from tokio");
            ch1.basic_ack(msg.delivery_tag)
          }).and_then(move |_| {
            ch2.queue_delete("hello", &QueueDeleteOptions::default())
          })
        })
      })
    })
  ).unwrap();
}
<commit_msg>fix tests<commit_after>#[macro_use] extern crate log;
extern crate lapin_futures as lapin;
extern crate futures;
extern crate tokio_core;
extern crate env_logger;

use futures::Stream;
use futures::future::Future;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;

use lapin::types::FieldTable;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,BasicPublishOptions,BasicQosOptions,BasicProperties,QueueDeclareOptions,QueueDeleteOptions,QueuePurgeOptions};

#[test]
fn connection() {
  env_logger::init().unwrap();
  let mut core = Core::new().unwrap();

  let handle = core.handle();
  let addr = "127.0.0.1:5672".parse().unwrap();

  core.run(
    TcpStream::connect(&addr, &handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &ConnectionOptions::default())
    }).and_then(|(client, _)| {

      client.create_channel().and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        channel.queue_declare("hello", &QueueDeclareOptions::default(), &FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          channel.queue_purge("hello", &QueuePurgeOptions::default()).and_then(move |_| {
            channel.basic_publish("", "hello", b"hello from tokio", &BasicPublishOptions::default(), BasicProperties::default())
          })
        })
      }).and_then(move |_| {
        client.create_channel()
      }).and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        let ch1 = channel.clone();
        let ch2 = channel.clone();
        channel.basic_qos(&BasicQosOptions { prefetch_count: 16, ..Default::default() }).and_then(move |_| {
          info!("channel QoS specified");
          channel.queue_declare("hello", &QueueDeclareOptions::default(), &FieldTable::new()).map(move |()| channel)
        }).and_then(move |channel| {
          info!("channel {} declared queue {}", id, "hello");

          channel.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default(), &FieldTable::new())
        }).and_then(move |stream| {
          info!("got consumer stream");

          stream.into_future().map_err(|(err, _)| err).and_then(move |(message, _)| {
            let msg = message.unwrap();
            info!("got message: {:?}", msg);
            assert_eq!(msg.data, b"hello from tokio");
            ch1.basic_ack(msg.delivery_tag)
          }).and_then(move |_| {
            ch2.queue_delete("hello", &QueueDeleteOptions::default())
          })
        })
      })
    })
  ).unwrap();
}
<|endoftext|>


<commit_before>/// The macro that surrounds definitions of Lucet hostcalls in Rust.
///
/// **Note:** this macro has been deprecated and replaced by the `#[lucet_hostcall]` attribute.
///
/// It is important to use this macro for hostcalls, rather than exporting them directly, as it
/// installs unwind protection that prevents panics from unwinding into the guest stack.
///
/// Since this is not yet a proc macro, the syntax is unfortunately fairly brittle. The functions it
/// encloses must be of the form:
///
/// ```ignore
/// #[$attr1]
/// #[$attr2]
/// ... // any number of attributes are supported; in most cases you will want `#[no_mangle]`
/// pub unsafe extern "C" fn $name( // must be `pub unsafe extern "C"`
///     &mut $vmctx,
///     $arg1: $arg1_ty,
///     $arg2: $arg2_ty,
///     ... , // trailing comma must always be present
/// ) -> $ret_ty { // return type must always be present even if it is `()`
///     // body
/// }
/// ```
#[macro_export]
#[deprecated(since = "0.4.2", note = "Use the #[lucet_hostcall] attribute instead")]
macro_rules! lucet_hostcalls {
    {
        $(
            $(#[$attr:meta])*
            pub unsafe extern "C" fn $name:ident(
                &mut $vmctx:ident
                $(, $arg:ident : $arg_ty:ty )*,
            ) -> $ret_ty:ty {
                $($body:tt)*
            }
        )*
    } => {
        $(
            #[allow(unused_mut)]
            #[allow(unused_unsafe)]
            #[$crate::lucet_hostcall]
            $(#[$attr])*
            pub unsafe extern "C" fn $name(
                $vmctx: &mut $crate::vmctx::Vmctx,
                $( $arg: $arg_ty ),*
            ) -> $ret_ty {
                $($body)*
            }
        )*
    }
}

/// Terminate an instance from within a hostcall, returning an optional value as an error.
///
/// Use this instead of `panic!` when you want the instance to terminate, but not the entire host
/// program. Like `panic!`, you can pass a format string with arguments, a value that implements
/// `Any`, or nothing to return a default message.
///
/// Upon termination, the call to `Instance::run()` will return with an
/// `Err(Error::RuntimeTerminated)` value containing the value you pass to this macro.
///
/// This macro safely unwinds the hostcall stack out to the entrypoint of the hostcall, so any
/// resources that may have been acquired will be properly dropped.
#[macro_export]
macro_rules! lucet_hostcall_terminate {
    () => {
        lucet_hostcall_terminate!("lucet_hostcall_terminate")
    };
    ( $payload:expr ) => {
        panic!($crate::instance::TerminationDetails::provide($payload))
    };
    ( $payload:expr, ) => {
        lucet_hostcall_terminate!($payload)
    };
    ( $fmt:expr, $($arg:tt)+ ) => {
        lucet_hostcall_terminate!(format!($fmt, $($arg),+))
    };
}
<commit_msg>use `lucet_runtime` rather than `$crate` in `lucet_hostcalls!`<commit_after>/// The macro that surrounds definitions of Lucet hostcalls in Rust.
///
/// **Note:** this macro has been deprecated and replaced by the `#[lucet_hostcall]` attribute.
///
/// It is important to use this macro for hostcalls, rather than exporting them directly, as it
/// installs unwind protection that prevents panics from unwinding into the guest stack.
///
/// Since this is not a proc macro, the syntax is unfortunately fairly brittle. The functions it
/// encloses must be of the form:
///
/// ```ignore
/// #[$attr1]
/// #[$attr2]
/// ... // any number of attributes are supported; in most cases you will want `#[no_mangle]`
/// pub unsafe extern "C" fn $name( // must be `pub unsafe extern "C"`
///     &mut $vmctx,
///     $arg1: $arg1_ty,
///     $arg2: $arg2_ty,
///     ... , // trailing comma must always be present
/// ) -> $ret_ty { // return type must always be present even if it is `()`
///     // body
/// }
/// ```
#[macro_export]
#[deprecated(since = "0.4.2", note = "Use the #[lucet_hostcall] attribute instead")]
macro_rules! lucet_hostcalls {
    {
        $(
            $(#[$attr:meta])*
            pub unsafe extern "C" fn $name:ident(
                &mut $vmctx:ident
                $(, $arg:ident : $arg_ty:ty )*,
            ) -> $ret_ty:ty {
                $($body:tt)*
            }
        )*
    } => {
        $(
            #[allow(unused_mut)]
            #[allow(unused_unsafe)]
            #[$crate::lucet_hostcall]
            $(#[$attr])*
            pub unsafe extern "C" fn $name(
                $vmctx: &mut lucet_runtime::vmctx::Vmctx,
                $( $arg: $arg_ty ),*
            ) -> $ret_ty {
                $($body)*
            }
        )*
    }
}

/// Terminate an instance from within a hostcall, returning an optional value as an error.
///
/// Use this instead of `panic!` when you want the instance to terminate, but not the entire host
/// program. Like `panic!`, you can pass a format string with arguments, a value that implements
/// `Any`, or nothing to return a default message.
///
/// Upon termination, the call to `Instance::run()` will return with an
/// `Err(Error::RuntimeTerminated)` value containing the value you pass to this macro.
///
/// This macro safely unwinds the hostcall stack out to the entrypoint of the hostcall, so any
/// resources that may have been acquired will be properly dropped.
#[macro_export]
macro_rules! lucet_hostcall_terminate {
    () => {
        lucet_hostcall_terminate!("lucet_hostcall_terminate")
    };
    ( $payload:expr ) => {
        panic!($crate::instance::TerminationDetails::provide($payload))
    };
    ( $payload:expr, ) => {
        lucet_hostcall_terminate!($payload)
    };
    ( $fmt:expr, $($arg:tt)+ ) => {
        lucet_hostcall_terminate!(format!($fmt, $($arg),+))
    };
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<commit_msg>Added IResult:: map_inc (map incomplete)<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
  /// to a contained `Incomplete` value, leaving `Done` and `Error` value
  /// untouched.
  #[inline]
  pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
   where F: FnOnce(Needed) -> Needed {
    match self {
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(f(n)),
      Done(i, o)    => Done(i, o),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_inc() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
    let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));

    assert_eq!(done.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
    assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

//! Extension trait for factorization math on iterators.

use num;
use num::{One, FromPrimitive};
use num::{Num, Integer};
use crate::util::mod_pow;

/// Prime-factorization-based functions implemented on arbitrary
///  iterables of `(prime, power)` pairs.
///
/// There are certain preconditions for using these methods:
///
///   * In each pair, `prime` must actually be a prime;
///     It is forbidden to be zero, one, negative, or composite.
///   * `power` must not be zero.
///   * The primes must be sorted, with each appearing only once.
///
/// A diagnostic for violations of these conditions (with the exception
///  of non-compositeness) may be provided in debug builds.
pub trait FactorExt<X: Ord>: IntoIterator<Item = (X, usize)> {
    /// Recover an integer from its prime decomposition.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().factor_product(), 20);
    /// ```
    fn factor_product(self) -> X
    where
        X: Clone + One,
        Self: Sized,
    {
        self.into_iter().fold(X::one(), |acc, (k, v)| acc * num::pow(k.clone(), v.clone()))
    }

    /// Compute the total number of positive integers which evenly divide
    ///  a number from its prime decomposition.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().divisor_count(), 6);
    /// ```
    fn divisor_count(self) -> X
    where
        X: Clone + FromPrimitive + One,
        Self: Sized,
    {
        // product( n[i]+1 );  we're counting the possible ways to select a power
        //                      from 0 to n[i] (inclusive) for each prime p[i]
        self.into_iter().fold(X::one(), |acc, (_, v)| {
            acc * FromPrimitive::from_usize(v.clone() + 1).unwrap()
        })
    }

    /// Compute the sum of all positive integers which evenly divide the number
    ///  represented by the `Factorization` (including 1 and the number itself).
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().divisor_sum(), 42);
    /// ```
    fn divisor_sum(self) -> X
    where
        X: Clone + One + Num,
        Self: Sized,
    {
        // A geometric series for each factor
        self.into_iter().fold(X::one(), |mut acc, (k, v)| {
            let numer = (num::pow(k.clone(), v.clone() + 1) - One::one());
            let denom = (k.clone() - One::one());
            acc * numer / denom
        })
    }

    /// Compute the Euler totient `phi(x)`, the total number of
    ///  positive integers less than `x` that are coprime to `x`.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().totient(), 8);
    /// ```
    fn totient(self) -> X
    where
        X: Clone + One + Num,
        Self: Sized,
    {
        // product( (p[i] - 1) * pow(p[i], n[i]-1) )
        self.into_iter().fold(X::one(), |acc, (k, v)| {
            acc * num::pow(k.clone(), v.clone() - 1) * (k.clone() - One::one())
        })
    }

    // FIXME: sigma_k for other k?

    // FIXME for now I see no issue with just returning a ::std::vec::IntoIter.  Do that.
    // TODO: pending unboxed abstract types
    // fn iter_divisors(&self) -> Iterator<K>

    /// Compute the value mod `m`.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f: factor::Factored<_> = (1..=20u64).map(factor::factorize).product();
    /// assert_eq!(f.into_iter().factor_product_mod(&1297), 278);
    /// ```
    fn factor_product_mod(self, modulus: &X) -> X
    where
        X: Clone + One + Integer,
        Self: Sized,
    {
        self.into_iter().fold(X::one(), |mut acc, (k, v)| {
            acc = acc * mod_pow(k.clone(), v.clone(), modulus.clone());
            acc = acc % modulus.clone();
            acc
        })
    }
}

impl<I, X: Ord> FactorExt<X> for I where I: IntoIterator<Item = (X, usize)> {}
<commit_msg>fix unused_mut warning<commit_after>// Copyright 2015-2016 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

//! Extension trait for factorization math on iterators.

use num;
use num::{One, FromPrimitive};
use num::{Num, Integer};
use crate::util::mod_pow;

/// Prime-factorization-based functions implemented on arbitrary
///  iterables of `(prime, power)` pairs.
///
/// There are certain preconditions for using these methods:
///
///   * In each pair, `prime` must actually be a prime;
///     It is forbidden to be zero, one, negative, or composite.
///   * `power` must not be zero.
///   * The primes must be sorted, with each appearing only once.
///
/// A diagnostic for violations of these conditions (with the exception
///  of non-compositeness) may be provided in debug builds.
pub trait FactorExt<X: Ord>: IntoIterator<Item = (X, usize)> {
    /// Recover an integer from its prime decomposition.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().factor_product(), 20);
    /// ```
    fn factor_product(self) -> X
    where
        X: Clone + One,
        Self: Sized,
    {
        self.into_iter().fold(X::one(), |acc, (k, v)| acc * num::pow(k.clone(), v.clone()))
    }

    /// Compute the total number of positive integers which evenly divide
    ///  a number from its prime decomposition.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().divisor_count(), 6);
    /// ```
    fn divisor_count(self) -> X
    where
        X: Clone + FromPrimitive + One,
        Self: Sized,
    {
        // product( n[i]+1 );  we're counting the possible ways to select a power
        //                      from 0 to n[i] (inclusive) for each prime p[i]
        self.into_iter().fold(X::one(), |acc, (_, v)| {
            acc * FromPrimitive::from_usize(v.clone() + 1).unwrap()
        })
    }

    /// Compute the sum of all positive integers which evenly divide the number
    ///  represented by the `Factorization` (including 1 and the number itself).
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().divisor_sum(), 42);
    /// ```
    fn divisor_sum(self) -> X
    where
        X: Clone + One + Num,
        Self: Sized,
    {
        // A geometric series for each factor
        self.into_iter().fold(X::one(), |acc, (k, v)| {
            let numer = (num::pow(k.clone(), v.clone() + 1) - One::one());
            let denom = (k.clone() - One::one());
            acc * numer / denom
        })
    }

    /// Compute the Euler totient `phi(x)`, the total number of
    ///  positive integers less than `x` that are coprime to `x`.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f = factor::factorize(20u64);
    /// assert_eq!(f.into_iter().totient(), 8);
    /// ```
    fn totient(self) -> X
    where
        X: Clone + One + Num,
        Self: Sized,
    {
        // product( (p[i] - 1) * pow(p[i], n[i]-1) )
        self.into_iter().fold(X::one(), |acc, (k, v)| {
            acc * num::pow(k.clone(), v.clone() - 1) * (k.clone() - One::one())
        })
    }

    // FIXME: sigma_k for other k?

    // FIXME for now I see no issue with just returning a ::std::vec::IntoIter.  Do that.
    // TODO: pending unboxed abstract types
    // fn iter_divisors(&self) -> Iterator<K>

    /// Compute the value mod `m`.
    ///
    /// # Example:
    ///
    /// ```
    /// use factor::prelude::*;
    ///
    /// let f: factor::Factored<_> = (1..=20u64).map(factor::factorize).product();
    /// assert_eq!(f.into_iter().factor_product_mod(&1297), 278);
    /// ```
    fn factor_product_mod(self, modulus: &X) -> X
    where
        X: Clone + One + Integer,
        Self: Sized,
    {
        self.into_iter().fold(X::one(), |acc, (k, v)| {
            acc * mod_pow(k.clone(), v.clone(), modulus.clone()) % modulus.clone()
        })
    }
}

impl<I, X: Ord> FactorExt<X> for I where I: IntoIterator<Item = (X, usize)> {}
<|endoftext|>


<commit_before>use std::fmt::{self};

pub struct Clock {
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        Clock {
            minutes: (hours * 60) + minutes,
        }
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        Clock::new(0, self.minutes + minutes)
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut minutes = self.minutes;
        let mut hours = 0;

        while minutes < 0 {
            hours -= 1;
            minutes += 60
        }
        while minutes >= 60 {
            hours += 1;
            minutes -= 60
        }
        while hours < 0 {
            hours += 24;
        }
        while hours >= 24 {
            hours -= 24;
        }

        write!(f, "{:02}:{:02}", hours, minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.minutes)
    }
}

impl PartialEq for Clock {
    fn eq(&self, other: &Self) -> bool {
        return format!("{}", self) == format!("{}", other);
    }
}
<commit_msg>Remove redundant return<commit_after>use std::fmt::{self};

pub struct Clock {
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        Clock {
            minutes: (hours * 60) + minutes,
        }
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        Clock::new(0, self.minutes + minutes)
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut minutes = self.minutes;
        let mut hours = 0;

        while minutes < 0 {
            hours -= 1;
            minutes += 60
        }
        while minutes >= 60 {
            hours += 1;
            minutes -= 60
        }
        while hours < 0 {
            hours += 24;
        }
        while hours >= 24 {
            hours -= 24;
        }

        write!(f, "{:02}:{:02}", hours, minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.minutes)
    }
}

impl PartialEq for Clock {
    fn eq(&self, other: &Self) -> bool {
        format!("{}", self) == format!("{}", other)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate proto_derive;
#[macro_use]
extern crate log;

extern crate env_logger;
extern crate itertools;
extern crate proto;

use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::io::{
    Cursor,
    Read,
    Result,
    Write,
    self,
};
use std::mem;

use itertools::Itertools;
use proto::Message;

mod descriptor;
mod plugin;

fn main() {
    env_logger::init().unwrap();
    let mut bytes = Vec::new();
    io::stdin().read_to_end(&mut bytes).unwrap();

    assert_ne!(bytes.len(), 0);

    let mut request = plugin::CodeGeneratorRequest::default();
    Message::merge_from(&mut request, bytes.len(), &mut Cursor::new(&mut bytes)).unwrap();

    let mut response = plugin::CodeGeneratorResponse::default();

    trace!("{:#?}", request);

    for file in request.proto_file {
        let mut resp = plugin::code_generator_response::File::default();

        match file.name.rfind('.') {
            Some(idx) => resp.name.push_str(&file.name[..idx]),
            None => resp.name.push_str(&file.name),
        }
        resp.name.push_str(".rs");

        resp.content = CodeGenerator::generate(file);
        response.file.push(resp);
    }

    let out = io::stdout();
    response.write_to(&mut out.lock()).unwrap();
}

struct CodeGenerator {
    source_info: descriptor::SourceCodeInfo,
    depth: u8,
    path: Vec<i32>,
    buf: String,
}

impl CodeGenerator {
    fn generate(file: descriptor::FileDescriptorProto) -> String {

        let mut source_info = file.source_code_info.expect("no source code info in request");
        source_info.location.retain(|location| {
            let len = location.path.len();
            len > 0 && len % 2 == 0
        });
        source_info.location.sort_by_key(|location| location.path.clone());

        let mut code_gen = CodeGenerator {
            source_info: source_info,
            depth: 0,
            path: Vec::new(),
            buf: String::new(),
        };

        debug!("file: {:?}, package: {:?}", file.name, file.package);
        if !file.package.is_empty() {
            code_gen.push_mod(&file.package);
        }

        code_gen.path.push(4);
        for (idx, message) in file.message_type.into_iter().enumerate() {
            code_gen.path.push(idx as i32);
            code_gen.append_message(message);
            code_gen.path.pop();
        }
        code_gen.path.pop();

        code_gen.path.push(5);
        for (idx, desc) in file.enum_type.into_iter().enumerate() {
            code_gen.path.push(idx as i32);
            code_gen.append_enum(desc);
            code_gen.path.pop();
        }
        code_gen.path.pop();

        if !file.package.is_empty() {
            code_gen.pop_mod();
        }

        code_gen.buf
    }

    fn append_message(&mut self, message: descriptor::DescriptorProto) {
        if !message.nested_type.is_empty() || !message.enum_type.is_empty() {
            self.push_mod(&camel_to_snake(&message.name));
            self.path.push(3);
            for (idx, inner) in message.nested_type.into_iter().enumerate() {
                self.path.push(idx as i32);
                self.append_message(inner);
                self.path.pop();
            }
            self.path.pop();

            self.path.push(4);
            for (idx, inner) in message.enum_type.into_iter().enumerate() {
                self.path.push(idx as i32);
                self.append_enum(inner);
                self.path.pop();
            }
            self.path.pop();

            self.pop_mod();
        }

        debug!("  message: {:?}", message.name);

        self.append_doc();

        self.push_indent();
        self.buf.push_str("#[derive(Debug, Message)]\n");
        self.push_indent();
        self.buf.push_str("struct ");
        self.buf.push_str(&message.name);
        self.buf.push_str(" {\n");

        self.depth += 1;
        self.path.push(2);
        for (idx, field) in message.fields.into_iter().enumerate() {
            self.path.push(idx as i32);
            self.append_field(field);
            self.path.pop();
        }
        self.path.pop();
        self.depth -= 1;

        self.push_indent();
        self.buf.push_str("}\n");
    }

    fn append_field(&mut self, field: descriptor::FieldDescriptorProto) {
        use descriptor::field_descriptor_proto::Type::*;
        use descriptor::field_descriptor_proto::Label::*;

        let repeated = field.label == LABEL_REPEATED;
        let signed = field.field_type == TYPE_SINT32 ||
                     field.field_type == TYPE_SINT64;
        let fixed = field.field_type == TYPE_FIXED32 ||
                    field.field_type == TYPE_FIXED64 ||
                    field.field_type == TYPE_SFIXED32 ||
                    field.field_type == TYPE_SFIXED64;

        let ty = match field.field_type {
            TYPE_FLOAT => Cow::Borrowed("f32"),
            TYPE_DOUBLE => Cow::Borrowed("f64"),
            TYPE_UINT32 | TYPE_FIXED32 => Cow::Borrowed("u32"),
            TYPE_UINT64 | TYPE_FIXED64 => Cow::Borrowed("u64"),
            TYPE_INT32 | TYPE_SFIXED32 | TYPE_SINT32 => Cow::Borrowed("i32"),
            TYPE_INT64 | TYPE_SFIXED64 | TYPE_SINT64 => Cow::Borrowed("i64"),
            TYPE_BOOL => Cow::Borrowed("bool"),
            TYPE_STRING => Cow::Borrowed("String"),
            TYPE_BYTES => Cow::Borrowed("Vec<u8>"),
            TYPE_GROUP | TYPE_MESSAGE | TYPE_ENUM => Cow::Owned(rust_ident(&field.type_name)),
        };
        debug!("    field: {:?}, type: {:?}", field.name, ty);

        self.append_doc();
        self.push_indent();
        self.buf.push_str("#[proto(tag=");
        self.buf.push_str(&field.number.to_string());
        if signed {
            self.buf.push_str(", signed");
        } else if fixed {
            self.buf.push_str(", fixed");
        }
        self.buf.push_str(")]\n");
        self.push_indent();
        self.buf.push_str("pub ");
        self.buf.push_str(&field.name);
        self.buf.push_str(": ");
        if repeated { self.buf.push_str("Vec<"); }
        self.buf.push_str(&ty);
        if repeated { self.buf.push_str(">"); }
        self.buf.push_str(",\n");
    }

    fn append_doc(&mut self) {
        let idx = self.source_info
                      .location
                      .binary_search_by_key(&&self.path[..], |location| &location.path[..])
                      .unwrap();
        let location = &self.source_info.location[idx];

        for comment in &location.leading_detached_comments {
            for line in comment.lines() {
                for _ in 0..self.depth {
                    self.buf.push_str("    ");
                }
                self.buf.push_str("//!");
                self.buf.push_str(line);
                self.buf.push_str("\n");
            }
            self.buf.push_str("\n");
        }

        for line in location.leading_comments.lines() {
            for _ in 0..self.depth {
                self.buf.push_str("    ");
            }
            self.buf.push_str("///");
            self.buf.push_str(line);
            self.buf.push_str("\n");
        }
        for line in location.trailing_comments.lines() {
            for _ in 0..self.depth {
                self.buf.push_str("    ");
            }
            self.buf.push_str("///");
            self.buf.push_str(line);
            self.buf.push_str("\n");
        }
    }

    fn append_enum(&mut self, desc: descriptor::EnumDescriptorProto) {
        debug!("  enum: {:?}", desc.name);

        self.append_doc();
        self.push_indent();
        self.buf.push_str("#[derive(Clone, Copy, Debug, Enumeration)]\n");
        self.push_indent();
        self.buf.push_str("enum ");
        self.buf.push_str(&desc.name);
        self.buf.push_str(" {\n");

        self.depth += 1;
        self.path.push(2);
        for (idx, value) in desc.value.into_iter().enumerate() {
            self.path.push(idx as i32);
            self.append_enum_value(value);
            self.path.pop();
        }
        self.path.pop();
        self.depth -= 1;

        self.push_indent();
        self.buf.push_str("}\n");

    }

    fn append_enum_value(&mut self, value: descriptor::EnumValueDescriptorProto) {
        self.append_doc();
        self.push_indent();
        self.buf.push_str(&snake_to_upper_camel(&value.name));
        self.buf.push_str(" = ");
        self.buf.push_str(&value.number.to_string());
        self.buf.push_str(",\n");
    }

    fn push_indent(&mut self) {
        for _ in 0..self.depth {
            self.buf.push_str("    ");
        }
    }

    fn push_mod(&mut self, module: &str) {
        self.push_indent();
        self.buf.push_str("mod ");
        self.buf.push_str(module);
        self.buf.push_str(" {\n");
        self.depth += 1;
    }

    fn pop_mod(&mut self) {
        self.depth -= 1;
        self.push_indent();
        self.buf.push_str("}\n");
    }
}

/// Converts a Protobuf identifier (e.g. `.Foo.Bar`) to Rust (e.g. `foo::Bar`).
fn rust_ident(pb_ident: &str) -> String {
    let mut ident = rust_module(pb_ident).map(|mut module| {
        module.push_str("::");
        module
    }).unwrap_or_default();
    ident.push_str(rust_type(pb_ident));
    ident
}

/// Returns the Rust module from a Protobuf identifier.
fn rust_module(pb_ident: &str) -> Option<String> {
    let ridx = pb_ident.rfind('.').expect(&format!("malformed Protobuf identifier: {}", pb_ident));

    if ridx == 0 {
        None
    } else {
        Some(pb_ident[1..ridx].split('.').map(camel_to_snake).join("::"))
    }
}

fn rust_type(pb_ident: &str) -> &str {
    let idx = pb_ident.rfind('.').expect(&format!("malformed Protobuf identifier: {}", pb_ident));
    &pb_ident[idx + 1..]
}

fn camel_to_snake(camel: &str) -> String {
    // protoc does not allow non-ascii identifiers.
    let len = camel.as_bytes().iter().skip(1).filter(|&&c| is_uppercase(c)).count() + camel.len();
    let mut snake = Vec::with_capacity(len);

    let mut skip = 0;
    for (i, &c) in camel.as_bytes().iter().enumerate() {
        if is_uppercase(c) {
            if i != skip {
                snake.push('_' as u8);
                skip = i + 1;
            } else {
                skip += 1;
            }
            snake.push(to_lowercase(c));
        } else {
            snake.push(c);
        }
    }

    String::from_utf8(snake).expect(&format!("non-utf8 identifier: {}", camel))
}

fn snake_to_upper_camel(snake: &str) -> String {
    let mut s = String::with_capacity(snake.len());

    if snake.is_empty() {
        return s;
    }

    for fragment in snake.split('_') {
        if fragment.is_empty() {
            s.push('_');
        } else {
            let (first, rest) = fragment.split_at(1);
            s.push_str(&first.to_uppercase());
            s.push_str(&rest.to_lowercase());
        }
    }
    s
}

#[inline]
fn is_uppercase(c: u8) -> bool {
    c >= 'A' as u8 && c <= 'Z' as u8
}

#[inline]
fn to_lowercase(c: u8) -> u8 {
    debug_assert!(is_uppercase(c));
    c + 32
}

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

    #[test]
    fn test_camel_to_snake() {
        assert_eq!("foo_bar", &camel_to_snake("FooBar"));
        assert_eq!("foo_bar_baz", &camel_to_snake("FooBarBAZ"));
        assert_eq!("foo_bar_baz", &camel_to_snake("FooBArBAZ"));
        assert_eq!("foo_bar_bazle_e", &camel_to_snake("FooBArBAZleE"));
    }

    #[test]
    fn test_snake_to_upper_camel() {
        assert_eq!("", &snake_to_upper_camel(""));
        assert_eq!("F", &snake_to_upper_camel("F"));
        assert_eq!("Foo", &snake_to_upper_camel("FOO"));
        assert_eq!("FooBar", &snake_to_upper_camel("FOO_BAR"));
        assert_eq!("_FooBar", &snake_to_upper_camel("_FOO_BAR"));
        assert_eq!("FooBar_", &snake_to_upper_camel("FOO_BAR_"));
        assert_eq!("_FooBar_", &snake_to_upper_camel("_FOO_BAR_"));
        assert_eq!("Fuzzbuster", &snake_to_upper_camel("fuzzBuster"));
    }
}
<commit_msg>small bugs<commit_after>#[macro_use]
extern crate proto_derive;
#[macro_use]
extern crate log;

extern crate env_logger;
extern crate itertools;
extern crate proto;

use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::io::{
    Cursor,
    Read,
    Result,
    Write,
    self,
};
use std::mem;

use itertools::Itertools;
use proto::Message;

mod descriptor;
mod plugin;

fn main() {
    env_logger::init().unwrap();
    let mut bytes = Vec::new();
    io::stdin().read_to_end(&mut bytes).unwrap();

    assert_ne!(bytes.len(), 0);

    let mut request = plugin::CodeGeneratorRequest::default();
    Message::merge_from(&mut request, bytes.len(), &mut Cursor::new(&mut bytes)).unwrap();

    let mut response = plugin::CodeGeneratorResponse::default();

    trace!("{:#?}", request);

    for file in request.proto_file {
        let mut resp = plugin::code_generator_response::File::default();

        match file.name.rfind('.') {
            Some(idx) => resp.name.push_str(&file.name[..idx]),
            None => resp.name.push_str(&file.name),
        }
        resp.name.push_str(".rs");

        resp.content = CodeGenerator::generate(file);
        response.file.push(resp);
    }

    let out = io::stdout();
    response.write_to(&mut out.lock()).unwrap();
}

struct CodeGenerator {
    source_info: descriptor::SourceCodeInfo,
    depth: u8,
    path: Vec<i32>,
    buf: String,
}

impl CodeGenerator {
    fn generate(file: descriptor::FileDescriptorProto) -> String {

        let mut source_info = file.source_code_info.expect("no source code info in request");
        source_info.location.retain(|location| {
            let len = location.path.len();
            len > 0 && len % 2 == 0
        });
        source_info.location.sort_by_key(|location| location.path.clone());

        let mut code_gen = CodeGenerator {
            source_info: source_info,
            depth: 0,
            path: Vec::new(),
            buf: String::new(),
        };

        debug!("file: {:?}, package: {:?}", file.name, file.package);

        code_gen.path.push(4);
        for (idx, message) in file.message_type.into_iter().enumerate() {
            code_gen.path.push(idx as i32);
            code_gen.append_message(message);
            code_gen.path.pop();
        }
        code_gen.path.pop();

        code_gen.path.push(5);
        for (idx, desc) in file.enum_type.into_iter().enumerate() {
            code_gen.path.push(idx as i32);
            code_gen.append_enum(desc);
            code_gen.path.pop();
        }
        code_gen.path.pop();

        code_gen.buf
    }

    fn append_message(&mut self, message: descriptor::DescriptorProto) {
        if !message.nested_type.is_empty() || !message.enum_type.is_empty() {
            self.push_mod(&camel_to_snake(&message.name));
            self.path.push(3);
            for (idx, inner) in message.nested_type.into_iter().enumerate() {
                self.path.push(idx as i32);
                self.append_message(inner);
                self.path.pop();
            }
            self.path.pop();

            self.path.push(4);
            for (idx, inner) in message.enum_type.into_iter().enumerate() {
                self.path.push(idx as i32);
                self.append_enum(inner);
                self.path.pop();
            }
            self.path.pop();

            self.pop_mod();
        }

        debug!("  message: {:?}", message.name);

        self.append_doc();

        self.push_indent();
        self.buf.push_str("#[derive(Debug, Message)]\n");
        self.push_indent();
        self.buf.push_str("pub struct ");
        self.buf.push_str(&message.name);
        self.buf.push_str(" {\n");

        self.depth += 1;
        self.path.push(2);
        for (idx, field) in message.fields.into_iter().enumerate() {
            self.path.push(idx as i32);
            self.append_field(field);
            self.path.pop();
        }
        self.path.pop();
        self.depth -= 1;

        self.push_indent();
        self.buf.push_str("}\n");
    }

    fn append_field(&mut self, field: descriptor::FieldDescriptorProto) {
        use descriptor::field_descriptor_proto::Type::*;
        use descriptor::field_descriptor_proto::Label::*;

        let repeated = field.label == LABEL_REPEATED;
        let signed = field.field_type == TYPE_SINT32 ||
                     field.field_type == TYPE_SINT64;
        let fixed = field.field_type == TYPE_FIXED32 ||
                    field.field_type == TYPE_FIXED64 ||
                    field.field_type == TYPE_SFIXED32 ||
                    field.field_type == TYPE_SFIXED64;
        let message = field.field_type == TYPE_MESSAGE;

        let ty = match field.field_type {
            TYPE_FLOAT => Cow::Borrowed("f32"),
            TYPE_DOUBLE => Cow::Borrowed("f64"),
            TYPE_UINT32 | TYPE_FIXED32 => Cow::Borrowed("u32"),
            TYPE_UINT64 | TYPE_FIXED64 => Cow::Borrowed("u64"),
            TYPE_INT32 | TYPE_SFIXED32 | TYPE_SINT32 => Cow::Borrowed("i32"),
            TYPE_INT64 | TYPE_SFIXED64 | TYPE_SINT64 => Cow::Borrowed("i64"),
            TYPE_BOOL => Cow::Borrowed("bool"),
            TYPE_STRING => Cow::Borrowed("String"),
            TYPE_BYTES => Cow::Borrowed("Vec<u8>"),
            TYPE_GROUP | TYPE_MESSAGE | TYPE_ENUM => Cow::Owned(rust_ident(&field.type_name)),
        };
        debug!("    field: {:?}, type: {:?}", field.name, ty);

        self.append_doc();
        self.push_indent();
        self.buf.push_str("#[proto(tag=\"");
        self.buf.push_str(&field.number.to_string());
        self.buf.push_str("\"");
        if signed {
            self.buf.push_str(", signed");
        } else if fixed {
            self.buf.push_str(", fixed");
        }
        self.buf.push_str(")]\n");
        self.push_indent();
        self.buf.push_str("pub ");
        self.buf.push_str(&field.name);
        self.buf.push_str(": ");
        if repeated { self.buf.push_str("Vec<"); }
        else if message { self.buf.push_str("Option<"); }
        self.buf.push_str(&ty);
        if repeated || message { self.buf.push_str(">"); }
        self.buf.push_str(",\n");
    }

    fn append_doc(&mut self) {
        let idx = self.source_info
                      .location
                      .binary_search_by_key(&&self.path[..], |location| &location.path[..])
                      .unwrap();
        let location = &self.source_info.location[idx];

        for comment in &location.leading_detached_comments {
            for line in comment.lines() {
                for _ in 0..self.depth {
                    self.buf.push_str("    ");
                }
                self.buf.push_str("//!");
                self.buf.push_str(line);
                self.buf.push_str("\n");
            }
            self.buf.push_str("\n");
        }

        for line in location.leading_comments.lines() {
            for _ in 0..self.depth {
                self.buf.push_str("    ");
            }
            self.buf.push_str("///");
            self.buf.push_str(line);
            self.buf.push_str("\n");
        }
        for line in location.trailing_comments.lines() {
            for _ in 0..self.depth {
                self.buf.push_str("    ");
            }
            self.buf.push_str("///");
            self.buf.push_str(line);
            self.buf.push_str("\n");
        }
    }

    fn append_enum(&mut self, desc: descriptor::EnumDescriptorProto) {
        debug!("  enum: {:?}", desc.name);

        self.append_doc();
        self.push_indent();
        self.buf.push_str("#[derive(Clone, Copy, Debug, Enumeration)]\n");
        self.push_indent();
        self.buf.push_str("pub enum ");
        self.buf.push_str(&desc.name);
        self.buf.push_str(" {\n");

        self.depth += 1;
        self.path.push(2);
        for (idx, value) in desc.value.into_iter().enumerate() {
            self.path.push(idx as i32);
            self.append_enum_value(value);
            self.path.pop();
        }
        self.path.pop();
        self.depth -= 1;

        self.push_indent();
        self.buf.push_str("}\n");

    }

    fn append_enum_value(&mut self, value: descriptor::EnumValueDescriptorProto) {
        self.append_doc();
        self.push_indent();
        self.buf.push_str(&snake_to_upper_camel(&value.name));
        self.buf.push_str(" = ");
        self.buf.push_str(&value.number.to_string());
        self.buf.push_str(",\n");
    }

    fn push_indent(&mut self) {
        for _ in 0..self.depth {
            self.buf.push_str("    ");
        }
    }

    fn push_mod(&mut self, module: &str) {
        self.push_indent();
        self.buf.push_str("mod ");
        self.buf.push_str(module);
        self.buf.push_str(" {\n");
        self.depth += 1;
    }

    fn pop_mod(&mut self) {
        self.depth -= 1;
        self.push_indent();
        self.buf.push_str("}\n");
    }
}

/// Converts a Protobuf identifier (e.g. `.Foo.Bar`) to Rust (e.g. `foo::Bar`).
fn rust_ident(pb_ident: &str) -> String {
    let mut ident = rust_module(pb_ident).map(|mut module| {
        module.push_str("::");
        module
    }).unwrap_or_default();
    ident.push_str(rust_type(pb_ident));
    ident
}

/// Returns the Rust module from a Protobuf identifier.
fn rust_module(pb_ident: &str) -> Option<String> {
    let ridx = pb_ident.rfind('.').expect(&format!("malformed Protobuf identifier: {}", pb_ident));

    if ridx == 0 {
        None
    } else {
        Some(pb_ident[1..ridx].split('.').map(camel_to_snake).join("::"))
    }
}

fn rust_type(pb_ident: &str) -> &str {
    let idx = pb_ident.rfind('.').expect(&format!("malformed Protobuf identifier: {}", pb_ident));
    &pb_ident[idx + 1..]
}

fn camel_to_snake(camel: &str) -> String {
    // protoc does not allow non-ascii identifiers.
    let len = camel.as_bytes().iter().skip(1).filter(|&&c| is_uppercase(c)).count() + camel.len();
    let mut snake = Vec::with_capacity(len);

    let mut skip = 0;
    for (i, &c) in camel.as_bytes().iter().enumerate() {
        if is_uppercase(c) {
            if i != skip {
                snake.push('_' as u8);
                skip = i + 1;
            } else {
                skip += 1;
            }
            snake.push(to_lowercase(c));
        } else {
            snake.push(c);
        }
    }

    String::from_utf8(snake).expect(&format!("non-utf8 identifier: {}", camel))
}

fn snake_to_upper_camel(snake: &str) -> String {
    let mut s = String::with_capacity(snake.len());

    if snake.is_empty() {
        return s;
    }

    for fragment in snake.split('_') {
        if fragment.is_empty() {
            s.push('_');
        } else {
            let (first, rest) = fragment.split_at(1);
            s.push_str(&first.to_uppercase());
            s.push_str(&rest.to_lowercase());
        }
    }
    s
}

#[inline]
fn is_uppercase(c: u8) -> bool {
    c >= 'A' as u8 && c <= 'Z' as u8
}

#[inline]
fn to_lowercase(c: u8) -> u8 {
    debug_assert!(is_uppercase(c));
    c + 32
}

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

    #[test]
    fn test_camel_to_snake() {
        assert_eq!("foo_bar", &camel_to_snake("FooBar"));
        assert_eq!("foo_bar_baz", &camel_to_snake("FooBarBAZ"));
        assert_eq!("foo_bar_baz", &camel_to_snake("FooBArBAZ"));
        assert_eq!("foo_bar_bazle_e", &camel_to_snake("FooBArBAZleE"));
    }

    #[test]
    fn test_snake_to_upper_camel() {
        assert_eq!("", &snake_to_upper_camel(""));
        assert_eq!("F", &snake_to_upper_camel("F"));
        assert_eq!("Foo", &snake_to_upper_camel("FOO"));
        assert_eq!("FooBar", &snake_to_upper_camel("FOO_BAR"));
        assert_eq!("_FooBar", &snake_to_upper_camel("_FOO_BAR"));
        assert_eq!("FooBar_", &snake_to_upper_camel("FOO_BAR_"));
        assert_eq!("_FooBar_", &snake_to_upper_camel("_FOO_BAR_"));
        assert_eq!("Fuzzbuster", &snake_to_upper_camel("fuzzBuster"));
    }
}
<|endoftext|>


<commit_before>//! This module provides casting iterators for certain types of accessors.

/// Casting iterator and accompanying types for `Colors`.
pub mod colors;
/// Casting iterator and accompanying types for `Indices`.
pub mod indices;
/// Casting iterator and accompanying types for `Joints`.
pub mod joints;
/// Casting iterator and accompanying types for `TexCoords`.
pub mod tex_coords;
/// Casting iterator and accompanying types for `Weights`.
pub mod weights;
/// Casting iterator and accompanying types for `MorphWeights`.
pub mod morph_weights;
/// Casting iterator and accompanying types for `Rotations`.
pub mod rotations;

fn norm_i8_as_f32(x: i8) -> f32 {
    (x as f32 * (1.0 / i8::max_value() as f32)).max(-1.0)
}

fn norm_u8_as_u16(x: u8) -> u16 {
    x as u16 * 0x100
}

fn norm_u8_as_f32(x: u8) -> f32 {
    x as f32 * (1.0 / u8::max_value() as f32)
}

fn norm_i16_as_f32(x: i16) -> f32 {
    (x as f32 * (1.0 / i16::max_value() as f32)).max(-1.0)
}

fn norm_u16_as_u8(x: u16) -> u8 {
    (x / 0x100) as u8
}

fn norm_u16_as_f32(x: u16) -> f32 {
    x as f32 * (1.0 / u16::max_value() as f32)
}

fn norm_f32_as_u8(x: f32) -> u8 {
    (x * u8::max_value() as f32) as u8
}

fn norm_f32_as_u16(x: f32) -> u16 {
    (x * u16::max_value() as f32) as u16
}
<commit_msg>#[inline(always)] for internal conversion functions.<commit_after>//! This module provides casting iterators for certain types of accessors.

/// Casting iterator and accompanying types for `Colors`.
pub mod colors;
/// Casting iterator and accompanying types for `Indices`.
pub mod indices;
/// Casting iterator and accompanying types for `Joints`.
pub mod joints;
/// Casting iterator and accompanying types for `TexCoords`.
pub mod tex_coords;
/// Casting iterator and accompanying types for `Weights`.
pub mod weights;
/// Casting iterator and accompanying types for `MorphWeights`.
pub mod morph_weights;
/// Casting iterator and accompanying types for `Rotations`.
pub mod rotations;

#[inline(always)]
fn norm_i8_as_f32(x: i8) -> f32 {
    (x as f32 * (1.0 / i8::max_value() as f32)).max(-1.0)
}

#[inline(always)]
fn norm_u8_as_u16(x: u8) -> u16 {
    x as u16 * 0x100
}

#[inline(always)]
fn norm_u8_as_f32(x: u8) -> f32 {
    x as f32 * (1.0 / u8::max_value() as f32)
}

#[inline(always)]
fn norm_i16_as_f32(x: i16) -> f32 {
    (x as f32 * (1.0 / i16::max_value() as f32)).max(-1.0)
}

#[inline(always)]
fn norm_u16_as_u8(x: u16) -> u8 {
    (x / 0x100) as u8
}

#[inline(always)]
fn norm_u16_as_f32(x: u16) -> f32 {
    x as f32 * (1.0 / u16::max_value() as f32)
}

#[inline(always)]
fn norm_f32_as_u8(x: f32) -> u8 {
    (x * u8::max_value() as f32) as u8
}

#[inline(always)]
fn norm_f32_as_u16(x: f32) -> u16 {
    (x * u16::max_value() as f32) as u16
}
<|endoftext|>


<commit_before>use std::f64::NAN;

#[derive(Debug, Clone, PartialEq)]
pub struct JsBool {
    val: bool,
}

#[derive(Debug, Clone, PartialEq)]
pub struct JsError {
    val: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct JsNull;

#[derive(Debug, Clone, PartialEq)]
pub struct JsNumber {
    val: f64,
}

#[derive(Debug, Clone, PartialEq)]
pub struct JsObject;

#[derive(Debug, Clone, PartialEq)]
pub struct JsString {
    val: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct JsSymbol {
    val: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct JsUndefined;

pub trait JsType {
    /// Coerce `self` into a value of JsBool for logical operations and if-statements.
    fn as_bool(self) -> JsBool;

    /// Coerce `self` into a value of JsNumber for numerical operations.
    fn as_number(self) -> JsNumber;
}

impl JsType for JsBool {
    /// Identity
    fn as_bool(self) -> JsBool {
        self
    }

    /// true -> 1; false -> 0
    fn as_number(self) -> JsNumber {
        if self.val {
            JsNumber { val: 1f64 }
        } else {
            JsNumber { val: 0f64 }
        }
    }
}

impl JsType for JsError {
    /// -> true
    fn as_bool(self) -> JsBool {
        JsBool { val: true }
    }

    /// -> NAN
    fn as_number(self) -> JsNumber {
        JsNumber { val: NAN }
    }
}

impl JsType for JsNull {
    /// -> false
    fn as_bool(self) -> JsBool {
        JsBool { val: false }
    }

    /// -> 0
    fn as_number(self) -> JsNumber {
        JsNumber { val: 0f64 }
    }
}

impl JsType for JsNumber {
    /// 0, -0, and NaN -> false; everything else -> true
    fn as_bool(self) -> JsBool {
        if self.val == 0.0f64 || self.val == -0.0f64 || self.val.is_nan() {
            JsBool { val: false }
        } else {
            JsBool { val: true }
        }
    }

    /// Identity
    fn as_number(self) -> JsNumber {
        self
    }
}

impl JsType for JsObject {
    /// -> true
    fn as_bool(self) -> JsBool {
        JsBool { val: true }
    }

    /// -> NaN
    fn as_number(self) -> JsNumber {
        JsNumber { val: NAN }
    }
}

impl JsType for JsString {
    /// empty string -> false; otherwise -> true
    fn as_bool(self) -> JsBool {
        if self.val.len() == 0 {
            JsBool { val: false }
        } else {
            JsBool { val: true }
        }
    }

    /// valid number `n` -> n; otherwise -> NaN
    fn as_number(self) -> JsNumber {
        if self.val.len() == 0 {
            JsNumber { val: 0f64 }
        } else {
            let num = self.val.parse();
            match num {
                Ok(n)  => JsNumber { val: n },
                Err(_) => JsNumber { val: NAN },
            }
        }
    }
}

impl JsType for JsSymbol {
    /// -> true
    fn as_bool(self) -> JsBool {
        JsBool { val: true }
    }

    /// TODO: actually throws error
    fn as_number(self) -> JsNumber {
        JsNumber { val: NAN }
    }
}

impl JsType for JsUndefined {
    /// -> false
    fn as_bool(self) -> JsBool {
        JsBool { val: false }
    }

    /// -> NaN
    fn as_number(self) -> JsNumber {
        JsNumber { val: NAN }
    }
}

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

    #[test]
    fn test_as_bool() {
        assert_eq!(JsBool { val: true  }, JsBool { val: true }.as_bool());
        assert_eq!(JsBool { val: false }, JsBool { val: false }.as_bool());

        assert_eq!(JsBool { val: false }, JsUndefined.as_bool());
        assert_eq!(JsBool { val: false }, JsNull.as_bool());
        assert_eq!(JsBool { val: false }, JsNumber { val: 0.0f64 }.as_bool());
        assert_eq!(JsBool { val: false }, JsNumber { val: -0.0f64 }.as_bool());
        assert_eq!(JsBool { val: false }, JsNumber { val: NAN }.as_bool());

        assert_eq!(JsBool { val: false }, JsString { val: String::from("")  }.as_bool());
        assert_eq!(JsBool { val: true  }, JsString { val: String::from("a") }.as_bool());
        assert_eq!(JsBool { val: true  }, JsSymbol { val: String::from("")  }.as_bool());
        assert_eq!(JsBool { val: true  }, JsSymbol { val: String::from("a") }.as_bool());

        assert_eq!(JsBool { val: true  }, JsObject.as_bool());
        assert_eq!(JsBool { val: true  }, JsError { val: String::from("a") }.as_bool());
    }

    fn assert_nan(n: JsNumber) {
        assert!(n.val.is_nan());
    }

    #[test]
    fn test_as_number() {
        assert_eq!(JsNumber { val: 1f64 }, JsBool { val: true  }.as_number());
        assert_eq!(JsNumber { val: 0f64 }, JsBool { val: false }.as_number());

        assert_eq!(JsNumber { val: 0f64 }, JsNull.as_number());
        assert_eq!(JsNumber { val: 0f64 }, JsNumber { val: 0.0f64  }.as_number());
        assert_eq!(JsNumber { val: 0f64 }, JsNumber { val: -0.0f64 }.as_number());
        assert_eq!(JsNumber { val: 0f64 }, JsString { val: String::from("") }.as_number());
        assert_nan(JsSymbol { val: String::from("")  }.as_number());
        assert_nan(JsSymbol { val: String::from("a") }.as_number());
        assert_nan(JsObject.as_number());
        assert_nan(JsError { val: String::from("a") }.as_number());
        assert_nan(JsUndefined.as_number());
        assert_nan(JsNumber { val: NAN }.as_number());
        assert_nan(JsString { val: String::from("a") }.as_number());
    }
}
<commit_msg>Remove old js_value<commit_after><|endoftext|>


<commit_before>use std::fmt;

/// An error encountered while working with structured data.
#[derive(Debug)]
pub struct Error {
    inner: Inner
}

#[derive(Debug)]
enum Inner {
    #[cfg(feature = "std")]
    Io(std::io::Error),
    Msg(&'static str),
    Fmt,
}

impl Error {
    /// Create an error from the given message.
    pub fn msg(msg: &'static str) -> Self {
        Error {
            inner: Inner::Msg(msg),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Inner::*;
        match &self.inner {
            #[cfg(feature = "std")]
            Io(err) => err.fmt(f),
            Msg(msg) => msg.fmt(f),
            Fmt => fmt::Error.fmt(f),
        }
    }
}

impl From<fmt::Error> for Error {
    fn from(_: fmt::Error) -> Self {
        Error {
            inner: Inner::Fmt,
        }
    }
}

impl From<Error> for fmt::Error {
    fn from(_: Error) -> Self {
        fmt::Error
    }
}

#[cfg(feature = "std")]
mod std_support {
    use super::*;
    use std::{error, io};

    impl error::Error for Error {
        fn description(&self) -> &str {
            "key values error"
        }
    }

    impl From<io::Error> for Error {
        fn from(err: io::Error) -> Self {
            Error {
                inner: Inner::Io(err)
            }
        }
    }

    impl From<Error> for io::Error {
        fn from(err: Error) -> Self {
            if let Inner::Io(err) = err.inner {
                err
            } else {
                io::Error::new(io::ErrorKind::Other, err)
            }
        }
    }
}
<commit_msg>Fix error with rustc 1.21<commit_after>use std::fmt;
#[cfg(feature = "std")]
use std::io;

/// An error encountered while working with structured data.
#[derive(Debug)]
pub struct Error {
    inner: Inner
}

#[derive(Debug)]
enum Inner {
    #[cfg(feature = "std")]
    Io(io::Error),
    Msg(&'static str),
    Fmt,
}

impl Error {
    /// Create an error from the given message.
    pub fn msg(msg: &'static str) -> Self {
        Error {
            inner: Inner::Msg(msg),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Inner::*;
        match &self.inner {
            #[cfg(feature = "std")]
            &Io(ref err) => err.fmt(f),
            &Msg(ref msg) => msg.fmt(f),
            &Fmt => fmt::Error.fmt(f),
        }
    }
}

impl From<fmt::Error> for Error {
    fn from(_: fmt::Error) -> Self {
        Error {
            inner: Inner::Fmt,
        }
    }
}

impl From<Error> for fmt::Error {
    fn from(_: Error) -> Self {
        fmt::Error
    }
}

#[cfg(feature = "std")]
mod std_support {
    use super::*;
    use std::{error, io};

    impl error::Error for Error {
        fn description(&self) -> &str {
            "key values error"
        }
    }

    impl From<io::Error> for Error {
        fn from(err: io::Error) -> Self {
            Error {
                inner: Inner::Io(err)
            }
        }
    }

    impl From<Error> for io::Error {
        fn from(err: Error) -> Self {
            if let Inner::Io(err) = err.inner {
                err
            } else {
                io::Error::new(io::ErrorKind::Other, err)
            }
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Structs and functions for working with lists.
//!
//! A list is a way to group accounts together, either as a way to highlight those accounts, or to
//! view as a subset of or supplement to your main timeline. A list can be viewed in the same way
//! as the user's own timelines, loading in pages with the same [`Timeline`] interface.
//!
//! [`Timeline`]: ../tweet/struct.Timeline.html
//!
//! Lists can be private or public. If a list if public, then other users can view the list's
//! members and the statuses of those members. (Statuses by protected accounts can still only be
//! read by approved followers.)
//!
//! A list has "members", those accounts that are tracked as part of the list. When you call
//! `statuses` on a given list, you're looking at the recent posts by its members. Members can be
//! added and removed either one at a time, or in batches. Protected accounts can only be added to
//! a list if the user is an approved follower of that account.
//!
//! A user can "subscribe" to another user's list as a sort of bookmark. Doing this places the list
//! in the "lists" section of their profile, and in the `subscriptions` and `list` sets available
//! from the API. Note that you don't need to subscribe to a list to view the statuses or users in
//! it; you can do that to any public or personally owned list anyway. Subscribing merely allows
//! quick access in case you want to keep track of a list someone else made.
//!
//! If a list is public, then all metadata about that list is public. Protected accounts can be
//! seen as members of a list, but their statuses are still only visible to approved followers.
//! None of the user-focused queries in this module assume that they're about the authenticated
//! user; they can all be called in reference to any user.
//!
//! ## Types
//!
//! - `List`: This is the list metadata returned from Twitter when requesting information about the
//!   list itself, or when performing some modification to one.
//! - `ListID`: There are two ways to reference a list in the Twitter API: Either via a unique
//!   numeric ID, or with its "slug" combined with a reference to the user who created it. This
//!   enum wraps that distinction into one type that all the methods take when they need to
//!   reference a list like this. See the enum's documentation for details on how to create one.
//! - `ListUpdate`: When updating a list's metadata, all the fields that can be updated are
//!   optional, so the `update` function returns this builder struct so you don't have to provide
//!   all the parameters if you don't need to.
//!
//! ## Functions
//!
//! ### Basic actions
//!
//! These functions perform basic write actions on lists as a whole. These all require write access
//! to the authenticated user's account.
//!
//! - `create`/`delete`
//! - `update` (see `ListUpdate` for full details)
//! - `subscribe`/`unsubscribe`
//! - `add_member`/`remove_member`
//! - `add_member_list`/`remove_member_list`
//!
//! ### Basic queries
//!
//! These functions let you query information about lists, or related to lists somehow.
//!
//! - `ownerships`/`subscriptions`/`list`: Note that `list` will only return the most recent 100
//!   lists in the `ownerships`/`subscriptions` sets.
//! - `memberships`
//! - `members`/`is_member`
//! - `subscribers`/`is_subscriber`
//! - `show`
//! - `statuses`

use std::collections::HashMap;

use common::*;

use chrono;

use auth;
use error;
use links;
use user;

mod fun;
pub use self::fun::*;

/// Convenience enum to refer to a list via its owner and name or via numeric ID.
///
/// Any API call that needs to reference a specific list has a set of parameters that collectively
/// refer to it. Not only do lists have a unique numeric ID that refers to them, they have a "slug"
/// that stands in as the list's unique name. This slug is only unique when taken in combination
/// with the user that created it, though, so this leads to the raw API call having parameters that
/// refer to the user by screen name or ID, or the list as a whole by this pair of slug parameters
/// or the single ID parameter. egg-mode wraps this pattern with this `ListID` enum.
///
/// Because the slug is formed from two variables instead of one, this enum foregoes the many
/// `From` implementations that `UserID` has and instead opts for two creation functions. If you
/// have a user/name combo, use `ListID::from_slug` when looking for the list. If you have the
/// list's ID instead, then you can use `ListID::from_id`.
///
/// # Example
///
/// ```rust
/// use egg_mode::list::ListID;
///
/// //The following two ListIDs refer to the same list:
/// let slug = ListID::from_slug("Twitter", "support");
/// let id = ListID::from_id(99924643);
/// ```
#[derive(Debug, Copy, Clone)]
pub enum ListID<'a> {
    ///Referring via the list's owner and its "slug" or name.
    Slug(user::UserID<'a>, &'a str),
    ///Referring via the list's numeric ID.
    ID(u64),
}

impl<'a> ListID<'a> {
    ///Make a new `ListID` by supplying its owner and name.
    pub fn from_slug<T: Into<user::UserID<'a>>>(owner: T, list_name: &'a str) -> ListID<'a> {
        ListID::Slug(owner.into(), list_name)
    }

    ///Make a new `ListID` by supplying its numeric ID.
    pub fn from_id(list_id: u64) -> ListID<'a> {
        ListID::ID(list_id)
    }
}

/// Represents the metadata for a list.
///
/// Because of the myriad ways to reference a list, there are a few seemingly-redundant fields on
/// here. It's worthwhile to understand all the referential fields:
///
/// * `name` is the human-readable name of the list. Notably, this can contain spaces and uppercase
///   letters.
/// * `slug` is simply `name` converted to a format that can be put into a URL and used to
///   reference the list for API calls.
/// * `full_name` is how you'd link the list as a @mention, in the form `@screen_name/slug`.
/// * `id` is the numeric ID, which can be used with `ListID::from_id` to make a `ListID` for the
///   list.
/// * `uri` is how you assemble a link to the list. Start with `"https://twitter.com"`, concat this
///   field to the end, and you have a full URL. Note that the field does start with its own slash.
/// * `user` is a mostly-populated `TwitterUser` corresponding to the creator of the list. If you
///   combine `user.screen_name` or `user.id` with `slug`, you can send them to `ListID::from_slug`
///   to make a `ListID` for the list.
#[derive(Clone, Debug, Deserialize)]
pub struct List {
    ///The name of the list.
    pub name: String,
    ///The user who created the list.
    pub user: user::TwitterUser,
    ///The "slug" of a list, that can be combined with its creator's `UserID` to refer to the list.
    pub slug: String,
    ///The numeric ID of the list.
    pub id: u64,
    ///The number of accounts "subscribed" to the list, for whom it will appear in their collection
    ///of available lists.
    pub subscriber_count: u64,
    ///The number of accounts added to the list.
    pub member_count: u64,
    ///The full name of the list, preceded by `@`, that can be used to link to the list as part of
    ///a tweet, direct message, or other place on Twitter where @mentions are parsed.
    pub full_name: String,
    ///The description of the list, as entered by its creator.
    pub description: String,
    ///The full name of the list, preceded by `/`, that can be preceded with `https://twitter.com`
    ///to create a link to the list.
    pub uri: String,
    ///UTC timestamp of when the list was created.
    pub created_at: chrono::DateTime<chrono::Utc>,
}

/// Represents a pending update to a list's metadata.
///
/// As updating a list could modify each field independently, this operation is exposed as a builder
/// struct. To update any field, call the method named after that field, then call `send` to send
/// the update to Twitter.
///
/// # Example
///
/// ```rust,no_run
/// # extern crate egg_mode; extern crate tokio; extern crate futures;
/// # use egg_mode::Token;
/// use tokio::runtime::current_thread::block_on_all;
/// # fn main() {
/// # let token: Token = unimplemented!();
/// use egg_mode::list::{self, ListID};
///
/// //remember, you can only update a list if you own it!
/// let update = list::update(ListID::from_slug("Twitter", "support"));
/// let list = block_on_all(update.name("Official Support").send(&token)).unwrap();
/// # }
/// ```
pub struct ListUpdate<'a> {
    list: ListID<'a>,
    name: Option<&'a str>,
    public: Option<bool>,
    desc: Option<&'a str>,
}

impl<'a> ListUpdate<'a> {
    ///Updates the name of the list.
    pub fn name(self, name: &'a str) -> ListUpdate<'a> {
        ListUpdate {
            name: Some(name),
            ..self
        }
    }

    ///Sets whether the list is public.
    pub fn public(self, public: bool) -> ListUpdate<'a> {
        ListUpdate {
            public: Some(public),
            ..self
        }
    }

    ///Updates the description of the list.
    pub fn desc(self, desc: &'a str) -> ListUpdate<'a> {
        ListUpdate {
            desc: Some(desc),
            ..self
        }
    }

    ///Sends the update request to Twitter.
    pub fn send(self, token: &auth::Token) -> FutureResponse<List> {
        let mut params = HashMap::new();
        add_list_param(&mut params, &self.list);

        if let Some(name) = self.name {
            add_param(&mut params, "name", name);
        }

        if let Some(public) = self.public {
            if public {
                add_param(&mut params, "mode", "public");
            } else {
                add_param(&mut params, "mode", "private");
            }
        }

        if let Some(desc) = self.desc {
            add_param(&mut params, "description", desc);
        }

        let req = auth::post(links::lists::UPDATE, token, Some(&params));

        make_parsed_future(req)
    }
}
<commit_msg>Deserialize lists properly (datetime format)<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Structs and functions for working with lists.
//!
//! A list is a way to group accounts together, either as a way to highlight those accounts, or to
//! view as a subset of or supplement to your main timeline. A list can be viewed in the same way
//! as the user's own timelines, loading in pages with the same [`Timeline`] interface.
//!
//! [`Timeline`]: ../tweet/struct.Timeline.html
//!
//! Lists can be private or public. If a list if public, then other users can view the list's
//! members and the statuses of those members. (Statuses by protected accounts can still only be
//! read by approved followers.)
//!
//! A list has "members", those accounts that are tracked as part of the list. When you call
//! `statuses` on a given list, you're looking at the recent posts by its members. Members can be
//! added and removed either one at a time, or in batches. Protected accounts can only be added to
//! a list if the user is an approved follower of that account.
//!
//! A user can "subscribe" to another user's list as a sort of bookmark. Doing this places the list
//! in the "lists" section of their profile, and in the `subscriptions` and `list` sets available
//! from the API. Note that you don't need to subscribe to a list to view the statuses or users in
//! it; you can do that to any public or personally owned list anyway. Subscribing merely allows
//! quick access in case you want to keep track of a list someone else made.
//!
//! If a list is public, then all metadata about that list is public. Protected accounts can be
//! seen as members of a list, but their statuses are still only visible to approved followers.
//! None of the user-focused queries in this module assume that they're about the authenticated
//! user; they can all be called in reference to any user.
//!
//! ## Types
//!
//! - `List`: This is the list metadata returned from Twitter when requesting information about the
//!   list itself, or when performing some modification to one.
//! - `ListID`: There are two ways to reference a list in the Twitter API: Either via a unique
//!   numeric ID, or with its "slug" combined with a reference to the user who created it. This
//!   enum wraps that distinction into one type that all the methods take when they need to
//!   reference a list like this. See the enum's documentation for details on how to create one.
//! - `ListUpdate`: When updating a list's metadata, all the fields that can be updated are
//!   optional, so the `update` function returns this builder struct so you don't have to provide
//!   all the parameters if you don't need to.
//!
//! ## Functions
//!
//! ### Basic actions
//!
//! These functions perform basic write actions on lists as a whole. These all require write access
//! to the authenticated user's account.
//!
//! - `create`/`delete`
//! - `update` (see `ListUpdate` for full details)
//! - `subscribe`/`unsubscribe`
//! - `add_member`/`remove_member`
//! - `add_member_list`/`remove_member_list`
//!
//! ### Basic queries
//!
//! These functions let you query information about lists, or related to lists somehow.
//!
//! - `ownerships`/`subscriptions`/`list`: Note that `list` will only return the most recent 100
//!   lists in the `ownerships`/`subscriptions` sets.
//! - `memberships`
//! - `members`/`is_member`
//! - `subscribers`/`is_subscriber`
//! - `show`
//! - `statuses`

use std::collections::HashMap;

use common::*;

use chrono;

use auth;
use error;
use links;
use user;

mod fun;
pub use self::fun::*;

/// Convenience enum to refer to a list via its owner and name or via numeric ID.
///
/// Any API call that needs to reference a specific list has a set of parameters that collectively
/// refer to it. Not only do lists have a unique numeric ID that refers to them, they have a "slug"
/// that stands in as the list's unique name. This slug is only unique when taken in combination
/// with the user that created it, though, so this leads to the raw API call having parameters that
/// refer to the user by screen name or ID, or the list as a whole by this pair of slug parameters
/// or the single ID parameter. egg-mode wraps this pattern with this `ListID` enum.
///
/// Because the slug is formed from two variables instead of one, this enum foregoes the many
/// `From` implementations that `UserID` has and instead opts for two creation functions. If you
/// have a user/name combo, use `ListID::from_slug` when looking for the list. If you have the
/// list's ID instead, then you can use `ListID::from_id`.
///
/// # Example
///
/// ```rust
/// use egg_mode::list::ListID;
///
/// //The following two ListIDs refer to the same list:
/// let slug = ListID::from_slug("Twitter", "support");
/// let id = ListID::from_id(99924643);
/// ```
#[derive(Debug, Copy, Clone)]
pub enum ListID<'a> {
    ///Referring via the list's owner and its "slug" or name.
    Slug(user::UserID<'a>, &'a str),
    ///Referring via the list's numeric ID.
    ID(u64),
}

impl<'a> ListID<'a> {
    ///Make a new `ListID` by supplying its owner and name.
    pub fn from_slug<T: Into<user::UserID<'a>>>(owner: T, list_name: &'a str) -> ListID<'a> {
        ListID::Slug(owner.into(), list_name)
    }

    ///Make a new `ListID` by supplying its numeric ID.
    pub fn from_id(list_id: u64) -> ListID<'a> {
        ListID::ID(list_id)
    }
}

/// Represents the metadata for a list.
///
/// Because of the myriad ways to reference a list, there are a few seemingly-redundant fields on
/// here. It's worthwhile to understand all the referential fields:
///
/// * `name` is the human-readable name of the list. Notably, this can contain spaces and uppercase
///   letters.
/// * `slug` is simply `name` converted to a format that can be put into a URL and used to
///   reference the list for API calls.
/// * `full_name` is how you'd link the list as a @mention, in the form `@screen_name/slug`.
/// * `id` is the numeric ID, which can be used with `ListID::from_id` to make a `ListID` for the
///   list.
/// * `uri` is how you assemble a link to the list. Start with `"https://twitter.com"`, concat this
///   field to the end, and you have a full URL. Note that the field does start with its own slash.
/// * `user` is a mostly-populated `TwitterUser` corresponding to the creator of the list. If you
///   combine `user.screen_name` or `user.id` with `slug`, you can send them to `ListID::from_slug`
///   to make a `ListID` for the list.
#[derive(Clone, Debug, Deserialize)]
pub struct List {
    ///The name of the list.
    pub name: String,
    ///The user who created the list.
    pub user: user::TwitterUser,
    ///The "slug" of a list, that can be combined with its creator's `UserID` to refer to the list.
    pub slug: String,
    ///The numeric ID of the list.
    pub id: u64,
    ///The number of accounts "subscribed" to the list, for whom it will appear in their collection
    ///of available lists.
    pub subscriber_count: u64,
    ///The number of accounts added to the list.
    pub member_count: u64,
    ///The full name of the list, preceded by `@`, that can be used to link to the list as part of
    ///a tweet, direct message, or other place on Twitter where @mentions are parsed.
    pub full_name: String,
    ///The description of the list, as entered by its creator.
    pub description: String,
    ///The full name of the list, preceded by `/`, that can be preceded with `https://twitter.com`
    ///to create a link to the list.
    pub uri: String,
    ///UTC timestamp of when the list was created.
    #[serde(deserialize_with = "deserialize_datetime")]
    pub created_at: chrono::DateTime<chrono::Utc>,
}

/// Represents a pending update to a list's metadata.
///
/// As updating a list could modify each field independently, this operation is exposed as a builder
/// struct. To update any field, call the method named after that field, then call `send` to send
/// the update to Twitter.
///
/// # Example
///
/// ```rust,no_run
/// # extern crate egg_mode; extern crate tokio; extern crate futures;
/// # use egg_mode::Token;
/// use tokio::runtime::current_thread::block_on_all;
/// # fn main() {
/// # let token: Token = unimplemented!();
/// use egg_mode::list::{self, ListID};
///
/// //remember, you can only update a list if you own it!
/// let update = list::update(ListID::from_slug("Twitter", "support"));
/// let list = block_on_all(update.name("Official Support").send(&token)).unwrap();
/// # }
/// ```
pub struct ListUpdate<'a> {
    list: ListID<'a>,
    name: Option<&'a str>,
    public: Option<bool>,
    desc: Option<&'a str>,
}

impl<'a> ListUpdate<'a> {
    ///Updates the name of the list.
    pub fn name(self, name: &'a str) -> ListUpdate<'a> {
        ListUpdate {
            name: Some(name),
            ..self
        }
    }

    ///Sets whether the list is public.
    pub fn public(self, public: bool) -> ListUpdate<'a> {
        ListUpdate {
            public: Some(public),
            ..self
        }
    }

    ///Updates the description of the list.
    pub fn desc(self, desc: &'a str) -> ListUpdate<'a> {
        ListUpdate {
            desc: Some(desc),
            ..self
        }
    }

    ///Sends the update request to Twitter.
    pub fn send(self, token: &auth::Token) -> FutureResponse<List> {
        let mut params = HashMap::new();
        add_list_param(&mut params, &self.list);

        if let Some(name) = self.name {
            add_param(&mut params, "name", name);
        }

        if let Some(public) = self.public {
            if public {
                add_param(&mut params, "mode", "public");
            } else {
                add_param(&mut params, "mode", "private");
            }
        }

        if let Some(desc) = self.desc {
            add_param(&mut params, "description", desc);
        }

        let req = auth::post(links::lists::UPDATE, token, Some(&params));

        make_parsed_future(req)
    }
}
<|endoftext|>