<commit_before>//! UDP relay client

use std::{
    io,
    io::{Cursor, Read},
    net::{IpAddr, Ipv4Addr, SocketAddr},
};

use bytes::{Bytes, BytesMut};
use log::{debug, error, warn};
use tokio::net::UdpSocket;

use crate::{
    config::{ServerAddr, ServerConfig},
    context::Context,
    crypto::{CipherCategory, CipherType},
    relay::{socks5::Address, sys::create_udp_socket, utils::try_timeout},
};

use super::{
    crypto_io::{decrypt_payload, encrypt_payload},
    DEFAULT_TIMEOUT,
    MAXIMUM_UDP_PAYLOAD_SIZE,
};

/// UDP client for communicating with ShadowSocks' server
pub struct ServerClient {
    socket: UdpSocket,
    method: CipherType,
    key: Bytes,
}

impl ServerClient {
    /// Create a client to communicate with Shadowsocks' UDP server
    pub async fn new(context: &Context, svr_cfg: &ServerConfig) -> io::Result<ServerClient> {
        let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
        let socket = create_udp_socket(&local_addr).await?;
        match svr_cfg.addr() {
            ServerAddr::SocketAddr(ref remote_addr) => socket.connect(remote_addr).await?,
            ServerAddr::DomainName(ref dname, port) => {
                lookup_then!(context, dname, *port, |addr| { socket.connect(&addr).await })?;
            }
        };
        Ok(ServerClient {
            socket,
            method: svr_cfg.method(),
            key: svr_cfg.clone_key(),
        })
    }

    /// Send a UDP packet to addr through proxy
    pub async fn send_to(&mut self, context: &Context, addr: &Address, payload: &[u8]) -> io::Result<()> {
        debug!(
            "UDP server client send to {}, payload length {} bytes",
            addr,
            payload.len()
        );

        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let mut send_buf = Vec::with_capacity(addr.serialized_len() + payload.len());
        addr.write_to_buf(&mut send_buf);
        send_buf.extend_from_slice(payload);

        if let CipherCategory::None = self.method.category() {
            let send_len = try_timeout(self.socket.send(&send_buf), Some(timeout)).await?;
            if send_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    send_buf.len(),
                    send_len
                );
            }
        } else {
            let mut encrypt_buf = BytesMut::new();
            encrypt_payload(context, self.method, &self.key, &send_buf, &mut encrypt_buf)?;

            let send_len = try_timeout(self.socket.send(&encrypt_buf), Some(timeout)).await?;
            if encrypt_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    encrypt_buf.len(),
                    send_len
                );
            }
        }

        Ok(())
    }

    /// Receive packet from Shadowsocks' UDP server
    pub async fn recv_from(&mut self, context: &Context) -> io::Result<(Address, Vec<u8>)> {
        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // Waiting for response from server SERVER -> CLIENT
        // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded.
        let mut recv_buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
        let recv_n = try_timeout(self.socket.recv(&mut recv_buf), Some(timeout)).await?;

        let mut cur = if let CipherCategory::None = self.method.category() {
            recv_buf.truncate(recv_n);
            Cursor::new(recv_buf)
        } else {
            let decrypt_buf = match decrypt_payload(context, self.method, &self.key, &recv_buf[..recv_n])? {
                None => {
                    error!("UDP packet too short, received length {}", recv_n);
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Some(b) => b,
            };
            Cursor::new(decrypt_buf)
        };

        // SERVER -> CLIENT protocol: ADDRESS + PAYLOAD
        // FIXME: Address is ignored. Maybe useful in the future if we uses one common UdpSocket for communicate with remote server
        let addr = Address::read_from(&mut cur).await?;

        let mut payload = Vec::with_capacity(recv_n - cur.position() as usize);
        cur.read_to_end(&mut payload)?;

        debug!(
            "UDP server client recv {}, payload length {} bytes",
            addr,
            payload.len()
        );

        Ok((addr, payload))
    }
}
<commit_msg>add split support to the UDP client<commit_after>//! UDP relay client

use std::{
    io,
    io::{Cursor, Read},
    net::{IpAddr, Ipv4Addr, SocketAddr},
    sync::Arc,
};

use bytes::{Bytes, BytesMut};
use log::{debug, error, warn};
use tokio::net::{
    udp::{RecvHalf, SendHalf},
    UdpSocket,
};

use crate::{
    config::{ServerAddr, ServerConfig},
    context::Context,
    crypto::{CipherCategory, CipherType},
    relay::{socks5::Address, sys::create_udp_socket, utils::try_timeout},
};

use super::{
    crypto_io::{decrypt_payload, encrypt_payload},
    DEFAULT_TIMEOUT,
    MAXIMUM_UDP_PAYLOAD_SIZE,
};

struct Half<T> {
    half: T,
    inner: Arc<HalfInner>,
}

struct HalfInner {
    method: CipherType,
    key: Bytes,
}

/// Receive half of a UDP client for communicating with ShadowSocks' server
pub struct ServerClientRecvHalf(Half<RecvHalf>);

impl ServerClientRecvHalf {
    /// Receive packet from Shadowsocks' UDP server
    pub async fn recv_from(&mut self, context: &Context) -> io::Result<(Address, Vec<u8>)> {
        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // Waiting for response from server SERVER -> CLIENT
        // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded.
        let mut recv_buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
        let recv_n = try_timeout(self.0.half.recv(&mut recv_buf), Some(timeout)).await?;
        let (addr, payload) =
            ServerClient::parse_resp(context, self.0.inner.method, &self.0.inner.key, &recv_buf[..recv_n]).await?;
        Ok((addr, payload))
    }
}

/// Send half of a UDP client for communicating with ShadowSocks' server
pub struct ServerClientSendHalf(Half<SendHalf>);

impl ServerClientSendHalf {
    /// Send a UDP packet to addr through proxy
    pub async fn send_to(&mut self, context: &Context, addr: &Address, payload: &[u8]) -> io::Result<()> {
        debug!(
            "UDP server client send to {}, payload length {} bytes",
            addr,
            payload.len()
        );

        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        let send_buf = ServerClient::pack_req(self.0.inner.method, &self.0.inner.key, context, addr, payload).await?;

        let send_len = try_timeout(self.0.half.send(&send_buf), Some(timeout)).await?;
        if send_buf.len() != send_len {
            warn!(
                "UDP server client send {} bytes, but actually sent {} bytes",
                send_buf.len(),
                send_len
            );
        }
        Ok(())
    }
}

/// UDP client for communicating with ShadowSocks' server
pub struct ServerClient {
    socket: UdpSocket,
    method: CipherType,
    key: Bytes,
}

