<commit_before>use std::io::Read;

use types::{Result, Dimensions};
use common::riff::{RiffReader, RiffChunk, ChunkId};
use traits::LoadableMetadata;
use utils::ReadExt;

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Metadata {
    VP8(VP8Metadata),
    VP8L(VP8LMetadata),
    VP8X(VP8XMetadata)
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub struct VP8Metadata {
    pub version_number: u8,
    pub show_frame: bool,
    pub first_partition_len: u32,
    pub frame: VP8Frame
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VP8Frame {
    Key { dimensions: Dimensions, x_scale: u8, y_scale: u8 },
    Inter
}

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

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

const WEBP_CHUNK_TYPE: ChunkId = ChunkId([b'W', b'E', b'B', b'P']);
const ALPH_CHUNK_ID: ChunkId   = ChunkId([b'A', b'L', b'P', b'H']);
const VP8_CHUNK_ID: ChunkId    = ChunkId([b'V', b'P', b'8', b' ']);
const VP8L_CHUNK_ID: ChunkId   = ChunkId([b'V', b'P', b'8', b'L']);
const VP8X_CHUNK_ID: ChunkId   = ChunkId([b'V', b'P', b'8', b'X']);

impl Metadata {
    pub fn dimensions(&self) -> Dimensions {
        match *self {
            Metadata::VP8(VP8Metadata { frame: VP8Frame::Key { dimensions, .. }, .. }) => dimensions,
            _ => unimplemented!()
        }
    }
}

impl LoadableMetadata for Metadata {
    fn load<R: ?Sized + Read>(r: &mut R) -> Result<Metadata> {
        let mut rr = RiffReader::new(r);

        let mut root = try!(rr.root());
        if root.chunk_type() != WEBP_CHUNK_TYPE {
            return Err(invalid_format!("invalid WEBP signature"));
        }

        loop {
            let mut chunk = match root.next() {
                Some(c) => try!(c),
                None => return Err(unexpected_eof!("when reading first WEBP chunk"))
            };

            match chunk.chunk_id() {
                VP8_CHUNK_ID => return read_vp8_chunk(&mut chunk).map(Metadata::VP8),
                VP8L_CHUNK_ID => unimplemented!(),
                VP8X_CHUNK_ID => unimplemented!(),
                ALPH_CHUNK_ID => unimplemented!(),
                cid => return Err(invalid_format!("invalid WEBP chunk id: {}", cid))
            }
        }
    }
}

fn read_vp8_chunk(chunk: &mut RiffChunk) -> Result<VP8Metadata> {
    let r = chunk.contents();

    let mut hdr = [0u8; 3];
    if try!(r.read_exact_0(&mut hdr)) != 3 {
        return Err(unexpected_eof!("when reading VP8 frame header"));
    }

    let mut result = VP8Metadata {
        version_number: 0,
        show_frame: false,
        first_partition_len: 0,
        frame: VP8Frame::Inter
    };

    // bits of first three bytes:
    //    xxxsvvvf xxxxxxxx xxxxxxxx
    // where
    //    f  --  frame type, 0 is key frame, 1 is interframe
    //    v  --  version number
    //    s  --  show frame flag, 1 is display, 0 is don't display
    //    x  --  size of first data partition in bytes

    let key_frame = hdr[0] & 1 == 0;
    result.version_number = (hdr[0] >> 1) & 7;
    result.show_frame = (hdr[0] >> 4) & 1 == 1;
    result.first_partition_len = ((hdr[0] >> 5) as u32) |
                                 ((hdr[1] as u32) << 3) |
                                 ((hdr[2] as u32) << 11);

    if key_frame {
        let mut hdr = [0u8; 7];
        if try!(r.read_exact_0(&mut hdr)) != 7 {
            return Err(unexpected_eof!("when reading VP8 key frame header"));
        }

        // check magic value
        if &hdr[..3] != &[0x9d, 0x01, 0x2a] {
            return Err(invalid_format!("VP8 key frame magic code is invalid: {:?}", &hdr[..3]));
        }

        // bits of next four bytes:
        //    wwwwwwww xxwwwwww hhhhhhhh yyhhhhhh
        // where
        //    x  --  horizontal scale
        //    w  --  width
        //    y  --  vertical scale
        //    h  --  height

        let width  = ((hdr[4] & 0x3f) as u32) << 8 | hdr[3] as u32;
        let height = ((hdr[6] & 0x3f) as u32) << 8 | hdr[5] as u32;
        let x_scale = hdr[4] >> 6;
        let y_scale = hdr[6] >> 6;

        result.frame = VP8Frame::Key {
            dimensions: (width, height).into(),
            x_scale: x_scale,
            y_scale: y_scale
        };
    }

    Ok(result)
}

<commit_msg>Removed stray unimplemented!() macros in favor of errors<commit_after>use std::io::Read;

use types::{Result, Dimensions};
use common::riff::{RiffReader, RiffChunk, ChunkId};
use traits::LoadableMetadata;
use utils::ReadExt;

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Metadata {
    VP8(VP8Metadata),
    VP8L(VP8LMetadata),
    VP8X(VP8XMetadata)
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub struct VP8Metadata {
    pub version_number: u8,
    pub show_frame: bool,
    pub first_partition_len: u32,
    pub frame: VP8Frame
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum VP8Frame {
    Key { dimensions: Dimensions, x_scale: u8, y_scale: u8 },
    Inter
}

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

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

const WEBP_CHUNK_TYPE: ChunkId = ChunkId([b'W', b'E', b'B', b'P']);
const ALPH_CHUNK_ID: ChunkId   = ChunkId([b'A', b'L', b'P', b'H']);
const VP8_CHUNK_ID: ChunkId    = ChunkId([b'V', b'P', b'8', b' ']);
const VP8L_CHUNK_ID: ChunkId   = ChunkId([b'V', b'P', b'8', b'L']);
const VP8X_CHUNK_ID: ChunkId   = ChunkId([b'V', b'P', b'8', b'X']);

impl Metadata {
    pub fn dimensions(&self) -> Dimensions {
        match *self {
            Metadata::VP8(VP8Metadata { frame: VP8Frame::Key { dimensions, .. }, .. }) => dimensions,
            _ => unimplemented!()
        }
    }
}

impl LoadableMetadata for Metadata {
    fn load<R: ?Sized + Read>(r: &mut R) -> Result<Metadata> {
        let mut rr = RiffReader::new(r);

        let mut root = try!(rr.root());
        if root.chunk_type() != WEBP_CHUNK_TYPE {
            return Err(invalid_format!("invalid WEBP signature"));
        }

        loop {
            let mut chunk = match root.next() {
                Some(c) => try!(c),
                None => return Err(unexpected_eof!("when reading first WEBP chunk"))
            };

            match chunk.chunk_id() {
                VP8_CHUNK_ID => return read_vp8_chunk(&mut chunk).map(Metadata::VP8),
                VP8L_CHUNK_ID => return Err(invalid_format!("unsupported (yet) VP8 chunk id")),
                VP8X_CHUNK_ID => return Err(invalid_format!("unsupported (yet) VP8 chunk id")),
                ALPH_CHUNK_ID => return Err(invalid_format!("unsupported (yet) VP8 chunk id")),
                cid => return Err(invalid_format!("invalid WEBP chunk id: {}", cid))
            }
        }
    }
}

fn read_vp8_chunk(chunk: &mut RiffChunk) -> Result<VP8Metadata> {
    let r = chunk.contents();

    let mut hdr = [0u8; 3];
    if try!(r.read_exact_0(&mut hdr)) != 3 {
        return Err(unexpected_eof!("when reading VP8 frame header"));
    }

    let mut result = VP8Metadata {
        version_number: 0,
        show_frame: false,
        first_partition_len: 0,
        frame: VP8Frame::Inter
    };

    // bits of first three bytes:
    //    xxxsvvvf xxxxxxxx xxxxxxxx
    // where
    //    f  --  frame type, 0 is key frame, 1 is interframe
    //    v  --  version number
    //    s  --  show frame flag, 1 is display, 0 is don't display
    //    x  --  size of first data partition in bytes

    let key_frame = hdr[0] & 1 == 0;
    result.version_number = (hdr[0] >> 1) & 7;
    result.show_frame = (hdr[0] >> 4) & 1 == 1;
    result.first_partition_len = ((hdr[0] >> 5) as u32) |
                                 ((hdr[1] as u32) << 3) |
                                 ((hdr[2] as u32) << 11);

    if key_frame {
        let mut hdr = [0u8; 7];
        if try!(r.read_exact_0(&mut hdr)) != 7 {
            return Err(unexpected_eof!("when reading VP8 key frame header"));
        }

        // check magic value
        if &hdr[..3] != &[0x9d, 0x01, 0x2a] {
            return Err(invalid_format!("VP8 key frame magic code is invalid: {:?}", &hdr[..3]));
        }

        // bits of next four bytes:
        //    wwwwwwww xxwwwwww hhhhhhhh yyhhhhhh
        // where
        //    x  --  horizontal scale
        //    w  --  width
        //    y  --  vertical scale
        //    h  --  height

        let width  = ((hdr[4] & 0x3f) as u32) << 8 | hdr[3] as u32;
        let height = ((hdr[6] & 0x3f) as u32) << 8 | hdr[5] as u32;
        let x_scale = hdr[4] >> 6;
        let y_scale = hdr[6] >> 6;

        result.frame = VP8Frame::Key {
            dimensions: (width, height).into(),
            x_scale: x_scale,
            y_scale: y_scale
        };
    }

    Ok(result)
}

<|endoftext|>


<commit_before>use std::sync::Arc;
use std::time::Duration;

use grpcio::{ChannelBuilder, Environment};
use kvproto::{kvrpcpb::*, tikvpb::TikvClient};
use test_raftstore::*;
use tikv_util::{collections::HashMap, HandyRwLock};

// In theory, raft can propose conf change as long as there is no pending one. Replicas
// don't apply logs synchronously, so it's possible the old leader is removed before the new
// leader applies all logs.
// In the current implementation, the new leader rejects conf change until it applies all logs.
// It guarantees the correctness of green GC. This test is to prevent breaking it in the
// future.
#[test]
fn test_collect_lock_from_stale_leader() {
    let mut cluster = new_server_cluster(0, 2);
    cluster.pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    let leader = cluster.leader_of_region(region_id).unwrap();

    // Create clients.
    let env = Arc::new(Environment::new(1));
    let mut clients = HashMap::default();
    for node_id in cluster.get_node_ids() {
        let channel =
            ChannelBuilder::new(Arc::clone(&env)).connect(cluster.sim.rl().get_addr(node_id));
        let client = TikvClient::new(channel);
        clients.insert(node_id, client);
    }

    // Start transferring the region to store 2.
    let new_peer = new_peer(2, 1003);
    cluster.pd_client.must_add_peer(region_id, new_peer.clone());

    // Create the ctx of the first region.
    let leader_client = clients.get(&leader.get_store_id()).unwrap();
    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader.clone());
    ctx.set_region_epoch(cluster.get_region_epoch(region_id));

    // Pause the new peer applying so that when it becomes the leader, it doesn't apply all logs.
    let new_leader_apply_fp = "on_handle_apply_1003";
    fail::cfg(new_leader_apply_fp, "pause").unwrap();
    must_kv_prewrite(
        leader_client,
        ctx,
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );

    // Leader election only considers the progress of appending logs, so it can succeed.
    cluster.must_transfer_leader(region_id, new_peer.clone());
    // It shouldn't succeed in the current implementation.
    cluster.pd_client.remove_peer(region_id, leader.clone());
    std::thread::sleep(Duration::from_secs(1));
    cluster.pd_client.must_have_peer(region_id, leader);

    // Must scan the lock from the old leader.
    let locks = must_physical_scan_lock(leader_client, Context::default(), 100, b"", 10);
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), b"k1");

    // Can't scan the lock from the new leader.
    let leader_client = clients.get(&new_peer.get_store_id()).unwrap();
    must_register_lock_observer(leader_client, 100);
    let locks = must_check_lock_observer(leader_client, 100, true);
    assert!(locks.is_empty());
    let locks = must_physical_scan_lock(leader_client, Context::default(), 100, b"", 10);
    assert!(locks.is_empty());

    fail::remove(new_leader_apply_fp);
}

#[test]
fn test_observer_send_error() {
    let (_cluster, client, ctx) = must_new_cluster_and_kv_client();

    let max_ts = 100;
    must_register_lock_observer(&client, max_ts);
    must_kv_prewrite(
        &client,
        ctx.clone(),
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );
    assert_eq!(must_check_lock_observer(&client, max_ts, true).len(), 1);

    let observer_send_fp = "lock_observer_send";
    fail::cfg(observer_send_fp, "return").unwrap();
    must_kv_prewrite(
        &client,
        ctx,
        vec![new_mutation(Op::Put, b"k2", b"v")],
        b"k1".to_vec(),
        10,
    );
    let resp = check_lock_observer(&client, max_ts);
    assert!(resp.get_error().is_empty(), "{:?}", resp.get_error());
    // Should mark dirty if fails to send locks.
    assert!(!resp.get_is_clean());
}

#[test]
fn test_notify_observer_after_apply() {
    let (mut cluster, client, ctx) = must_new_cluster_and_kv_client();
    let post_apply_query_fp = "notify_lock_observer_query";
    let apply_plain_kvs_fp = "notify_lock_observer_snapshot";

    // Write a lock and pause before notifying the lock observer.
    let max_ts = 100;
    must_register_lock_observer(&client, max_ts);
    fail::cfg(post_apply_query_fp, "pause").unwrap();
    let key = b"k";
    let (client_clone, ctx_clone) = (client.clone(), ctx.clone());
    std::thread::spawn(move || {
        must_kv_prewrite(
            &client_clone,
            ctx_clone,
            vec![new_mutation(Op::Put, key, b"v")],
            key.to_vec(),
            10,
        );
    });
    // We can use physical_scan_lock to get the lock because we notify the lock observer after writing data to the rocskdb.
    let mut locks = vec![];
    for _ in 1..100 {
        sleep_ms(10);
        assert!(must_check_lock_observer(&client, max_ts, true).is_empty());
        locks.extend(must_physical_scan_lock(
            &client,
            ctx.clone(),
            max_ts,
            b"",
            100,
        ));
        if !locks.is_empty() {
            break;
        }
    }
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), key);
    fail::remove(post_apply_query_fp);
    assert_eq!(must_check_lock_observer(&client, max_ts, true).len(), 1);

    // Add a new store.
    let store_id = cluster.add_new_engine();
    let channel = ChannelBuilder::new(Arc::new(Environment::new(1)))
        .connect(cluster.sim.rl().get_addr(store_id));
    let replica_client = TikvClient::new(channel);

    // Add a new peer and pause before notifying the lock observer.
    must_register_lock_observer(&replica_client, max_ts);
    fail::cfg(apply_plain_kvs_fp, "pause").unwrap();
    cluster
        .pd_client
        .must_add_peer(ctx.get_region_id(), new_peer(store_id, store_id));
    // We can use physical_scan_lock to get the lock because we notify the lock observer after writing data to the rocskdb.
    let mut locks = vec![];
    for _ in 1..100 {
        sleep_ms(10);
        assert!(must_check_lock_observer(&replica_client, max_ts, true).is_empty());
        locks.extend(must_physical_scan_lock(
            &replica_client,
            ctx.clone(),
            max_ts,
            b"",
            100,
        ));
        if !locks.is_empty() {
            break;
        }
    }
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), key);
    fail::remove(apply_plain_kvs_fp);
    assert_eq!(
        must_check_lock_observer(&replica_client, max_ts, true).len(),
        1
    );
}

// It may cause locks missing during green GC if the raftstore notifies the lock observer before writing data to the rocksdb:
//   1. Store-1 transfers a region to store-2 and store-2 is applying logs.
//   2. GC worker registers lock observer on store-2 after calling lock observer's callback and before finishing applying which means the lock won't be observed.
//   3. GC worker scans locks on each store independently. It's possible GC worker has scanned all locks on store-2 and hasn't scanned locks on store-1.
//   4. Store-2 applies all logs and removes the peer on store-1.
//   5. GC worker can't scan the lock on store-1 because the peer has been destroyed.
//   6. GC worker can't get the lock from store-2 because it can't observe the lock and has scanned it.
#[test]
fn test_collect_applying_locks() {
    let mut cluster = new_server_cluster(0, 2);
    cluster.pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    let leader = cluster.leader_of_region(region_id).unwrap();

    // Create clients.
    let env = Arc::new(Environment::new(1));
    let mut clients = HashMap::default();
    for node_id in cluster.get_node_ids() {
        let channel =
            ChannelBuilder::new(Arc::clone(&env)).connect(cluster.sim.rl().get_addr(node_id));
        let client = TikvClient::new(channel);
        clients.insert(node_id, client);
    }

    // Start transferring the region to store 2.
    let new_peer = new_peer(2, 1003);
    cluster.pd_client.must_add_peer(region_id, new_peer.clone());

    // Create the ctx of the first region.
    let store_1_client = clients.get(&leader.get_store_id()).unwrap();
    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader.clone());
    ctx.set_region_epoch(cluster.get_region_epoch(region_id));

    // Pause store-2 after calling observer callbacks and before writing to the rocksdb.
    let new_leader_apply_fp = "post_handle_apply_1003";
    fail::cfg(new_leader_apply_fp, "pause").unwrap();

    // Write 1 lock.
    must_kv_prewrite(
        &store_1_client,
        ctx,
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );
    // Wait for store-2 applying.
    std::thread::sleep(Duration::from_secs(3));

    // Starting the process of green GC at safe point 20:
    //   1. Register lock observers on all stores.
    //   2. Scan locks physically on each store independently.
    //   3. Get locks from all observers.
    let safe_point = 20;

    // Register lock observers.
    clients.iter().for_each(|(_, c)| {
        must_register_lock_observer(c, safe_point);
    });

    // Finish scanning locks on store-2 and find nothing.
    let store_2_client = clients.get(&new_peer.get_store_id()).unwrap();
    let locks = must_physical_scan_lock(store_2_client, Context::default(), safe_point, b"", 1);
    assert!(locks.is_empty(), "{:?}", locks);

    // Transfer the region from store-1 to store-2.
    fail::remove(new_leader_apply_fp);
    cluster.must_transfer_leader(region_id, new_peer);
    cluster.pd_client.must_remove_peer(region_id, leader);
    // Wait for store-1 desroying the region.
    std::thread::sleep(Duration::from_secs(3));

    // Scan locks on store-1 after the region has been destroyed.
    let locks = must_physical_scan_lock(store_1_client, Context::default(), safe_point, b"", 1);
    assert!(locks.is_empty(), "{:?}", locks);

    // Check lock observers.
    let mut locks = vec![];
    clients.iter().for_each(|(_, c)| {
        locks.extend(must_check_lock_observer(c, safe_point, true));
    });
    // Must observe the applying lock even through we can't use scan to get it.
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), b"k1");
}
<commit_msg>test: fix test_notify_observer_after_apply (#8533)<commit_after>use std::sync::Arc;
use std::time::Duration;

use grpcio::{ChannelBuilder, Environment};
use kvproto::{kvrpcpb::*, tikvpb::TikvClient};
use test_raftstore::*;
use tikv_util::{collections::HashMap, HandyRwLock};

// In theory, raft can propose conf change as long as there is no pending one. Replicas
// don't apply logs synchronously, so it's possible the old leader is removed before the new
// leader applies all logs.
// In the current implementation, the new leader rejects conf change until it applies all logs.
// It guarantees the correctness of green GC. This test is to prevent breaking it in the
// future.
#[test]
fn test_collect_lock_from_stale_leader() {
    let mut cluster = new_server_cluster(0, 2);
    cluster.pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    let leader = cluster.leader_of_region(region_id).unwrap();

    // Create clients.
    let env = Arc::new(Environment::new(1));
    let mut clients = HashMap::default();
    for node_id in cluster.get_node_ids() {
        let channel =
            ChannelBuilder::new(Arc::clone(&env)).connect(cluster.sim.rl().get_addr(node_id));
        let client = TikvClient::new(channel);
        clients.insert(node_id, client);
    }

    // Start transferring the region to store 2.
    let new_peer = new_peer(2, 1003);
    cluster.pd_client.must_add_peer(region_id, new_peer.clone());

    // Create the ctx of the first region.
    let leader_client = clients.get(&leader.get_store_id()).unwrap();
    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader.clone());
    ctx.set_region_epoch(cluster.get_region_epoch(region_id));

    // Pause the new peer applying so that when it becomes the leader, it doesn't apply all logs.
    let new_leader_apply_fp = "on_handle_apply_1003";
    fail::cfg(new_leader_apply_fp, "pause").unwrap();
    must_kv_prewrite(
        leader_client,
        ctx,
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );

    // Leader election only considers the progress of appending logs, so it can succeed.
    cluster.must_transfer_leader(region_id, new_peer.clone());
    // It shouldn't succeed in the current implementation.
    cluster.pd_client.remove_peer(region_id, leader.clone());
    std::thread::sleep(Duration::from_secs(1));
    cluster.pd_client.must_have_peer(region_id, leader);

    // Must scan the lock from the old leader.
    let locks = must_physical_scan_lock(leader_client, Context::default(), 100, b"", 10);
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), b"k1");

    // Can't scan the lock from the new leader.
    let leader_client = clients.get(&new_peer.get_store_id()).unwrap();
    must_register_lock_observer(leader_client, 100);
    let locks = must_check_lock_observer(leader_client, 100, true);
    assert!(locks.is_empty());
    let locks = must_physical_scan_lock(leader_client, Context::default(), 100, b"", 10);
    assert!(locks.is_empty());

    fail::remove(new_leader_apply_fp);
}