impl ServerClient {
    /// Create a client to communicate with Shadowsocks' UDP server
    pub async fn new(context: &Context, svr_cfg: &ServerConfig) -> io::Result<ServerClient> {
        let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
        let socket = create_udp_socket(&local_addr).await?;
        match svr_cfg.addr() {
            ServerAddr::SocketAddr(ref remote_addr) => socket.connect(remote_addr).await?,
            ServerAddr::DomainName(ref dname, port) => {
                lookup_then!(context, dname, *port, |addr| { socket.connect(&addr).await })?;
            }
        };
        Ok(ServerClient {
            socket,
            method: svr_cfg.method(),
            key: svr_cfg.clone_key(),
        })
    }

    /// Split the UDP client into receive and send halves.
    pub fn split(self) -> (ServerClientRecvHalf, ServerClientSendHalf) {
        let (r, s) = self.socket.split();
        let hi = Arc::new(HalfInner {
            method: self.method,
            key: self.key,
        });
        (
            ServerClientRecvHalf(Half {
                half: r,
                inner: hi.clone(),
            }),
            ServerClientSendHalf(Half { half: s, inner: hi }),
        )
    }

    async fn pack_req(
        method: CipherType,
        key: &Bytes,
        context: &Context,
        addr: &Address,
        payload: &[u8],
    ) -> io::Result<Vec<u8>> {
        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let mut send_buf = Vec::with_capacity(addr.serialized_len() + payload.len());
        addr.write_to_buf(&mut send_buf);
        send_buf.extend_from_slice(payload);
        if let CipherCategory::None = method.category() {
            Ok(send_buf)
        } else {
            let mut encrypt_buf = BytesMut::new();
            encrypt_payload(context, method, key, &send_buf, &mut encrypt_buf)?;
            Ok(encrypt_buf.freeze().as_ref().to_vec())
        }
    }

    /// Send a UDP packet to addr through proxy
    pub async fn send_to(&mut self, context: &Context, addr: &Address, payload: &[u8]) -> io::Result<()> {
        debug!(
            "UDP server client send to {}, payload length {} bytes",
            addr,
            payload.len()
        );

        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        let send_buf = Self::pack_req(self.method, &self.key, context, addr, payload).await?;

        let send_len = try_timeout(self.socket.send(&send_buf), Some(timeout)).await?;
        if send_buf.len() != send_len {
            warn!(
                "UDP server client send {} bytes, but actually sent {} bytes",
                send_buf.len(),
                send_len
            );
        }

        Ok(())
    }

    async fn parse_resp(
        context: &Context,
        method: CipherType,
        key: &Bytes,
        recv_buf: &[u8],
    ) -> io::Result<(Address, Vec<u8>)> {
        let mut cur = if let CipherCategory::None = method.category() {
            Cursor::new(recv_buf.to_vec())
        } else {
            let decrypt_buf = match decrypt_payload(context, method, key, recv_buf)? {
                None => {
                    error!("UDP packet too short, received length {}", recv_buf.len());
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Some(b) => b,
            };
            Cursor::new(decrypt_buf)
        };

        // SERVER -> CLIENT protocol: ADDRESS + PAYLOAD
        // FIXME: Address is ignored. Maybe useful in the future if we uses one common UdpSocket for communicate with remote server
        let addr = Address::read_from(&mut cur).await?;

        let mut payload = Vec::with_capacity(recv_buf.len() - cur.position() as usize);
        cur.read_to_end(&mut payload)?;

        debug!(
            "UDP server client recv {}, payload length {} bytes",
            addr,
            payload.len()
        );

        Ok((addr, payload))
    }

    /// Receive packet from Shadowsocks' UDP server
    pub async fn recv_from(&mut self, context: &Context) -> io::Result<(Address, Vec<u8>)> {
        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // Waiting for response from server SERVER -> CLIENT
        // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded.
        let mut recv_buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
        let recv_n = try_timeout(self.socket.recv(&mut recv_buf), Some(timeout)).await?;
        let (addr, payload) = Self::parse_resp(context, self.method, &self.key, &recv_buf[..recv_n]).await?;
        Ok((addr, payload))
    }
}
<|endoftext|>


<commit_before>//! UDP relay client

use std::{
    io,
    io::{Cursor, Read},
    net::{IpAddr, Ipv4Addr, SocketAddr},
};

use bytes::{Bytes, BytesMut};
use log::{debug, error, warn};
use tokio::net::UdpSocket;

use crate::{
    config::{ServerAddr, ServerConfig},
    context::Context,
    crypto::{CipherCategory, CipherType},
    relay::{socks5::Address, sys::create_udp_socket, utils::try_timeout},
};

use super::{
    crypto_io::{decrypt_payload, encrypt_payload},
    DEFAULT_TIMEOUT,
    MAXIMUM_UDP_PAYLOAD_SIZE,
};

/// UDP client for communicating with ShadowSocks' server
pub struct ServerClient {
    socket: UdpSocket,
    method: CipherType,
    key: Bytes,
}

impl ServerClient {
    /// Create a client to communicate with Shadowsocks' UDP server
    pub async fn new(context: &Context, svr_cfg: &ServerConfig) -> io::Result<ServerClient> {
        let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
        let socket = create_udp_socket(&local_addr).await?;
        match svr_cfg.addr() {
            ServerAddr::SocketAddr(ref remote_addr) => socket.connect(remote_addr).await?,
            ServerAddr::DomainName(ref dname, port) => {
                lookup_then!(context, dname, *port, |addr| { socket.connect(&addr).await })?;
            }
        };
        Ok(ServerClient {
            socket,
            method: svr_cfg.method(),
            key: svr_cfg.clone_key(),
        })
    }

    /// Send a UDP packet to addr through proxy
    pub async fn send_to(&mut self, context: &Context, addr: &Address, payload: &[u8]) -> io::Result<()> {
        debug!(
            "UDP server client send to {}, payload length {} bytes",
            addr,
            payload.len()
        );

        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let mut send_buf = Vec::with_capacity(addr.serialized_len() + payload.len());
        addr.write_to_buf(&mut send_buf);
        send_buf.extend_from_slice(payload);

        if let CipherCategory::None = self.method.category() {
            let send_len = try_timeout(self.socket.send(&send_buf), Some(timeout)).await?;
            if send_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    send_buf.len(),
                    send_len
                );
            }
        } else {
            let mut encrypt_buf = BytesMut::new();
            encrypt_payload(context, self.method, &self.key, &send_buf, &mut encrypt_buf)?;

            let send_len = try_timeout(self.socket.send(&encrypt_buf), Some(timeout)).await?;
            if encrypt_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    encrypt_buf.len(),
                    send_len
                );
            }
        }

        Ok(())
    }

    /// Receive packet from Shadowsocks' UDP server
    pub async fn recv_from(&mut self, context: &Context) -> io::Result<(Address, Vec<u8>)> {
        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // Waiting for response from server SERVER -> CLIENT
        // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded.
        let mut recv_buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
        let recv_n = try_timeout(self.socket.recv(&mut recv_buf), Some(timeout)).await?;

        let mut cur = if let CipherCategory::None = self.method.category() {
            let decrypt_buf = match decrypt_payload(context, self.method, &self.key, &recv_buf[..recv_n])? {
                None => {
                    error!("UDP packet too short, received length {}", recv_n);
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Some(b) => b,
            };
            Cursor::new(decrypt_buf)
        } else {
            recv_buf.truncate(recv_n);
            Cursor::new(recv_buf)
        };

        // SERVER -> CLIENT protocol: ADDRESS + PAYLOAD
        // FIXME: Address is ignored. Maybe useful in the future if we uses one common UdpSocket for communicate with remote server
        let addr = Address::read_from(&mut cur).await?;

        let mut payload = Vec::with_capacity(recv_n - cur.position() as usize);
        cur.read_to_end(&mut payload)?;

        debug!(
            "UDP server client recv {}, payload length {} bytes",
            addr,
            payload.len()
        );

        Ok((addr, payload))
    }
}
<commit_msg>fix data decryption in UDP ServerClient<commit_after>//! UDP relay client