#[test]
fn test_observer_send_error() {
    let (_cluster, client, ctx) = must_new_cluster_and_kv_client();

    let max_ts = 100;
    must_register_lock_observer(&client, max_ts);
    must_kv_prewrite(
        &client,
        ctx.clone(),
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );
    assert_eq!(must_check_lock_observer(&client, max_ts, true).len(), 1);

    let observer_send_fp = "lock_observer_send";
    fail::cfg(observer_send_fp, "return").unwrap();
    must_kv_prewrite(
        &client,
        ctx,
        vec![new_mutation(Op::Put, b"k2", b"v")],
        b"k1".to_vec(),
        10,
    );
    let resp = check_lock_observer(&client, max_ts);
    assert!(resp.get_error().is_empty(), "{:?}", resp.get_error());
    // Should mark dirty if fails to send locks.
    assert!(!resp.get_is_clean());
}

#[test]
fn test_notify_observer_after_apply() {
    let (mut cluster, client, ctx) = must_new_cluster_and_kv_client();
    cluster.pd_client.disable_default_operator();
    let post_apply_query_fp = "notify_lock_observer_query";
    let apply_plain_kvs_fp = "notify_lock_observer_snapshot";

    // Write a lock and pause before notifying the lock observer.
    let max_ts = 100;
    must_register_lock_observer(&client, max_ts);
    fail::cfg(post_apply_query_fp, "pause").unwrap();
    let key = b"k";
    let (client_clone, ctx_clone) = (client.clone(), ctx.clone());
    std::thread::spawn(move || {
        must_kv_prewrite(
            &client_clone,
            ctx_clone,
            vec![new_mutation(Op::Put, key, b"v")],
            key.to_vec(),
            10,
        );
    });
    // We can use physical_scan_lock to get the lock because we notify the lock observer after writing data to the rocskdb.
    let mut locks = vec![];
    for _ in 1..100 {
        sleep_ms(10);
        assert!(must_check_lock_observer(&client, max_ts, true).is_empty());
        locks.extend(must_physical_scan_lock(
            &client,
            ctx.clone(),
            max_ts,
            b"",
            100,
        ));
        if !locks.is_empty() {
            break;
        }
    }
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), key);
    fail::remove(post_apply_query_fp);
    assert_eq!(must_check_lock_observer(&client, max_ts, true).len(), 1);

    // Add a new store.
    let store_id = cluster.add_new_engine();
    let channel = ChannelBuilder::new(Arc::new(Environment::new(1)))
        .connect(cluster.sim.rl().get_addr(store_id));
    let replica_client = TikvClient::new(channel);

    // Add a new peer and pause before notifying the lock observer.
    must_register_lock_observer(&replica_client, max_ts);
    fail::cfg(apply_plain_kvs_fp, "pause").unwrap();
    cluster
        .pd_client
        .must_add_peer(ctx.get_region_id(), new_peer(store_id, store_id));
    // We can use physical_scan_lock to get the lock because we notify the lock observer after writing data to the rocskdb.
    let mut locks = vec![];
    for _ in 1..100 {
        sleep_ms(10);
        assert!(must_check_lock_observer(&replica_client, max_ts, true).is_empty());
        locks.extend(must_physical_scan_lock(
            &replica_client,
            ctx.clone(),
            max_ts,
            b"",
            100,
        ));
        if !locks.is_empty() {
            break;
        }
    }
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), key);
    fail::remove(apply_plain_kvs_fp);
    assert_eq!(
        must_check_lock_observer(&replica_client, max_ts, true).len(),
        1
    );
}

// It may cause locks missing during green GC if the raftstore notifies the lock observer before writing data to the rocksdb:
//   1. Store-1 transfers a region to store-2 and store-2 is applying logs.
//   2. GC worker registers lock observer on store-2 after calling lock observer's callback and before finishing applying which means the lock won't be observed.
//   3. GC worker scans locks on each store independently. It's possible GC worker has scanned all locks on store-2 and hasn't scanned locks on store-1.
//   4. Store-2 applies all logs and removes the peer on store-1.
//   5. GC worker can't scan the lock on store-1 because the peer has been destroyed.
//   6. GC worker can't get the lock from store-2 because it can't observe the lock and has scanned it.
#[test]
fn test_collect_applying_locks() {
    let mut cluster = new_server_cluster(0, 2);
    cluster.pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    let leader = cluster.leader_of_region(region_id).unwrap();

    // Create clients.
    let env = Arc::new(Environment::new(1));
    let mut clients = HashMap::default();
    for node_id in cluster.get_node_ids() {
        let channel =
            ChannelBuilder::new(Arc::clone(&env)).connect(cluster.sim.rl().get_addr(node_id));
        let client = TikvClient::new(channel);
        clients.insert(node_id, client);
    }

    // Start transferring the region to store 2.
    let new_peer = new_peer(2, 1003);
    cluster.pd_client.must_add_peer(region_id, new_peer.clone());

    // Create the ctx of the first region.
    let store_1_client = clients.get(&leader.get_store_id()).unwrap();
    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader.clone());
    ctx.set_region_epoch(cluster.get_region_epoch(region_id));

    // Pause store-2 after calling observer callbacks and before writing to the rocksdb.
    let new_leader_apply_fp = "post_handle_apply_1003";
    fail::cfg(new_leader_apply_fp, "pause").unwrap();

    // Write 1 lock.
    must_kv_prewrite(
        &store_1_client,
        ctx,
        vec![new_mutation(Op::Put, b"k1", b"v")],
        b"k1".to_vec(),
        10,
    );
    // Wait for store-2 applying.
    std::thread::sleep(Duration::from_secs(3));

    // Starting the process of green GC at safe point 20:
    //   1. Register lock observers on all stores.
    //   2. Scan locks physically on each store independently.
    //   3. Get locks from all observers.
    let safe_point = 20;

    // Register lock observers.
    clients.iter().for_each(|(_, c)| {
        must_register_lock_observer(c, safe_point);
    });

    // Finish scanning locks on store-2 and find nothing.
    let store_2_client = clients.get(&new_peer.get_store_id()).unwrap();
    let locks = must_physical_scan_lock(store_2_client, Context::default(), safe_point, b"", 1);
    assert!(locks.is_empty(), "{:?}", locks);

    // Transfer the region from store-1 to store-2.
    fail::remove(new_leader_apply_fp);
    cluster.must_transfer_leader(region_id, new_peer);
    cluster.pd_client.must_remove_peer(region_id, leader);
    // Wait for store-1 desroying the region.
    std::thread::sleep(Duration::from_secs(3));

    // Scan locks on store-1 after the region has been destroyed.
    let locks = must_physical_scan_lock(store_1_client, Context::default(), safe_point, b"", 1);
    assert!(locks.is_empty(), "{:?}", locks);

    // Check lock observers.
    let mut locks = vec![];
    clients.iter().for_each(|(_, c)| {
        locks.extend(must_check_lock_observer(c, safe_point, true));
    });
    // Must observe the applying lock even through we can't use scan to get it.
    assert_eq!(locks.len(), 1);
    assert_eq!(locks[0].get_key(), b"k1");
}
<|endoftext|>