use std::{
    io,
    io::{Cursor, Read},
    net::{IpAddr, Ipv4Addr, SocketAddr},
};

use bytes::{Bytes, BytesMut};
use log::{debug, error, warn};
use tokio::net::UdpSocket;

use crate::{
    config::{ServerAddr, ServerConfig},
    context::Context,
    crypto::{CipherCategory, CipherType},
    relay::{socks5::Address, sys::create_udp_socket, utils::try_timeout},
};

use super::{
    crypto_io::{decrypt_payload, encrypt_payload},
    DEFAULT_TIMEOUT,
    MAXIMUM_UDP_PAYLOAD_SIZE,
};

/// UDP client for communicating with ShadowSocks' server
pub struct ServerClient {
    socket: UdpSocket,
    method: CipherType,
    key: Bytes,
}

impl ServerClient {
    /// Create a client to communicate with Shadowsocks' UDP server
    pub async fn new(context: &Context, svr_cfg: &ServerConfig) -> io::Result<ServerClient> {
        let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
        let socket = create_udp_socket(&local_addr).await?;
        match svr_cfg.addr() {
            ServerAddr::SocketAddr(ref remote_addr) => socket.connect(remote_addr).await?,
            ServerAddr::DomainName(ref dname, port) => {
                lookup_then!(context, dname, *port, |addr| { socket.connect(&addr).await })?;
            }
        };
        Ok(ServerClient {
            socket,
            method: svr_cfg.method(),
            key: svr_cfg.clone_key(),
        })
    }

    /// Send a UDP packet to addr through proxy
    pub async fn send_to(&mut self, context: &Context, addr: &Address, payload: &[u8]) -> io::Result<()> {
        debug!(
            "UDP server client send to {}, payload length {} bytes",
            addr,
            payload.len()
        );

        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // CLIENT -> SERVER protocol: ADDRESS + PAYLOAD
        let mut send_buf = Vec::with_capacity(addr.serialized_len() + payload.len());
        addr.write_to_buf(&mut send_buf);
        send_buf.extend_from_slice(payload);

        if let CipherCategory::None = self.method.category() {
            let send_len = try_timeout(self.socket.send(&send_buf), Some(timeout)).await?;
            if send_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    send_buf.len(),
                    send_len
                );
            }
        } else {
            let mut encrypt_buf = BytesMut::new();
            encrypt_payload(context, self.method, &self.key, &send_buf, &mut encrypt_buf)?;

            let send_len = try_timeout(self.socket.send(&encrypt_buf), Some(timeout)).await?;
            if encrypt_buf.len() != send_len {
                warn!(
                    "UDP server client send {} bytes, but actually sent {} bytes",
                    encrypt_buf.len(),
                    send_len
                );
            }
        }

        Ok(())
    }

    /// Receive packet from Shadowsocks' UDP server
    pub async fn recv_from(&mut self, context: &Context) -> io::Result<(Address, Vec<u8>)> {
        let timeout = context.config().udp_timeout.unwrap_or(DEFAULT_TIMEOUT);

        // Waiting for response from server SERVER -> CLIENT
        // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded.
        let mut recv_buf = vec![0u8; MAXIMUM_UDP_PAYLOAD_SIZE];
        let recv_n = try_timeout(self.socket.recv(&mut recv_buf), Some(timeout)).await?;

        let mut cur = if let CipherCategory::None = self.method.category() {
            recv_buf.truncate(recv_n);
            Cursor::new(recv_buf)
        } else {
            let decrypt_buf = match decrypt_payload(context, self.method, &self.key, &recv_buf[..recv_n])? {
                None => {
                    error!("UDP packet too short, received length {}", recv_n);
                    let err = io::Error::new(io::ErrorKind::InvalidData, "packet too short");
                    return Err(err);
                }
                Some(b) => b,
            };
            Cursor::new(decrypt_buf)
        };

        // SERVER -> CLIENT protocol: ADDRESS + PAYLOAD
        // FIXME: Address is ignored. Maybe useful in the future if we uses one common UdpSocket for communicate with remote server
        let addr = Address::read_from(&mut cur).await?;

        let mut payload = Vec::with_capacity(recv_n - cur.position() as usize);
        cur.read_to_end(&mut payload)?;

        debug!(
            "UDP server client recv {}, payload length {} bytes",
            addr,
            payload.len()
        );

        Ok((addr, payload))
    }
}
<|endoftext|>


<commit_before>use clap::ArgMatches;
use std::collections::HashSet;

pub fn actions_get(matches: &ArgMatches) -> HashSet<String> {
    let mut hs_actions = HashSet::<String>::new();

    if let Some(_) = matches.values_of("list-provides") {
        let bill = String::from("load-jobs");
        hs_actions.insert(bill);
        let list_provides = String::from("list-provides");
        hs_actions.insert(list_provides);
    }
    if let Some(_) = matches.values_of("session") {
        let bill = String::from("load-jobs");
        hs_actions.insert(bill);
        let str_load_scripts = String::from("load-scripts");
        hs_actions.insert(str_load_scripts);
        let session = String::from("session");
        hs_actions.insert(session);
    }
    return hs_actions;
}
<commit_msg>Feature add list-target<commit_after>use clap::ArgMatches;
use std::collections::HashSet;

pub fn actions_get(matches: &ArgMatches) -> HashSet<String> {
    let mut hs_actions = HashSet::<String>::new();

    if let Some(_) = matches.values_of("list-provides") {
        let bill = String::from("load-jobs");
        hs_actions.insert(bill);
        let list_provides = String::from("list-provides");
        hs_actions.insert(list_provides);
    }
    if let Some(_) = matches.values_of("list-target") {
        let bill = String::from("load-jobs");
        hs_actions.insert(bill);
        let list_provides = String::from("list-target");
        hs_actions.insert(list_provides);
    }
    if let Some(_) = matches.values_of("session") {
        let bill = String::from("load-jobs");
        hs_actions.insert(bill);
        let str_load_scripts = String::from("load-scripts");
        hs_actions.insert(str_load_scripts);
        let session = String::from("session");
        hs_actions.insert(session);
    }
    return hs_actions;
}
<|endoftext|>


<commit_before>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: state/console/console.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Manages the model portion
      of the in-game console.
*/

use glfw;
use ui;
use math;
use super::State;
use util::Log;

#[macro_escape]
#[path = "../../util/log_macros.rs"]
mod log_macros;

struct Console
{
  activator: @mut ui::Console_Activator,

  position: math::Vec2f,
  velocity: f32, /* On the Y axis only. */

  body: ~str,
  prefix: ~str,
  input: ~str,
}

impl Console
{
  pub fn new() -> @mut Console
  {
    let c = @mut Console
    {
      activator: ui::Console_Activator::new(),

      position: math::Vec2f::zero(),
      velocity: 300.0,

      body: fmt!("Welcome to Q^3\nVersion: %s.%s", env!("VERSION"), env!("COMMIT")),
      prefix: ~"> ",
      input: ~"",
    };

    /* The 'get' and 'set' functions are built in to the console. */
    c.activator.functions.insert(~"get",
    |_get, property| -> Option<~str>
    {
      let mut err = ~"";

      /* Check if this property exists. */
      match c.activator.accessors.find(&property.to_owned())
      {
        Some(func) =>
        { c.add_log(fmt!("%s = %s", property, (*func)(property))); }
        None =>
        { err = fmt!("Error: Invalid property %s", property); }
      }

      if err.len() == 0
      { None }
      else
      { Some(err) }
    });

    c.activator.functions.insert(~"set",
    |_set, params| -> Option<~str>
    {
      let mut error = ~"";
      let mut property = ~"";
      let mut params = params.to_owned();
      for x in params.split_iter(' ')
      { property = x.to_owned(); break; }

      /* Remove the property from the string. */
      for _ in property.iter()
      { params.shift_char(); }
      params.shift_char();

      /* We require a property and a value. */
      if property.len() == 0
      { error = fmt!("Invalid len for 'set' function arg list: %s", params); }
      else
      {
        /* Check if this property exists. */
        match c.activator.mutators.find(&property)
        {
          Some(func) =>
          {
            /* Pass the args to the property mutator. */
            match (*func)(property, params)
            {
              /* Check if the mutator liked the args. */
              Some(err) => { error = err; }
              None => { }
            }
          }
          None => { error = fmt!("The property %s does not exist.", property); }
        }
      }

      if error.len() > 0
      { Some(fmt!("Error: %s", error)) }
      else
      { None }
    });

    c
  }

  pub fn add_log(&mut self, text: &str)
  { self.body.push_str("\n" + text); }
}

impl State for Console
{
  pub fn load(&mut self)
  { log_debug!("Loading console state."); }

  pub fn unload(&mut self)
  { log_debug!("Unloading console state."); }

  pub fn update(&mut self, _delta: f32) -> bool /* dt is in terms of seconds. */
  { false }

  pub fn render(&mut self) -> bool
  { false }

  pub fn key_action(&mut self, key: i32, action: i32, _mods: i32) -> bool
  {
    if action == glfw::PRESS || action == glfw::REPEAT
    {
      /* Mac grave is world 1 for some reason. */
      if key == glfw::KEY_GRAVE_ACCENT || key == glfw::KEY_WORLD_1
      {
        self.velocity *= -1.0;
        return true;
      }

      /* The following only apply if the console is enabled. */
      if self.velocity > 0.0
      {
        if key == glfw::KEY_ENTER
        {
          if self.input.len() == 0
          { return true; }

          /* Extract the function name. */
          let mut func = ~"";
          for x in self.input.split_iter(' ')
          { func = x.to_owned(); break; };

          /* Remove the function from the string. */
          for _ in func.iter()
          { self.input.shift_char(); }
          self.input.shift_char();

          /* Look for the function in the cached map. */
          match self.activator.functions.find(&func)
          {
            Some(f) =>
            {
              let input = self.input.clone();
              match (*f)(func, input)
              {
                Some(err) => { self.add_log(err); }
                None => { }
              }
            }
            None => { self.add_log("Error: Invalid function"); }
          }

          self.input = ~"";
          return true;
        }
        else if key == glfw::KEY_BACKSPACE
        {
          if self.input.len() > 0
          { self.input.pop_char(); }
          return true;
        }
        /* Non-whitespace. */
        else if key >= 32 && key <= 93
        {
          /* This will be handled when we receive it as a char. */
          return true;
        }
      }
    }

    false

  }

  pub fn key_char(&mut self, ch: char) -> bool
  {
    /* Check if the console is enabled. */
    if self.velocity > 0.0
    {
      /* Non-whitespace and not ` or ~ */
      if ch >= 0x20 as char && ch <= 0x7D as char && ch != 0x60 as char
      {
        self.input.push_char(ch);
        return true;
      }
    }

    false
  }
}

<commit_msg> #5 Crash no longer happes with invalid get/set<commit_after>/*
    Copyright 2013 Jesse 'Jeaye' Wilkerson
    See licensing in LICENSE file, or at:
        http://www.opensource.org/licenses/BSD-3-Clause

    File: state/console/console.rs
    Author: Jesse 'Jeaye' Wilkerson
    Description:
      Manages the model portion
      of the in-game console.
*/

use glfw;
use ui;
use math;
use super::State;
use util::Log;

#[macro_escape]
#[path = "../../util/log_macros.rs"]
mod log_macros;

struct Console
{
  activator: @mut ui::Console_Activator,

  position: math::Vec2f,
  velocity: f32, /* On the Y axis only. */

  body: ~str,
  prefix: ~str,
  input: ~str,
}

impl Console
{
  pub fn new() -> @mut Console
  {
    let c = @mut Console
    {
      activator: ui::Console_Activator::new(),

      position: math::Vec2f::zero(),
      velocity: 300.0,

      body: fmt!("Welcome to Q^3\nVersion: %s.%s", env!("VERSION"), env!("COMMIT")),
      prefix: ~"> ",
      input: ~"",
    };

    /* The 'get' and 'set' functions are built in to the console. */
    c.activator.functions.insert(~"get",
    |_get, property| -> Option<~str>
    {
      let mut err = ~"";

      /* Check if this property exists. */
      match c.activator.accessors.find(&property.to_owned())
      {
        Some(func) =>
        { c.add_log(fmt!("%s = %s", property, (*func)(property))); }
        None =>
        { err = fmt!("Error: Invalid property '%s'", property); }
      }

      if err.len() == 0
      { None }
      else
      { Some(err) }
    });

    c.activator.functions.insert(~"set",
    |_set, params| -> Option<~str>
    {
      let mut error = ~"";
      let mut property = ~"";
      let mut params = params.to_owned();
      for x in params.split_iter(' ')
      { property = x.to_owned(); break; }

      /* We require a property and a value.
       * Remove the property from the string.
       */
      for _ in property.iter()
      { params.shift_char(); }
      if params.len() > 0
      { params.shift_char(); }

      /* Check if this property exists. */
      match c.activator.mutators.find(&property)
      {
        Some(func) =>
        {
          /* Pass the args to the property mutator. */
          match (*func)(property, params)
          {
            /* Check if the mutator liked the args. */
            Some(err) => { error = err; }
            None => { }
          }
        }
        None => { error = fmt!("The property '%s' does not exist.", property); }
      }

      if error.len() > 0
      { Some(fmt!("Error: %s", error)) }
      else
      { None }
    });

    c
  }