<commit_before>use std::cmp;

#[test]
fn card_cmp_less() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(lesser.partial_cmp(&greater).unwrap(), cmp::Ordering::Less);
}

#[test]
fn card_cmp_greater() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(greater.partial_cmp(&lesser).unwrap(), cmp::Ordering::Greater);
}

#[test]
fn card_cmp_equal() {
    let heart_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let spade_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Spades
    };

    assert_eq!(heart_card.partial_cmp(&spade_card).unwrap(), cmp::Ordering::Equal);
}
<commit_msg>Removed unnecessary import<commit_after>#[test]
fn card_cmp_less() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(lesser.partial_cmp(&greater).unwrap(), cmp::Ordering::Less);
}

#[test]
fn card_cmp_greater() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(greater.partial_cmp(&lesser).unwrap(), cmp::Ordering::Greater);
}

#[test]
fn card_cmp_equal() {
    let heart_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let spade_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Spades
    };

    assert_eq!(heart_card.partial_cmp(&spade_card).unwrap(), cmp::Ordering::Equal);
}
<|endoftext|>


<commit_before>use cart::Cart;
use rom::{NesRom, CHR_BANK_SIZE, PRG_BANK_SIZE};

pub struct Uxrom {
    prg_bank: [[u8; PRG_BANK_SIZE]; 8],
    chr_rom: [u8; CHR_BANK_SIZE],
    bank_select: u8,
}

impl Uxrom {
    pub fn new(rom: &NesRom) -> Result<Self, &'static str> {
        if rom.prg.len() != PRG_BANK_SIZE * 8 {
            println!("{}", rom.prg.len());
            Err("Unexpected PRG ROM size")
        } else if rom.chr_rom_banks > 0 && rom.chr.len() != CHR_BANK_SIZE {
            Err("Unexpected CHR ROM size")
        } else {
            let mut cart = Uxrom {
                prg_bank: [[0; PRG_BANK_SIZE]; 8],
                chr_rom: [0; CHR_BANK_SIZE],
                bank_select: 0,
            };

            for i in 0..8 {
                let start_offset = i * PRG_BANK_SIZE;
                let end_offset = start_offset + PRG_BANK_SIZE;
                cart.prg_bank[i].copy_from_slice(&rom.prg[start_offset..end_offset]);
            }

            if rom.chr_rom_banks > 0 {
                cart.chr_rom.copy_from_slice(&rom.chr);
            }

            Ok(cart)
        }
    }
}

impl Cart for Uxrom {
    fn read_prg(&self, addr: u16) -> u8 {
        debug_assert!(addr >= 0x8000);
        let addr = addr as usize;
        if addr & 0xc000 == 0x8000 {
            let bank_select = self.bank_select as usize;
            self.prg_bank[bank_select][addr & 0x3fff]
        } else {
            self.prg_bank[7][addr & 0x3fff]
        }
    }

    fn write_prg(&mut self, addr: u16, value: u8) {
        debug_assert!(addr >= 0x8000);
        self.bank_select = value & 0x0f
    }

    fn read_chr(&self, addr: u16) -> u8 {
        self.chr_rom[addr as usize]
    }

    fn write_chr(&mut self, addr: u16, value: u8) {
        self.chr_rom[addr as usize] = value
    }
}
<commit_msg>Improved bank resolution for unrom<commit_after>use cart::Cart;
use rom::{NesRom, CHR_BANK_SIZE, PRG_BANK_SIZE};

pub struct Uxrom {
    prg_bank: Vec<u8>,
    chr_rom: [u8; CHR_BANK_SIZE],
    bank_select: u8,
    last_bank: u8,
}

impl Uxrom {
    pub fn new(rom: &NesRom) -> Result<Self, &'static str> {
        if rom.prg.len() != PRG_BANK_SIZE * 8 {
            println!("{}", rom.prg.len());
            Err("Unexpected PRG ROM size")
        } else if rom.chr_rom_banks > 0 && rom.chr.len() != CHR_BANK_SIZE {
            Err("Unexpected CHR ROM size")
        } else {
            let mut cart = Uxrom {
                prg_bank: vec![0; rom.prg.len()],
                chr_rom: [0; CHR_BANK_SIZE],
                bank_select: 0,
                last_bank: rom.prg_rom_banks - 1,
            };

            cart.prg_bank.copy_from_slice(&rom.prg);

            if rom.chr_rom_banks > 0 {
                cart.chr_rom.copy_from_slice(&rom.chr);
            }

            Ok(cart)
        }
    }
}

impl Cart for Uxrom {
    fn read_prg(&self, addr: u16) -> u8 {
        debug_assert!(addr >= 0x8000);
        let resolved_addr = resolve_prg_addr(addr, self.bank_select, self.last_bank);
        self.prg_bank[resolved_addr]
    }

    fn write_prg(&mut self, addr: u16, value: u8) {
        debug_assert!(addr >= 0x8000);
        self.bank_select = value & 0x0f
    }

    fn read_chr(&self, addr: u16) -> u8 {
        self.chr_rom[addr as usize]
    }

    fn write_chr(&mut self, addr: u16, value: u8) {
        self.chr_rom[addr as usize] = value
    }
}

fn resolve_prg_addr(addr: u16, bank_select: u8, last_bank: u8) -> usize {
    let addr = addr as usize;
    let normalized_addr = addr & 0x3fff;
    let bank_select = bank_select as usize;
    let last_bank = last_bank as usize;

    if addr & 0xc000 == 0x8000 {
        (bank_select << 14) | normalized_addr
    } else {
        (last_bank << 14) | normalized_addr
    }
}