  pub fn add_log(&mut self, text: &str)
  { self.body.push_str("\n" + text); }
}

impl State for Console
{
  pub fn load(&mut self)
  { log_debug!("Loading console state."); }

  pub fn unload(&mut self)
  { log_debug!("Unloading console state."); }

  pub fn update(&mut self, _delta: f32) -> bool /* dt is in terms of seconds. */
  { false }

  pub fn render(&mut self) -> bool
  { false }

  pub fn key_action(&mut self, key: i32, action: i32, _mods: i32) -> bool
  {
    if action == glfw::PRESS || action == glfw::REPEAT
    {
      /* Mac grave is world 1 for some reason. */
      if key == glfw::KEY_GRAVE_ACCENT || key == glfw::KEY_WORLD_1
      {
        self.velocity *= -1.0;
        return true;
      }

      /* The following only apply if the console is enabled. */
      if self.velocity > 0.0
      {
        if key == glfw::KEY_ENTER
        {
          if self.input.len() == 0
          { return true; }

          /* Extract the function name. */
          let mut func = ~"";
          for x in self.input.split_iter(' ')
          { func = x.to_owned(); break; };

          /* Remove the function from the string. */
          for _ in func.iter()
          { self.input.shift_char(); }
          if self.input.len() > 0
          { self.input.shift_char(); }

          /* Look for the function in the cached map. */
          match self.activator.functions.find(&func)
          {
            Some(f) =>
            {
              let input = self.input.clone();
              match (*f)(func, input)
              {
                Some(err) => { self.add_log(err); }
                None => { }
              }
            }
            None => { self.add_log("Error: Invalid function"); }
          }

          self.input.clear();
          return true;
        }
        else if key == glfw::KEY_BACKSPACE
        {
          if self.input.len() > 0
          { self.input.pop_char(); }
          return true;
        }
        /* Non-whitespace. */
        else if key >= 32 && key <= 93
        {
          /* This will be handled when we receive it as a char. */
          return true;
        }
      }
    }

    false

  }

  pub fn key_char(&mut self, ch: char) -> bool
  {
    /* Check if the console is enabled. */
    if self.velocity > 0.0
    {
      /* Non-whitespace and not ` or ~ */
      if ch >= 0x20 as char && ch <= 0x7D as char && ch != 0x60 as char
      {
        self.input.push_char(ch);
        return true;
      }
    }

    false
  }
}

<|endoftext|>


<commit_before>//! Provides a macro for creating an rpc service and client stub.
//! Ex:
//! ```
//! #[macro_use]
//! extern crate tarpc_macros;
//!
//! rpc_service!(my_server:
//!     hello(name: String) -> String;
//!     add(x: i32, y: i32) -> i32;
//! );
//!
//! use self::my_server::*;
//!
//! impl my_server::Service for () {
//!     fn hello(&self, s: String) -> Foo {
//!         format!("Hello, {}!", s)
//!     }
//!     fn add(&self, x: i32, y: i32) -> i32 {
//!         x + y
//!     }
//! }
//!
//! fn main() {
//!     let addr = "127.0.0.1:9000";
//!     let shutdown = my_server::serve(addr, ()).unwrap();
//!     let client = Client::new(addr).unwrap();
//!     assert_eq!(3, client.add(1, 2).unwrap());
//!     assert_eq!("Hello, Mom!".into(), client.hello("Mom").unwrap());
//!     drop(client);
//!     shutdown.shutdown();
//! }
//! ```
#![feature(concat_idents, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate tarpc;
#[macro_use]
extern crate log;

#[macro_export]
macro_rules! rpc_service { ($server:ident:
    $( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;)*) => {
        mod $server {
            use std::net::{
                TcpStream,
                ToSocketAddrs,
            };
            use std::io;
            use std::sync::Arc;
            use tarpc::{
                self,
                Shutdown,
                serve_async,
            };

            #[doc="An RPC error that occurred during serving an RPC request."]
            #[derive(Debug)]
            pub enum Error {
                #[doc="An IO error occurred."]
                Io(io::Error),

                #[doc="An unexpected internal error. Typically a bug in the server impl."]
                InternalError,
            }

            impl ::std::convert::From<tarpc::Error> for Error {
                fn from(err: tarpc::Error) -> Error {
                    match err {
                        tarpc::Error::Io(err) => Error::Io(err),
                        _ => Error::InternalError,
                    }
                }
            }

            impl ::std::convert::From<io::Error> for Error {
                fn from(err: io::Error) -> Error {
                    Error::Io(err)
                }
            }

            #[doc="The result of an RPC call; either the successful result or the error."]
            pub type Result<T> = ::std::result::Result<T, Error>;

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Request {
                $(
                    $fn_name($($in_),*),
                )*
            }

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Reply {
                $(
                    $fn_name($out),
                )*
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client(tarpc::Client<Request, Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A) -> Result<Self>
                    where A: ToSocketAddrs,
                {
                    let stream = try!(TcpStream::connect(addr));
                    let inner = try!(tarpc::Client::new(stream));
                    Ok(Client(inner))
                }

                $(
                    pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
                        let reply = try!((self.0).rpc(&Request::$fn_name($($arg),*)));
                        match reply {
                            Reply::$fn_name(reply) => Ok(reply),
                            _ => Err(Error::InternalError),
                        }
                    }
                )*
            }

            struct Server<S: 'static + Service>(S);

            impl<S> tarpc::Serve<Request, Reply> for Server<S>
                where S: 'static + Service
            {
                fn serve(&self, request: Request) -> Reply {
                    match request {
                        $(
                            Request::$fn_name($($arg),*) =>
                                Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A, service: S) -> Result<Shutdown>
                where A: ToSocketAddrs,
                      S: 'static + Service
            {
                let server = Arc::new(Server(service));
                Ok(try!(serve_async(addr, server)))
            }
        }
    }
}

#[cfg(test)]
mod test {

    rpc_service!(my_server:
        hello(foo: super::Foo) -> super::Foo;

        add(x: i32, y: i32) -> i32;
    );

    use self::my_server::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    pub struct Foo {
        message: String
    }

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo{message: format!("Hello, {}", &s.message)}
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, ()).unwrap();
        let client = Client::new(addr).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo{message: "Adam".into()};
        let want = Foo{message: format!("Hello, {}", &foo.message)};
        assert_eq!(want, client.hello(Foo{message: "Adam".into()}).unwrap());
        drop(client);
        shutdown.shutdown();
    }
}
<commit_msg>Generate an unused enum variant to fix a compiler error<commit_after>//! Provides a macro for creating an rpc service and client stub.
//! Ex:
//! ```
//! #[macro_use]
//! extern crate tarpc_macros;
//!
//! rpc_service!(my_server:
//!     hello(name: String) -> String;
//!     add(x: i32, y: i32) -> i32;
//! );
//!
//! use self::my_server::*;
//!
//! impl my_server::Service for () {
//!     fn hello(&self, s: String) -> Foo {
//!         format!("Hello, {}!", s)
//!     }
//!     fn add(&self, x: i32, y: i32) -> i32 {
//!         x + y
//!     }
//! }
//!
//! fn main() {
//!     let addr = "127.0.0.1:9000";
//!     let shutdown = my_server::serve(addr, ()).unwrap();
//!     let client = Client::new(addr).unwrap();
//!     assert_eq!(3, client.add(1, 2).unwrap());
//!     assert_eq!("Hello, Mom!".into(), client.hello("Mom").unwrap());
//!     drop(client);
//!     shutdown.shutdown();
//! }
//! ```
#![feature(concat_idents, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate tarpc;
#[macro_use]
extern crate log;