#[test]
fn test_resolve() {
    let addr = resolve_prg_addr(0x8000, 0, 7);
    assert_eq!(0, addr);

    let addr = resolve_prg_addr(0xbfff, 0, 7);
    assert_eq!(0x3fff, addr);

    let addr = resolve_prg_addr(0x8000, 1, 7);
    assert_eq!(0x4000, addr);

    let addr = resolve_prg_addr(0xbfff, 1, 7);
    assert_eq!(0x7fff, addr);

    let addr = resolve_prg_addr(0x8000, 2, 7);
    assert_eq!(0x8000, addr);

    let addr = resolve_prg_addr(0xbfff, 2, 7);
    assert_eq!(0xbfff, addr);

    let addr = resolve_prg_addr(0x8000, 3, 7);
    assert_eq!(0xc000, addr);

    let addr = resolve_prg_addr(0xbfff, 3, 7);
    assert_eq!(0xffff, addr);

    let addr = resolve_prg_addr(0x8000, 4, 7);
    assert_eq!(0x10000, addr);

    let addr = resolve_prg_addr(0xbfff, 4, 7);
    assert_eq!(0x13fff, addr);

    let addr = resolve_prg_addr(0x8000, 5, 7);
    assert_eq!(0x14000, addr);

    let addr = resolve_prg_addr(0xbfff, 5, 7);
    assert_eq!(0x17fff, addr);

    let addr = resolve_prg_addr(0x8000, 6, 7);
    assert_eq!(0x18000, addr);

    let addr = resolve_prg_addr(0xbfff, 6, 7);
    assert_eq!(0x1bfff, addr);

    let addr = resolve_prg_addr(0x8000, 7, 7);
    assert_eq!(0x1c000, addr);

    let addr = resolve_prg_addr(0xbfff, 7, 7);
    assert_eq!(0x1ffff, addr);

    // Any address 0xc000 and up should always resolve to the last bank
    let addr = resolve_prg_addr(0xc000, 0, 7);
    assert_eq!(0x1c000, addr);

    let addr = resolve_prg_addr(0xc000, 0, 6);
    assert_eq!(0x18000, addr);

    let addr = resolve_prg_addr(0xffff, 0, 5);
    assert_eq!(0x17fff, addr);
}
<|endoftext|>


<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use utility::to_u32;