#[macro_export]
macro_rules! rpc_service { ($server:ident:
    $( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;)*) => {
        #[allow(dead_code)]
        mod $server {
            use std::net::{
                TcpStream,
                ToSocketAddrs,
            };
            use std::io;
            use std::sync::Arc;
            use tarpc::{
                self,
                Shutdown,
                serve_async,
            };

            #[doc="An RPC error that occurred during serving an RPC request."]
            #[derive(Debug)]
            pub enum Error {
                #[doc="An IO error occurred."]
                Io(io::Error),

                #[doc="An unexpected internal error. Typically a bug in the server impl."]
                InternalError,
            }

            impl ::std::convert::From<tarpc::Error> for Error {
                fn from(err: tarpc::Error) -> Error {
                    match err {
                        tarpc::Error::Io(err) => Error::Io(err),
                        _ => Error::InternalError,
                    }
                }
            }

            impl ::std::convert::From<io::Error> for Error {
                fn from(err: io::Error) -> Error {
                    Error::Io(err)
                }
            }

            #[doc="The result of an RPC call; either the successful result or the error."]
            pub type Result<T> = ::std::result::Result<T, Error>;

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Request {
                $(
                    $fn_name($($in_),*),
                )*
            }

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum Reply {
                $(
                    $fn_name($out),
                )*
                Impossible,
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client(tarpc::Client<Request, Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A) -> Result<Self>
                    where A: ToSocketAddrs,
                {
                    let stream = try!(TcpStream::connect(addr));
                    let inner = try!(tarpc::Client::new(stream));
                    Ok(Client(inner))
                }

                $(
                    pub fn $fn_name(&self, $($arg: $in_),*) -> Result<$out> {
                        let reply = try!((self.0).rpc(&Request::$fn_name($($arg),*)));
                        if let Reply::$fn_name(reply) = reply {
                            Ok(reply)
                        } else {
                            Err(Error::InternalError)
                        }
                    }
                )*
            }

            struct Server<S: 'static + Service>(S);

            impl<S> tarpc::Serve<Request, Reply> for Server<S>
                where S: 'static + Service
            {
                fn serve(&self, request: Request) -> Reply {
                    match request {
                        $(
                            Request::$fn_name($($arg),*) =>
                                Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A, service: S) -> Result<Shutdown>
                where A: ToSocketAddrs,
                      S: 'static + Service
            {
                let server = Arc::new(Server(service));
                Ok(try!(serve_async(addr, server)))
            }
        }
    }
}

#[cfg(test)]
mod test {

    rpc_service!(my_server:
        hello(foo: super::Foo) -> super::Foo;

        add(x: i32, y: i32) -> i32;
    );

    use self::my_server::*;

    #[derive(PartialEq, Debug, Serialize, Deserialize)]
    pub struct Foo {
        message: String
    }

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo{message: format!("Hello, {}", &s.message)}
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, ()).unwrap();
        let client = Client::new(addr).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo{message: "Adam".into()};
        let want = Foo{message: format!("Hello, {}", &foo.message)};
        assert_eq!(want, client.hello(Foo{message: "Adam".into()}).unwrap());
        drop(client);
        shutdown.shutdown();
    }
}
<|endoftext|>


<commit_before>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

#[derive(Debug)]
pub struct Block {
  pub is_last: bool,
  pub length: u32,
  pub data: BlockData,
}

#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  StreamInfo(StreamInfo),
  Padding(u32),
  Application(Application),
  SeekTable(Vec<SeekPoint>),
  VorbisComment(VorbisComment),
  CueSheet(CueSheet),
  Picture(Picture),
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  pub min_block_size: u16,
  pub max_block_size: u16,
  pub min_frame_size: u32,
  pub max_frame_size: u32,
  pub sample_rate: u32,
  pub channels: u8,
  pub bits_per_sample: u8,
  pub total_samples: u64,
  pub md5_sum: Vec<u8>,
}

/// Data used by third-party applications
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  pub id: String,
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  pub sample_number: u64,
  pub stream_offset: u64,
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  pub vendor_string: String,
  pub comments: Vec<String>,
}

/// Stores cue information
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with a FLAC file
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<commit_msg>Change comments within VorbisComment to a HashMap<commit_after>use std::collections::HashMap;
use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

#[derive(Debug)]
pub struct Block {
  pub is_last: bool,
  pub length: u32,
  pub data: BlockData,
}

#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  StreamInfo(StreamInfo),
  Padding(u32),
  Application(Application),
  SeekTable(Vec<SeekPoint>),
  VorbisComment(VorbisComment),
  CueSheet(CueSheet),
  Picture(Picture),
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  pub min_block_size: u16,
  pub max_block_size: u16,
  pub min_frame_size: u32,
  pub max_frame_size: u32,
  pub sample_rate: u32,
  pub channels: u8,
  pub bits_per_sample: u8,
  pub total_samples: u64,
  pub md5_sum: Vec<u8>,
}

/// Data used by third-party applications
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  pub id: String,
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  pub sample_number: u64,
  pub stream_offset: u64,
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  pub vendor_string: String,
  pub comments: HashMap<String, String>,
}

/// Stores cue information
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with a FLAC file
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<|endoftext|>


<commit_before>use chrono::NaiveDateTime;
use diesel::prelude::*;

use crate::models::Crate;
use crate::schema::*;
use crate::sql::lower;

#[derive(Clone, Identifiable, Queryable, Debug)]
pub struct Keyword {
    pub id: i32,
    pub keyword: String,
    pub crates_cnt: i32,
    pub created_at: NaiveDateTime,
}

#[derive(Associations, Insertable, Identifiable, Debug, Clone, Copy)]
#[belongs_to(Keyword)]
#[belongs_to(Crate)]
#[table_name = "crates_keywords"]
#[primary_key(crate_id, keyword_id)]
pub struct CrateKeyword {
    crate_id: i32,
    keyword_id: i32,
}

impl Keyword {
    pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult<Keyword> {
        keywords::table
            .filter(keywords::keyword.eq(lower(name)))
            .first(&*conn)
    }

    pub fn find_or_create_all(conn: &PgConnection, names: &[&str]) -> QueryResult<Vec<Keyword>> {
        use diesel::dsl::any;

        let lowercase_names: Vec<_> = names.iter().map(|s| s.to_lowercase()).collect();

        let new_keywords: Vec<_> = lowercase_names
            .iter()
            .map(|s| keywords::keyword.eq(s))
            .collect();

        diesel::insert_into(keywords::table)
            .values(&new_keywords)
            .on_conflict_do_nothing()
            .execute(conn)?;
        keywords::table
            .filter(keywords::keyword.eq(any(&lowercase_names)))
            .load(conn)
    }

    pub fn valid_name(name: &str) -> bool {
        if name.is_empty() {
            return false;
        }
        // unwrap is okay because name is non-empty
        name.chars().next().unwrap().is_alphanumeric()
            && name
                .chars()
                .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
            && name.chars().all(|c| c.is_ascii())
    }

    pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> {
        conn.transaction(|| {
            let keywords = Keyword::find_or_create_all(conn, keywords)?;
            diesel::delete(CrateKeyword::belonging_to(krate)).execute(conn)?;
            let crate_keywords = keywords
                .into_iter()
                .map(|kw| CrateKeyword {
                    crate_id: krate.id,
                    keyword_id: kw.id,
                })
                .collect::<Vec<_>>();
            diesel::insert_into(crates_keywords::table)
                .values(&crate_keywords)
                .execute(conn)?;
            Ok(())
        })
    }
}

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

    fn pg_connection() -> PgConnection {
        let database_url =
            dotenv::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set to run tests");
        let conn = PgConnection::establish(&database_url).unwrap();
        // These tests deadlock if run concurrently
        conn.batch_execute("BEGIN;").unwrap();
        conn
    }

    #[test]
    fn dont_associate_with_non_lowercased_keywords() {
        let conn = pg_connection();
        // The code should be preventing lowercased keywords from existing,
        // but if one happens to sneak in there, don't associate crates with it.

        diesel::insert_into(keywords::table)
            .values(keywords::keyword.eq("NO"))
            .execute(&conn)
            .unwrap();

        let associated = Keyword::find_or_create_all(&conn, &["no"]).unwrap();
        assert_eq!(associated.len(), 1);
        assert_eq!(associated.first().unwrap().keyword, "no");
    }
}
<commit_msg>Replace is_alphanumeric + is_ascii with is_ascii_alphanumeric (#5032)<commit_after>use chrono::NaiveDateTime;
use diesel::prelude::*;

use crate::models::Crate;
use crate::schema::*;
use crate::sql::lower;

#[derive(Clone, Identifiable, Queryable, Debug)]
pub struct Keyword {
    pub id: i32,
    pub keyword: String,
    pub crates_cnt: i32,
    pub created_at: NaiveDateTime,
}

#[derive(Associations, Insertable, Identifiable, Debug, Clone, Copy)]
#[belongs_to(Keyword)]
#[belongs_to(Crate)]
#[table_name = "crates_keywords"]
#[primary_key(crate_id, keyword_id)]
pub struct CrateKeyword {
    crate_id: i32,
    keyword_id: i32,
}

impl Keyword {
    pub fn find_by_keyword(conn: &PgConnection, name: &str) -> QueryResult<Keyword> {
        keywords::table
            .filter(keywords::keyword.eq(lower(name)))
            .first(&*conn)
    }

    pub fn find_or_create_all(conn: &PgConnection, names: &[&str]) -> QueryResult<Vec<Keyword>> {
        use diesel::dsl::any;

        let lowercase_names: Vec<_> = names.iter().map(|s| s.to_lowercase()).collect();

        let new_keywords: Vec<_> = lowercase_names
            .iter()
            .map(|s| keywords::keyword.eq(s))
            .collect();

        diesel::insert_into(keywords::table)
            .values(&new_keywords)
            .on_conflict_do_nothing()
            .execute(conn)?;
        keywords::table
            .filter(keywords::keyword.eq(any(&lowercase_names)))
            .load(conn)
    }

    pub fn valid_name(name: &str) -> bool {
        if name.is_empty() {
            return false;
        }
        // unwrap is okay because name is non-empty
        name.chars().next().unwrap().is_ascii_alphanumeric()
            && name
                .chars()
                .all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
    }

    pub fn update_crate(conn: &PgConnection, krate: &Crate, keywords: &[&str]) -> QueryResult<()> {
        conn.transaction(|| {
            let keywords = Keyword::find_or_create_all(conn, keywords)?;
            diesel::delete(CrateKeyword::belonging_to(krate)).execute(conn)?;
            let crate_keywords = keywords
                .into_iter()
                .map(|kw| CrateKeyword {
                    crate_id: krate.id,
                    keyword_id: kw.id,
                })
                .collect::<Vec<_>>();
            diesel::insert_into(crates_keywords::table)
                .values(&crate_keywords)
                .execute(conn)?;
            Ok(())
        })
    }
}

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

    fn pg_connection() -> PgConnection {
        let database_url =
            dotenv::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set to run tests");
        let conn = PgConnection::establish(&database_url).unwrap();
        // These tests deadlock if run concurrently
        conn.batch_execute("BEGIN;").unwrap();
        conn
    }

    #[test]
    fn dont_associate_with_non_lowercased_keywords() {
        let conn = pg_connection();
        // The code should be preventing lowercased keywords from existing,
        // but if one happens to sneak in there, don't associate crates with it.

        diesel::insert_into(keywords::table)
            .values(keywords::keyword.eq("NO"))
            .execute(&conn)
            .unwrap();

        let associated = Keyword::find_or_create_all(&conn, &["no"]).unwrap();
        assert_eq!(associated.len(), 1);
        assert_eq!(associated.first().unwrap().keyword, "no");
    }
}
<|endoftext|>


<commit_before>//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a
//! separate file because there's both a large number of them, and not all tests
//! can be run on Android. This is because in Android `log2` uses an imprecise
//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53