pub fn frame_parser(input: &[u8], channels: u8) -> IResult<&[u8], Frame> {
  chain!(input,
    frame_header: header ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  )
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)             = tuple0;
      let (channel_assignment, bits_per_sample) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(tuple0.0 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(tuple0.0 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Use block_byte rather than pull from tuple0<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use utility::to_u32;

pub fn frame_parser(input: &[u8], channels: u8) -> IResult<&[u8], Frame> {
  chain!(input,
    frame_header: header ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  )
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u32, u32)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let sample_rate = bytes[0] & 0x0f;

      if sample_rate != 0x0f {
        let block_size = bytes[0] >> 4;

        IResult::Done(i, (block_size as u32, sample_rate as u32))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, usize)> {
  match take!(input, 1) {
    IResult::Done(i, bytes)   => {
      let channel_assignment = match bytes[0] >> 4 {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let bits_per_sample = (bytes[0] >> 1) & 0b0111;
      let is_valid        = (bytes[0] & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, bits_per_sample as usize))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn sample_or_frame_number(input: &[u8], is_sample: bool,
                          (size, value): (usize, u8))
                          -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in (0..size) {
        let byte = bytes[i] as u64;

        match byte {
          0b10000000...10111111 => {
            result = (result << 6) + (byte & 0b00111111);
          }
          _                     => {
            is_error = true;
            break;
          }
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u32)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

named!(header <&[u8], Header>,
  chain!(
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(sample_or_frame_number, is_variable_block_size,
                   number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)             = tuple0;
      let (channel_assignment, bits_per_sample) = tuple1;

      let block_size = match block_byte {
        0b0000          => 0,
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => 0,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        0b1111 => 0,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  )
);

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio_core::net::{TcpStream, TcpStreamNew};
use tokio_io::AsyncRead;
use tokio_core::reactor::Handle;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::*;
use imap_proto::builders::command::Command;
use proto::*;

pub mod builder {
    pub use imap_proto::builders::command::*;
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str, handle: &Handle) -> ConnectFuture {
        let addr = format!("{}:993", server);
        let addr = addr.to_socket_addrs().unwrap().next().unwrap();
        let stream = TcpStream::connect(&addr, handle);
        ConnectFuture::TcpConnecting(stream, server.to_string())
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap();
        let (cmd_bytes, next_state) = cmd.to_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        if self.future.is_some() {
            let mut future = self.future.take().unwrap();
            match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        if !self.transport.is_some() {
            return Ok(Async::NotReady);
        }
        let mut transport = self.transport.take().unwrap();
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        loop {
            match transport.poll() {
                Ok(Async::Ready(Some(rsp))) => {
                    if let Some(req_id) = rsp.request_id() {
                        self.done = *req_id == self.request_id;
                    };
                    self.transport = Some(transport);
                    return Ok(Async::Ready(StreamEvent::Next(rsp)));
                },
                Ok(Async::Ready(None)) | Ok(Async::NotReady) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ConnectFuture {
    #[doc(hidden)]
    TcpConnecting(TcpStreamNew, String),
    #[doc(hidden)]
    TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)]
    ServerGreeting(Option<ImapTransport>),
}

impl Future for ConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self { Self::new() }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self { Self::new() }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10000)))
    }
}
<commit_msg>Clarify number literal using digit grouping<commit_after>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio_core::net::{TcpStream, TcpStreamNew};
use tokio_io::AsyncRead;
use tokio_core::reactor::Handle;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::*;
use imap_proto::builders::command::Command;
use proto::*;

pub mod builder {
    pub use imap_proto::builders::command::*;
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str, handle: &Handle) -> ConnectFuture {
        let addr = format!("{}:993", server);
        let addr = addr.to_socket_addrs().unwrap().next().unwrap();
        let stream = TcpStream::connect(&addr, handle);
        ConnectFuture::TcpConnecting(stream, server.to_string())
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap();
        let (cmd_bytes, next_state) = cmd.to_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        if self.future.is_some() {
            let mut future = self.future.take().unwrap();
            match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        if !self.transport.is_some() {
            return Ok(Async::NotReady);
        }
        let mut transport = self.transport.take().unwrap();
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        loop {
            match transport.poll() {
                Ok(Async::Ready(Some(rsp))) => {
                    if let Some(req_id) = rsp.request_id() {
                        self.done = *req_id == self.request_id;
                    };
                    self.transport = Some(transport);
                    return Ok(Async::Ready(StreamEvent::Next(rsp)));
                },
                Ok(Async::Ready(None)) | Ok(Async::NotReady) => {
                    break;
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ConnectFuture {
    #[doc(hidden)]
    TcpConnecting(TcpStreamNew, String),
    #[doc(hidden)]
    TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)]
    ServerGreeting(Option<ImapTransport>),
}

impl Future for ConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self { Self::new() }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self { Self::new() }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10_000)))
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod get_repos_should {
    use super::*;

    #[test]
    fn return_repos_with_app_name_hello_world_library_and_language_rust_and_program_type_lib_and_user_intrepion(
    ) {
        let expected = vec![GitHubRepository {
            app_name: "hello-world-library".to_string(),
            client_type: None,
            language: ProgrammingLanguage::Rust,
            program_type: ProgramType::Library,
            server_type: None,
            user: "intrepion".to_string(),
        }];

        let actual = get_repos("intrepion", "hello-world-library", ProgrammingLanguage::Rust, ProgramType::Library);
    }
}

enum ProgrammingLanguage {
    Rust,
}

enum ProgramType {
    Library,
}

struct GitHubRepository {
    app_name: String,
    client_type: Option<String>,
    language: ProgrammingLanguage,
    program_type: ProgramType,
    server_type: Option<String>,
    user: String,
}
<commit_msg>green<commit_after>#[cfg(test)]
mod get_repos_should {
    use super::*;

    #[test]
    fn return_repos_with_app_name_hello_world_library_and_language_rust_and_program_type_lib_and_user_intrepion(
    ) {
        let expected = vec![GitHubRepository {
            app_name: "hello-world-library".to_string(),
            client_type: None,
            language: ProgrammingLanguage::Rust,
            program_type: ProgramType::Library,
            server_type: None,
            user: "intrepion".to_string(),
        }];

        let actual = get_repos(
            "intrepion",
            "hello-world",
            ProgrammingLanguage::Rust,
            ProgramType::Library,
        );
    }
}

enum ProgrammingLanguage {
    Rust,
}

enum ProgramType {
    Library,
}

struct GitHubRepository {
    app_name: String,
    client_type: Option<String>,
    language: ProgrammingLanguage,
    program_type: ProgramType,
    server_type: Option<String>,
    user: String,
}

fn get_repos(user: &str, app_name: &str, language: ProgrammingLanguage, program_type: ProgramType) {
}
<|endoftext|>


<commit_before>#![feature(use_extern_macros)]
extern crate tapioca_testutil;

tapioca_testutil::infer_test_api!(httpbin);

use httpbin::status__code_;

static code: &i32 = &200;

fn main() {
    let dummy_created_id = status__code_::ResourceId_code::from_static(code);

    status__code_::get(&dummy_created_id);
    status__code_::delete(dummy_created_id); //~ moved here
    status__code_::get(&dummy_created_id);

    status__code_::delete(&dummy_created_id); //~ mismatched types
    status__code_::get(&dummy_created_id);

    status__code_::delete(dummy_created_id.clone()); //~ no clone
    status__code_::get(&dummy_created_id);
}
<commit_msg>Fix compiletest expected error<commit_after>#![feature(use_extern_macros)]
extern crate tapioca_testutil;

tapioca_testutil::infer_test_api!(httpbin);

use httpbin::status__code_;

static code: &i32 = &200;

fn main() {
    let dummy_created_id = status__code_::ResourceId_code::from_static(code);

    status__code_::get(&dummy_created_id);
    status__code_::delete(dummy_created_id); //~ moved here
    status__code_::get(&dummy_created_id);

    status__code_::delete(&dummy_created_id); //~ mismatched types
    status__code_::get(&dummy_created_id);

    status__code_::delete(dummy_created_id.clone()); //~ no method named `clone`
    status__code_::get(&dummy_created_id);
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<i64>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    thumb: Option<InputFile>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (thumb (raw), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            thumb: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn thumb<V>(&mut self, thumb: V) -> &mut Self
    where
        V: Into<InputFileUpload>,
    {
        self.thumb = Some(thumb.into().into());
        self
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: i64) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<commit_msg>refactor: use Integer for SendAudio.duration instead of i64<commit_after>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<Integer>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    thumb: Option<InputFile>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (thumb (raw), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            thumb: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn thumb<V>(&mut self, thumb: V) -> &mut Self
    where
        V: Into<InputFileUpload>,
    {
        self.thumb = Some(thumb.into().into());
        self
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: Integer) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<|endoftext|>


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

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/// Coerce an immutable reference to be mutable.
#[inline]
#[deprecated="casting &T to &mut T is undefined behaviour: use Cell<T>, RefCell<T> or Unsafe<T>"]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::transmute;
    use raw;
    use realstd::str::StrAllocating;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(box [76u8], transmute("L".to_owned()));
        }
    }
}
<commit_msg>std: Reorder definitions in cast<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Unsafe casting functions

use mem;
use intrinsics;
use ptr::copy_nonoverlapping_memory;

/**
 * Transform a value of one type into a value of another type.
 * Both types must have the same size and alignment.
 *
 * # Example
 *
 * ```rust
 * use std::cast;
 *
 * let v: &[u8] = unsafe { cast::transmute("L") };
 * assert!(v == [76u8]);
 * ```
 */
#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

/**
 * Move a thing into the void
 *
 * The forget function will take ownership of the provided value but neglect
 * to run any required cleanup or memory-management operations on it.
 */
#[inline]
pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }

/// Casts the value at `src` to U. The two types must have the same length.
#[inline]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    let mut dest: U = mem::uninit();
    let dest_ptr: *mut u8 = transmute(&mut dest);
    let src_ptr: *u8 = transmute(src);
    copy_nonoverlapping_memory(dest_ptr, src_ptr, mem::size_of::<U>());
    dest
}

/// Coerce an immutable reference to be mutable.
#[inline]
#[deprecated="casting &T to &mut T is undefined behaviour: use Cell<T>, RefCell<T> or Unsafe<T>"]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }

/// Coerce a reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_lifetime<'a,'b,T>(ptr: &'a T) -> &'b T {
    transmute(ptr)
}

/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *T) -> *mut T {
    transmute(ptr)
}

/// Coerce a mutable reference to have an arbitrary associated lifetime.
#[inline]
pub unsafe fn transmute_mut_lifetime<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
    transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
    transmute_mut_lifetime(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
    transmute_lifetime(ptr)
}

/****************************************************************************
 * Tests
 ****************************************************************************/

#[cfg(test)]
mod tests {
    use cast::transmute;
    use raw;
    use realstd::str::StrAllocating;

    #[test]
    fn test_transmute_copy() {
        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
    }

    #[test]
    fn test_transmute() {
        unsafe {
            let x = @100u8;
            let x: *raw::Box<u8> = transmute(x);
            assert!((*x).data == 100);
            let _x: @int = transmute(x);
        }
    }

    #[test]
    fn test_transmute2() {
        unsafe {
            assert_eq!(box [76u8], transmute("L".to_owned()));
        }
    }
}
<|endoftext|>