#[test]
fn checked_log() {
    assert_eq!(999u32.checked_log(10), Some(2));
    assert_eq!(1000u32.checked_log(10), Some(3));
    assert_eq!(555u32.checked_log(13), Some(2));
    assert_eq!(63u32.checked_log(4), Some(2));
    assert_eq!(64u32.checked_log(4), Some(3));
    assert_eq!(10460353203u64.checked_log(3), Some(21));
    assert_eq!(10460353202u64.checked_log(3), Some(20));
    assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80));
    assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79));
    assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8));
    assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7));

    assert_eq!(0u8.checked_log(4), None);
    assert_eq!(0u16.checked_log(4), None);
    assert_eq!(0i8.checked_log(4), None);
    assert_eq!(0i16.checked_log(4), None);

    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log(4), None);
    }
    for i in 1..=i16::MAX {
        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
    }
    for i in 1..=u16::MAX {
        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
    }
}

#[test]
fn checked_log2() {
    assert_eq!(5u32.checked_log2(), Some(2));
    assert_eq!(0u64.checked_log2(), None);
    assert_eq!(128i32.checked_log2(), Some(7));
    assert_eq!((-55i16).checked_log2(), None);

    assert_eq!(0u8.checked_log2(), None);
    assert_eq!(0u16.checked_log2(), None);
    assert_eq!(0i8.checked_log2(), None);
    assert_eq!(0i16.checked_log2(), None);

    for i in 1..=u8::MAX {
        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
    }
    for i in 1..=u16::MAX {
        // Guard against Android's imprecise f32::log2 implementation.
        if i != 8192 && i != 32768 {
            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
        }
    }
    for i in i8::MIN..=0 {
        assert_eq!(i.checked_log2(), None);
    }
    for i in 1..=i8::MAX {
        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
    }
    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log2(), None);
    }
    for i in 1..=i16::MAX {
        // Guard against Android's imprecise f32::log2 implementation.
        if i != 8192 {
            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
        }
    }
}

// Validate cases that fail on Android's imprecise float log2 implementation.
#[test]
#[cfg(not(target_os = "android"))]
fn checked_log2_not_android() {
    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
}

#[test]
fn checked_log10() {
    assert_eq!(0u8.checked_log10(), None);
    assert_eq!(0u16.checked_log10(), None);
    assert_eq!(0i8.checked_log10(), None);
    assert_eq!(0i16.checked_log10(), None);

    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log10(), None);
    }
    for i in 1..=i16::MAX {
        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
    }
    for i in 1..=u16::MAX {
        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
    }
}
<commit_msg>test integer log10 values close to all powers of 10<commit_after>//! This tests the `Integer::{log,log2,log10}` methods. These tests are in a
//! separate file because there's both a large number of them, and not all tests
//! can be run on Android. This is because in Android `log2` uses an imprecise
//! approximation:https://github.com/rust-lang/rust/blob/4825e12fc9c79954aa0fe18f5521efa6c19c7539/src/libstd/sys/unix/android.rs#L27-L53

#[test]
fn checked_log() {
    assert_eq!(999u32.checked_log(10), Some(2));
    assert_eq!(1000u32.checked_log(10), Some(3));
    assert_eq!(555u32.checked_log(13), Some(2));
    assert_eq!(63u32.checked_log(4), Some(2));
    assert_eq!(64u32.checked_log(4), Some(3));
    assert_eq!(10460353203u64.checked_log(3), Some(21));
    assert_eq!(10460353202u64.checked_log(3), Some(20));
    assert_eq!(147808829414345923316083210206383297601u128.checked_log(3), Some(80));
    assert_eq!(147808829414345923316083210206383297600u128.checked_log(3), Some(79));
    assert_eq!(22528399544939174411840147874772641u128.checked_log(19683), Some(8));
    assert_eq!(22528399544939174411840147874772631i128.checked_log(19683), Some(7));

    assert_eq!(0u8.checked_log(4), None);
    assert_eq!(0u16.checked_log(4), None);
    assert_eq!(0i8.checked_log(4), None);
    assert_eq!(0i16.checked_log(4), None);

    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log(4), None);
    }
    for i in 1..=i16::MAX {
        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
    }
    for i in 1..=u16::MAX {
        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
    }
}

#[test]
fn checked_log2() {
    assert_eq!(5u32.checked_log2(), Some(2));
    assert_eq!(0u64.checked_log2(), None);
    assert_eq!(128i32.checked_log2(), Some(7));
    assert_eq!((-55i16).checked_log2(), None);

    assert_eq!(0u8.checked_log2(), None);
    assert_eq!(0u16.checked_log2(), None);
    assert_eq!(0i8.checked_log2(), None);
    assert_eq!(0i16.checked_log2(), None);

    for i in 1..=u8::MAX {
        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
    }
    for i in 1..=u16::MAX {
        // Guard against Android's imprecise f32::log2 implementation.
        if i != 8192 && i != 32768 {
            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
        }
    }
    for i in i8::MIN..=0 {
        assert_eq!(i.checked_log2(), None);
    }
    for i in 1..=i8::MAX {
        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
    }
    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log2(), None);
    }
    for i in 1..=i16::MAX {
        // Guard against Android's imprecise f32::log2 implementation.
        if i != 8192 {
            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
        }
    }
}

// Validate cases that fail on Android's imprecise float log2 implementation.
#[test]
#[cfg(not(target_os = "android"))]
fn checked_log2_not_android() {
    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
}

#[test]
fn checked_log10() {
    assert_eq!(0u8.checked_log10(), None);
    assert_eq!(0u16.checked_log10(), None);
    assert_eq!(0i8.checked_log10(), None);
    assert_eq!(0i16.checked_log10(), None);

    for i in i16::MIN..=0 {
        assert_eq!(i.checked_log10(), None);
    }
    for i in 1..=i16::MAX {
        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
    }
    for i in 1..=u16::MAX {
        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
    }
}

macro_rules! log10_loop {
    ($T:ty, $log10_max:expr) => {
        assert_eq!(<$T>::MAX.log10(), $log10_max);
        for i in 0..=$log10_max {
            let p = (10 as $T).pow(i as u32);
            if p >= 10 {
                assert_eq!((p - 9).log10(), i - 1);
                assert_eq!((p - 1).log10(), i - 1);
            }
            assert_eq!(p.log10(), i);
            assert_eq!((p + 1).log10(), i);
            if p >= 10 {
                assert_eq!((p + 9).log10(), i);
            }

            // also check `x.log(10)`
            if p >= 10 {
                assert_eq!((p - 9).log(10), i - 1);
                assert_eq!((p - 1).log(10), i - 1);
            }
            assert_eq!(p.log(10), i);
            assert_eq!((p + 1).log(10), i);
            if p >= 10 {
                assert_eq!((p + 9).log(10), i);
            }
        }
    };
}

#[test]
fn log10_u8() {
    log10_loop! { u8, 2 }
}

#[test]
fn log10_u16() {
    log10_loop! { u16, 4 }
}

#[test]
fn log10_u32() {
    log10_loop! { u32, 9 }
}

#[test]
fn log10_u64() {
    log10_loop! { u64, 19 }
}

#[test]
fn log10_u128() {
    log10_loop! { u128, 38 }
}
<|endoftext|>