<commit_before>/*
Module: comm

Communication between tasks

Communication between tasks is facilitated by ports (in the receiving task),
and channels (in the sending task). Any number of channels may feed into a
single port.

Ports and channels may only transmit values of unique types; that is,
values that are statically guaranteed to be accessed by a single
'owner' at a time.  Unique types include scalars, vectors, strings,
and records, tags, tuples and unique boxes (~T) thereof. Most notably,
shared boxes (@T) may not be transmitted across channels.

Example:

> use std::{task, comm, io};
>
> let p = comm::port();
> task::spawn(comm::chan(p), fn (c: chan<str>) {
>   comm::send(c, "Hello, World");
> });
>
> io::println(comm::recv(p));

*/

import sys;
import task;

export send;
export recv;
export chan;
export port;

#[abi = "cdecl"]
native mod rustrt {
    type void;
    type rust_port;

    fn chan_id_send<T: send>(t: *sys::type_desc,
                            target_task: task::task, target_port: port_id,
                            data: T) -> ctypes::uintptr_t;

    fn new_port(unit_sz: uint) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> ctypes::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *ctypes::uintptr_t,
                 killed: *ctypes::uintptr_t);
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
}

type port_id = int;

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
/*
Type: chan

A communication endpoint that can send messages. Channels send
messages to ports.

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.

Channels are weak: a channel does not keep the port it is bound to alive.
If a channel attempts to send data to a dead port that data will be silently
dropped.

Channels may be duplicated and themselves transmitted over other channels.
*/
tag chan<T: send> {
    chan_t(task::task, port_id);
}

resource port_ptr<T: send>(po: *rustrt::rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    rustrt::rust_port_detach(po);
    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
        // FIXME: For some reason if we don't assign to something here
        // we end up with invalid reads in the drop glue.
        let _t = recv_::<T>(po);
    }
    rustrt::del_port(po);
}

/*
Type: port

A communication endpoint that can receive messages. Ports receive
messages from channels.

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same port.

Ports may be associated with multiple <chan>s.
*/
tag port<T: send> { port_t(@port_ptr<T>); }

/*
Function: send

Sends data over a channel.

The sent data is moved into the channel, whereupon the caller loses access
to it.
*/
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(t, p) = ch;
    let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::leak(data);
    }
    task::yield();
}

/*
Function: port

Constructs a port.
*/
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

/*
Function: recv

Receive from a port.

If no data is available on the port then the task will block until data
becomes available.
*/
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

// Receive on a raw port pointer
fn recv_<T: send>(p: *rustrt::rust_port) -> T {
    // FIXME: Due to issue 1185 we can't use a return pointer when
    // calling C code, and since we can't create our own return
    // pointer on the stack, we're going to call a little intrinsic
    // that will grab the value of the return pointer, then call this
    // function, which we will then use to call the runtime.
    fn recv(dptr: *uint, port: *rustrt::rust_port,
            yield: *ctypes::uintptr_t,
            killed: *ctypes::uintptr_t) unsafe {
        rustrt::port_recv(dptr, port, yield, killed);
    }
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let killed = 0u;
    let killedp = ptr::addr_of(killed);
    let res = rusti::call_with_retptr(bind recv(_, p, yieldp, killedp));
    if killed != 0u {
        fail "killed";
    }
    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    }
    ret res;
}

/*
Function: chan

Constructs a channel.

The channel is bound to the port used to construct it.
*/
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(task::get_task(), rustrt::get_port_id(***p))
}
<commit_msg>Fix typo in example in libcore docs<commit_after>/*
Module: comm

Communication between tasks

Communication between tasks is facilitated by ports (in the receiving task),
and channels (in the sending task). Any number of channels may feed into a
single port.

Ports and channels may only transmit values of unique types; that is,
values that are statically guaranteed to be accessed by a single
'owner' at a time.  Unique types include scalars, vectors, strings,
and records, tags, tuples and unique boxes (~T) thereof. Most notably,
shared boxes (@T) may not be transmitted across channels.

Example:

> import std::{task, comm, io};
>
> let p = comm::port();
> task::spawn(comm::chan(p), fn (c: chan<str>) {
>   comm::send(c, "Hello, World");
> });
>
> io::println(comm::recv(p));

*/

import sys;
import task;

export send;
export recv;
export chan;
export port;

#[abi = "cdecl"]
native mod rustrt {
    type void;
    type rust_port;

    fn chan_id_send<T: send>(t: *sys::type_desc,
                            target_task: task::task, target_port: port_id,
                            data: T) -> ctypes::uintptr_t;

    fn new_port(unit_sz: uint) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> ctypes::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *ctypes::uintptr_t,
                 killed: *ctypes::uintptr_t);
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
}

type port_id = int;

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
/*
Type: chan

A communication endpoint that can send messages. Channels send
messages to ports.

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.

Channels are weak: a channel does not keep the port it is bound to alive.
If a channel attempts to send data to a dead port that data will be silently
dropped.

Channels may be duplicated and themselves transmitted over other channels.
*/
tag chan<T: send> {
    chan_t(task::task, port_id);
}

resource port_ptr<T: send>(po: *rustrt::rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    rustrt::rust_port_detach(po);
    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
        // FIXME: For some reason if we don't assign to something here
        // we end up with invalid reads in the drop glue.
        let _t = recv_::<T>(po);
    }
    rustrt::del_port(po);
}

/*
Type: port

A communication endpoint that can receive messages. Ports receive
messages from channels.

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same port.

Ports may be associated with multiple <chan>s.
*/
tag port<T: send> { port_t(@port_ptr<T>); }

/*
Function: send

Sends data over a channel.

The sent data is moved into the channel, whereupon the caller loses access
to it.
*/
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(t, p) = ch;
    let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::leak(data);
    }
    task::yield();
}

/*
Function: port

Constructs a port.
*/
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

/*
Function: recv

Receive from a port.

If no data is available on the port then the task will block until data
becomes available.
*/
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

// Receive on a raw port pointer
fn recv_<T: send>(p: *rustrt::rust_port) -> T {
    // FIXME: Due to issue 1185 we can't use a return pointer when
    // calling C code, and since we can't create our own return
    // pointer on the stack, we're going to call a little intrinsic
    // that will grab the value of the return pointer, then call this
    // function, which we will then use to call the runtime.
    fn recv(dptr: *uint, port: *rustrt::rust_port,
            yield: *ctypes::uintptr_t,
            killed: *ctypes::uintptr_t) unsafe {
        rustrt::port_recv(dptr, port, yield, killed);
    }
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let killed = 0u;
    let killedp = ptr::addr_of(killed);
    let res = rusti::call_with_retptr(bind recv(_, p, yieldp, killedp));
    if killed != 0u {
        fail "killed";
    }
    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    }
    ret res;
}

/*
Function: chan

Constructs a channel.

The channel is bound to the port used to construct it.
*/
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(task::get_task(), rustrt::get_port_id(***p))
}
<|endoftext|>