<commit_before>use std::f32::consts::PI;

use map_in_place::MapInPlace;
use num::complex::Complex32;
use num::traits::Zero;
use quad_osc::QuadOsc;
use rand::distributions::normal::Normal;
use rand::distributions::IndependentSample;
use rand::Rng;

use consts::SAMPLES_PER_FRAME;
use descramble::VoiceDecisions;
use enhance::EnhancedSpectrals;
use params::BaseParams;
use window;

// Result of equation 121
const SCALING_COEF: f32 = 146.6432708443356;

const DFT_SIZE: usize = 256;
const IDFT_SIZE: usize = 256;

const DFT_HALF: usize = DFT_SIZE / 2;
const IDFT_HALF: usize = IDFT_SIZE / 2;

/// Determine the (lower, upper) band edges for the given harmonic of the fundamental
/// frequency.
fn edges(l: usize, params: &BaseParams) -> (usize, usize) {
    let common = DFT_SIZE as f32 / (2.0 * PI) * params.fundamental;

    (
        (common * (l as f32 - 0.5)).ceil() as usize,
        (common * (l as f32 + 0.5)).ceil() as usize,
    )
}

/// Constructs unvoiced DFT/IDFT.
///
/// Constructs a frequency-domain representation of an "unvoiced" white noise signal,
/// bandpassed only for the unvoiced frequencies in the current frame. This spectrum can
/// then be used with an inverse Fourier transform to produce a white noise signal
/// containing only unvoiced frequency content.
pub struct UnvoicedDFT([Complex32; DFT_HALF]);

impl UnvoicedDFT {
    pub fn new<R: Rng>(params: &BaseParams, voice: &VoiceDecisions,
                       enhanced: &EnhancedSpectrals, mut rng: R)
        -> UnvoicedDFT
    {
        let mut dft = [Complex32::default(); DFT_HALF];
        let gaus = Normal::new(0.0, (window::ENERGY_SYNTHESIS / 2.0).sqrt() as f64);

        for (l, &amplitude) in enhanced.iter().enumerate() {
            let l = l + 1;

            if voice.is_voiced(l) {
                continue;
            }

            let (lower, upper) = edges(l, params);

            for m in lower..upper {
                dft[m] = Complex32::new(gaus.ind_sample(&mut rng) as f32,
                                        gaus.ind_sample(&mut rng) as f32);
            }

            let energy = (lower..upper)
                .map(|m| dft[m].norm_sqr())
                .fold(0.0, |s, x| s + x);
            let power = energy / (upper - lower) as f32;
            let scale = SCALING_COEF * amplitude / power.sqrt();

            // Scale the band according to Eq 120.
            (&mut dft[lower..upper]).map_in_place(|&x| scale * x);
        }

        UnvoicedDFT(dft)
    }

    pub fn idft(&self, n: isize) -> f32 {
        if n < -(IDFT_HALF as isize) || n >= IDFT_HALF as isize {
            return 0.0;
        }

        let mut osc = QuadOsc::new(0.0, 2.0 / IDFT_SIZE as f32 * PI * n as f32);

        2.0 / IDFT_SIZE as f32 * self.0.iter().map(|x| {
            let (sin, cos) = osc.next();
            x.re * cos - x.im * sin
        }).fold(0.0, |s, x| s + x)
    }
}

impl Default for UnvoicedDFT {
    fn default() -> UnvoicedDFT {
        UnvoicedDFT([Complex32::zero(); DFT_HALF])
    }
}

pub struct Unvoiced<'a, 'b> {
    cur: &'a UnvoicedDFT,
    prev: &'b UnvoicedDFT,
    window: window::Window,
}

impl<'a, 'b> Unvoiced<'a, 'b> {
    pub fn new(cur: &'a UnvoicedDFT, prev: &'b UnvoicedDFT) -> Unvoiced<'a, 'b> {
        Unvoiced {
            cur: cur,
            prev: prev,
            window: window::synthesis(),
        }
    }

    pub fn get(&self, n: usize) -> f32 {
        debug_assert!(n < SAMPLES_PER_FRAME);

        let n = n as isize;

        let numer = self.window.get(n) * self.prev.idft(n) +
            self.window.get(n - SAMPLES_PER_FRAME as isize) *
                self.cur.idft(n - SAMPLES_PER_FRAME as isize);
        let denom = self.window.get(n).powi(2) +
            self.window.get(n - SAMPLES_PER_FRAME as isize).powi(2);

        numer / denom
    }
}

#[cfg(test)]
mod test {
    use super::edges;
    use descramble::Bootstrap;
    use params::BaseParams;

    #[test]
    fn test_edges() {
        let chunks = [
            0b001000010010,
            0b110011001100,
            0b111000111000,
            0b111111111111,
            0b10100110101,
            0b00101111010,
            0b01110111011,
            0b00001000,
        ];

        let b = Bootstrap::new(&chunks);
        let p = BaseParams::new(b.unwrap_period());

        assert!((p.fundamental - 0.17575344).abs() < 0.000001);

        let (lower, upper) = edges(1, &p);
        assert_eq!(lower, 4);
        assert_eq!(upper, 11);

        let (lower, upper) = edges(2, &p);
        assert_eq!(lower, 11);
        assert_eq!(upper, 18);

        let (lower, upper) = edges(5, &p);
        assert_eq!(lower, 33);
        assert_eq!(upper, 40);

        let (lower, upper) = edges(8, &p);
        assert_eq!(lower, 54);
        assert_eq!(upper, 61);

        let (lower, upper) = edges(16, &p);
        assert_eq!(lower, 111);
        assert_eq!(upper, 119);
    }
}
<commit_msg>Document unvoiced module<commit_after>//! Unvoiced spectrum synthesis.
//!
//! At a high level, the unvoiced signal is generated with these steps:
//!
//! 1. Construct the frequency-domain representation of a white noise signal using the
//!    Discrete Fourier Transform (DFT).
//! 2. Bandpass the spectrum to contain only the frequencies marked as unvoiced in the
//!    current frame.
//! 3. Perform an Inverse Discrete Fourier Transform (IDFT) on this spectrum to produce a
//!    white noise signal containing only the unvoiced frequency content.
//!
//! Rather than performing both DFT and IDFT operations, which are relatively expensive
//! and were found to be a bottleneck, this implementation computes an equivalent result
//! using only a partial IDFT.
//!
//! ## DFT of Noise
//!
//! [Under certain circumstances][dft-noise] the DFT of a noise signal can have its points
//! sampled from a probability distribution, rather than each computed with a O(N)
//! procedure.
//!
//! According to the standard [p58], the DFT is generated from a windowed white noise
//! signal u(n). The standard specifies that the signal can have arbitrary mean but doesn't
//! specify if there are any constraints on the variance or if the signal must be real or
//! complex (although the given example u(n) is real with sample mean μx ≈
//! 26562 and variance σx2 ≈ 235198690.)
//!
//! This implementation assumes the white noise signal is real with samples pulled from a
//! Gaussian distribution having sample mean μx = 0 and sample variance
//! σx2 = 1, i.e., u(n) ~ *N*(0, 1). The resulting DFT of this
//! signal then has points with real and complex parts that are sampled from a Gaussian
//! distribution with mean μ = 0 and variance σ2 =
//! Ewσx2 / 2 = Ew / 2, i.e.,
//! Re[Uw(m)], Im[Uw(m)] ~ *N*(0, Ew / 2), where
//! Ew is the energy of the speech synthesis window ws(n).
//!
//! Note that [the given source][dft-noise] only derives this result for a complex signal
//! with equal real and imaginary sample variances, but empirical evaluations show that
//! the result is the same with a real signal.
//!
//! [dft-noise]: http://users.ece.gatech.edu/mrichard/DFT%20of%20Noise.pdf
//!
//! ## DFT Symmetry
//!
//! According to Eq 125, the IDFT is defined as
//!
//! > uw(n) = [Uw(-128) exp(*j* 2π(-128)n/256) +
//! >           Uw(-127) exp(*j* 2π(-127)n/256) + ··· +
//! >           Uw(126) exp(*j* π(126)n/256) +
//! >           Uw(127) exp(*j* 2π(127)n/256)] / 256
//!
//! Since u(n) is a real signal, Uw(m) = Uw(-m)\* (i.e.,
//! the complex conjugate), and the DFT magnitude is symmetric
//! around DC: for all m, 0 ≤ m ≤ 127,
//!
//! > Uw(m) exp(*j* mφ) + Uw(-m) exp(*-j* mφ) =
//! >
//! > (a + *j* b)(cos mφ + *j* sin mφ) + (a - *j* b)(cos mφ - sin mφ) =
//! >
//! > 2a cos mφ - 2b sin mφ = 2 Re[U(m)] cos mφ - 2 Im[U(m)] sin mφ
//!
//! Additionally, the definition of al and bl in Eqs 122 and 123
//! guarantees that for all L and ω0 parameters, a1 ≥ 2 and
//! bL ≤ 125. So according to Eq 124, every frame has at least
//! Uw(-128) = Uw(0) = 0.
//!
//! Using these results, it can be seen that the sum for uw(n) can be
//! "simplified" to
//!
//! > uw(n) =
//! >
//! > [0 + Uw(-127) exp(*j* 2π(-127)n/256) + ··· +
//! >   Uw(-1) exp(*j* 2π(-1)n/256) + 0 +
//! >   Uw(1) exp(*j* π(1)n/256) + ··· +
//! >   Uw(127) exp(*j* 2π(127)n/256)] / 256 =
//! >
//! > 2 [Re[U(0)] cos(2π(0)n/256) - Im[U(0)] sin(2π(0)n/256) +
//! >   Re[U(1)] cos(2π(1)n/256) - Im[U(1)] sin(2π(1)n/256) + ··· +
//! >   Re[U(127)] cos(2π(127)n/256) - Im[U(127)] sin(2π(127)n/256)] / 256
//!
//! which requires half as many Uw(m) values and performs no complex
//! arithmetic.

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

use map_in_place::MapInPlace;
use num::complex::Complex32;
use num::traits::Zero;
use quad_osc::QuadOsc;
use rand::distributions::IndependentSample;
use rand::distributions::normal::Normal;
use rand::Rng;

use consts::SAMPLES_PER_FRAME;
use descramble::VoiceDecisions;
use enhance::EnhancedSpectrals;
use params::BaseParams;
use window;

/// Unvoiced scaling coefficient γw computed from Eq 121.
const SCALING_COEF: f32 = 146.6432708443356;

/// Number of points in the generated discrete Fourier transform.
const DFT_SIZE: usize = 256;
/// Number of points in the generated inverse DFT.
const IDFT_SIZE: usize = 256;

/// Number of points in real half of DFT.
const DFT_HALF: usize = DFT_SIZE / 2;
/// Number of points in real half of IDFT.
const IDFT_HALF: usize = IDFT_SIZE / 2;

/// Constructs unvoiced DFT/IDFT.
pub struct UnvoicedDFT([Complex32; DFT_HALF]);

impl UnvoicedDFT {
    /// Construct a new `UnvoicedDFT` from the given frame parameters and noise generator.
    pub fn new<R: Rng>(params: &BaseParams, voice: &VoiceDecisions,
                       enhanced: &EnhancedSpectrals, mut rng: R)
        -> Self
    {
        // DFT values default to 0 according to Eqs 119 and 124.
        let mut dft = [Complex32::default(); DFT_HALF];

        // Create a Gaussian distribution with mean μ = 0 and variance σ^2 = E_w / 2.
        let gaus = Normal::new(0.0, (window::ENERGY_SYNTHESIS / 2.0).sqrt() as f64);

        for (l, &amplitude) in enhanced.iter().enumerate() {
            let l = l + 1;

            if voice.is_voiced(l) {
                continue;
            }

            // Compute the lower and upper frequency bands for the current harmonic.
            let (lower, upper) = edges(l, params);

            // Populate the current band with random spectrum.
            for m in lower..upper {
                dft[m] = Complex32::new(gaus.ind_sample(&mut rng) as f32,
                                        gaus.ind_sample(&mut rng) as f32);
            }

            // Compute energy of current band according to Eq 120.
            let energy = (lower..upper)
                .map(|m| dft[m].norm_sqr())
                .fold(0.0, |s, x| s + x);
            // Compute power of current band according to Eq 120.
            let power = energy / (upper - lower) as f32;
            // Compute scale for current enhanced spectral amplitude according to Eq 120.
            let scale = SCALING_COEF * amplitude / power.sqrt();

            // Scale the band according to Eq 120.
            (&mut dft[lower..upper]).map_in_place(|&x| scale * x);
        }

        UnvoicedDFT(dft)
    }

    /// Compute the IDFT uw(n) at the given point n.
    pub fn idft(&self, n: isize) -> f32 {
        // The IDFT is zero outside the defined range [p59].
        if n < -(IDFT_HALF as isize) || n >= IDFT_HALF as isize {
            return 0.0;
        }

        let mut osc = QuadOsc::new(0.0, 2.0 / IDFT_SIZE as f32 * PI * n as f32);

        2.0 / IDFT_SIZE as f32 * self.0.iter().map(|x| {
            let (sin, cos) = osc.next();
            x.re * cos - x.im * sin
        }).fold(0.0, |s, x| s + x)
    }
}

impl Default for UnvoicedDFT {
    /// Create a new `UnvoicedDFT` in the default state.
    fn default() -> Self {
        // By default all IDFT values are zero [p64]. Setting the DFT values to zero will
        // derive this effect.
        UnvoicedDFT([Complex32::zero(); DFT_HALF])
    }
}

/// Synthesizes unvoiced spectrum signal suv(n).
pub struct Unvoiced<'a, 'b> {
    /// Unvoiced DFT/IDFT for current frame.
    cur: &'a UnvoicedDFT,
    /// Unvoiced DFT/IDFT for previous frame.
    prev: &'b UnvoicedDFT,
    /// Synthesis window ws(n) for "weighted overlap add".
    window: window::Window,
}

impl<'a, 'b> Unvoiced<'a, 'b> {
    /// Create a new `Unvoiced` from the given unvoiced spectrums of the current and
    /// previous frames.
    pub fn new(cur: &'a UnvoicedDFT, prev: &'b UnvoicedDFT) -> Self {
        Unvoiced {
            cur: cur,
            prev: prev,
            window: window::synthesis(),
        }
    }

    /// Compute the unvoiced signal sample suv(n) for the given n, 0 ≤ n < N.
    pub fn get(&self, n: usize) -> f32 {
        debug_assert!(n < SAMPLES_PER_FRAME);

        let n = n as isize;

        // Compute numerator in Eq 126.
        let numer = self.window.get(n) * self.prev.idft(n) +
            self.window.get(n - SAMPLES_PER_FRAME as isize) *
                self.cur.idft(n - SAMPLES_PER_FRAME as isize);

        // Compute denominator in Eq 126.
        let denom = self.window.get(n).powi(2) +
            self.window.get(n - SAMPLES_PER_FRAME as isize).powi(2);

        // Compute Eq 126.
        numer / denom
    }
}

/// Determine the lower and upper band edges (al, bl) for the given
/// harmonic of the fundamental frequency.
fn edges(l: usize, params: &BaseParams) -> (usize, usize) {
    let common = DFT_SIZE as f32 / (2.0 * PI) * params.fundamental;

    (
        // Compute Eq 122.
        (common * (l as f32 - 0.5)).ceil() as usize,
        // Compute Eq 123.
        (common * (l as f32 + 0.5)).ceil() as usize,
    )
}

#[cfg(test)]
mod test {
    use super::edges;
    use descramble::Bootstrap;
    use params::BaseParams;

    #[test]
    fn test_edges() {
        let chunks = [
            0b001000010010,
            0b110011001100,
            0b111000111000,
            0b111111111111,
            0b10100110101,
            0b00101111010,
            0b01110111011,
            0b00001000,
        ];

        let b = Bootstrap::new(&chunks);
        let p = BaseParams::new(b.unwrap_period());

        assert!((p.fundamental - 0.17575344).abs() < 0.000001);

        let (lower, upper) = edges(1, &p);
        assert_eq!(lower, 4);
        assert_eq!(upper, 11);

        let (lower, upper) = edges(2, &p);
        assert_eq!(lower, 11);
        assert_eq!(upper, 18);

        let (lower, upper) = edges(5, &p);
        assert_eq!(lower, 33);
        assert_eq!(upper, 40);

        let (lower, upper) = edges(8, &p);
        assert_eq!(lower, 54);
        assert_eq!(upper, 61);

        let (lower, upper) = edges(16, &p);
        assert_eq!(lower, 111);
        assert_eq!(upper, 119);
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate exonum_testkit;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum_derive;

use std::borrow::Cow;

use exonum::{
    api::node::public::explorer::{BlocksQuery, BlocksRange, TransactionQuery},
    blockchain::{
        ExecutionResult, Schema, Service, Transaction, TransactionContext, TransactionSet,
    },
    crypto::{gen_keypair, Hash, PublicKey, SecretKey},
    messages::{AnyTx, Message, Signed},
};
use exonum_merkledb::Snapshot;
use exonum_testkit::{ApiKind, TestKitBuilder};

mod proto;

// Simple service implementation.

const SERVICE_ID: u16 = 512;

#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::TxTimestamp")]
struct TxTimestamp {
    message: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, TransactionSet)]
enum TimestampingServiceTransactions {
    TxTimestamp(TxTimestamp),
}

impl TxTimestamp {
    fn sign(author: &PublicKey, message: &str, key: &SecretKey) -> Signed<AnyTx> {
        Message::sign_transaction(
            Self {
                message: message.to_owned(),
            },
            SERVICE_ID,
            *author,
            key,
        )
    }
}

struct TimestampingService;

impl Transaction for TxTimestamp {
    fn execute(&self, _context: TransactionContext) -> ExecutionResult {
        Ok(())
    }
}

impl Service for TimestampingService {
    fn service_name(&self) -> &str {
        "timestamping"
    }

    fn state_hash(&self, _: &dyn Snapshot) -> Vec<Hash> {
        Vec::new()
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: AnyTx) -> Result<Box<dyn Transaction>, failure::Error> {
        let tx = TimestampingServiceTransactions::tx_from_raw(raw)?;
        Ok(tx.into())
    }
}

fn main() {
    // Create testkit for network with four validators.
    let mut testkit = TestKitBuilder::validator()
        .with_validators(4)
        .with_service(TimestampingService)
        .create();
    // Create few transactions.
    let keypair = gen_keypair();
    let tx1 = TxTimestamp::sign(&keypair.0, "Down To Earth", &keypair.1);
    let tx2 = TxTimestamp::sign(&keypair.0, "Cry Over Spilt Milk", &keypair.1);
    let tx3 = TxTimestamp::sign(&keypair.0, "Dropping Like Flies", &keypair.1);

    // Commit them into blockchain.
    let block =
        testkit.create_block_with_transactions(txvec![tx1.clone(), tx2.clone(), tx3.clone(),]);
    assert_eq!(block.len(), 3);
    assert!(block.iter().all(|transaction| transaction.status().is_ok()));

    // Check results with schema.
    let snapshot = testkit.snapshot();
    let schema = Schema::new(&snapshot);
    assert!(schema.transactions().contains(&tx1.hash()));
    assert!(schema.transactions().contains(&tx2.hash()));
    assert!(schema.transactions().contains(&tx3.hash()));

    // Check results with api.
    let api = testkit.api();
    let blocks_range: BlocksRange = api
        .public(ApiKind::Explorer)
        .query(&BlocksQuery {
            count: 10,
            ..Default::default()
        })
        .get("v1/blocks")
        .unwrap();
    assert_eq!(blocks_range.blocks.len(), 2);

    api.public(ApiKind::Explorer)
        .query(&TransactionQuery { hash: tx1.hash() })
        .get::<serde_json::Value>("v1/transactions")
        .unwrap();
}
<commit_msg>Fix testkit examples compilation<commit_after>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate exonum_testkit;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum_derive;

use exonum::{
    api::node::public::explorer::{BlocksQuery, BlocksRange, TransactionQuery},
    blockchain::{ExecutionResult, Schema},
    crypto::{gen_keypair, PublicKey, SecretKey},
    impl_service_dispatcher,
    messages::{AnyTx, Message, Signed},
    runtime::{
        rust::{RustArtifactSpec, Service, ServiceFactory, TransactionContext},
        ServiceInstanceId,
    },
};
use exonum_merkledb::ObjectHash;
use exonum_testkit::{ApiKind, ServiceInstances, TestKitBuilder};

mod proto;

// Simple service implementation.

#[derive(Serialize, Deserialize, Clone, Debug, ProtobufConvert)]
#[exonum(pb = "proto::TxTimestamp")]
struct TxTimestamp {
    message: String,
}

impl TxTimestamp {
    fn sign(
        instance_id: ServiceInstanceId,
        author: &PublicKey,
        message: &str,
        key: &SecretKey,
    ) -> Signed<AnyTx> {
        Message::sign_transaction(
            Self {
                message: message.to_owned(),
            },
            instance_id,
            *author,
            key,
        )
    }
}

#[service_interface]
trait TimestampingInterface {
    fn timestamp(&self, context: TransactionContext, arg: TxTimestamp) -> ExecutionResult;
}

#[derive(Debug)]
struct TimestampingService;

impl TimestampingInterface for TimestampingService {
    fn timestamp(&self, _context: TransactionContext, _arg: TxTimestamp) -> ExecutionResult {
        Ok(())
    }
}

impl_service_dispatcher!(TimestampingService, TimestampingInterface);

impl Service for TimestampingService {}

impl ServiceFactory for TimestampingService {
    fn artifact(&self) -> RustArtifactSpec {
        "timestamping/1.0.0".parse().unwrap()
    }
    fn new_instance(&self) -> Box<dyn Service> {
        Box::new(Self)
    }
}

fn main() {
    let instance_id = 512;
    // Create testkit for network with four validators.
    let mut testkit = TestKitBuilder::validator()
        .with_validators(4)
        .with_service(ServiceInstances::new(TimestampingService).with_instance(
            "timestamping",
            instance_id,
            (),
        ))
        .create();
    // Create few transactions.
    let keypair = gen_keypair();
    let tx1 = TxTimestamp::sign(instance_id, &keypair.0, "Down To Earth", &keypair.1);
    let tx2 = TxTimestamp::sign(instance_id, &keypair.0, "Cry Over Spilt Milk", &keypair.1);
    let tx3 = TxTimestamp::sign(instance_id, &keypair.0, "Dropping Like Flies", &keypair.1);

    // Commit them into blockchain.
    let block =
        testkit.create_block_with_transactions(txvec![tx1.clone(), tx2.clone(), tx3.clone(),]);
    assert_eq!(block.len(), 3);
    assert!(block.iter().all(|transaction| transaction.status().is_ok()));

    // Check results with schema.
    let snapshot = testkit.snapshot();
    let schema = Schema::new(&snapshot);
    assert!(schema.transactions().contains(&tx1.object_hash()));
    assert!(schema.transactions().contains(&tx2.object_hash()));
    assert!(schema.transactions().contains(&tx3.object_hash()));

    // Check results with api.
    let api = testkit.api();
    let blocks_range: BlocksRange = api
        .public(ApiKind::Explorer)
        .query(&BlocksQuery {
            count: 10,
            ..Default::default()
        })
        .get("v1/blocks")
        .unwrap();
    assert_eq!(blocks_range.blocks.len(), 2);

    api.public(ApiKind::Explorer)
        .query(&TransactionQuery {
            hash: tx1.object_hash(),
        })
        .get::<serde_json::Value>("v1/transactions")
        .unwrap();
}
<|endoftext|>


<commit_before>/// # Plans
/// Current this uses raw bit operations to provide a packed representation
/// with an interface similar to [Option<T>; N]. Once integer generics land,
/// it can instead use an abstraction layer to provide operations. Hopefully
/// that can be maintained as a separate crate.

use std::marker::PhantomData;
use std::mem;
use std::ptr;
use super::traits::JpmNode;
use super::innerptr::InnerPtr;
use ::rudymap::results::{InsertResult, RemoveResult};
use ::Key;
use nodrop::NoDrop;

pub struct LeafBitmap<K: Key, V> {
    keys: [u8; 256 / 8],
    values: NoDrop<[V; 256]>,
    pd: PhantomData<K>
}

impl<K: Key, V> LeafBitmap<K, V> {
    pub fn new() -> LeafBitmap<K, V> {
        LeafBitmap {
            keys: [0; 256 / 8],
            values: unsafe { mem::zeroed() },
            pd: PhantomData
        }
    }
}

impl<K: Key, V> Drop for LeafBitmap<K, V> {
    fn drop(&mut self) {
        for index in 0..256 {
            let key: [u8; 1] = [index as u8];
            self.remove(&key).success();
        }
    }
}

#[derive(Debug)]
enum Place {
    Occupied(usize),
    Empty(usize)
}

fn singleton_index(key: &[u8], keys: &[u8; 256 / 8]) -> Place {
    debug_assert_eq!(key.len(), 1);
    let index = key[0] as usize;
    let occupied = keys[index / 8] & (1 << (index % 8));
    if occupied != 0 {
        Place::Occupied(index)
    } else {
        Place::Empty(index)
    }
}

impl<K: Key, V> JpmNode<K, V> for LeafBitmap<K, V> {
    fn get(&self, key: &[u8]) -> Option<&V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => Some(&self.values[index]),
            Place::Empty(index) => None
        }
    }

    fn get_mut(&mut self, key: &[u8]) -> Option<&mut V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => Some(&mut self.values[index]),
            Place::Empty(index) => None
        }
    }

    fn insert(&mut self, key: &[u8], value: V) -> InsertResult<V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => {
                let place = &mut self.values[index];
                InsertResult::replace(place, value)
            },
            Place::Empty(index) => {
                let place = &mut self.values[index];
                self.keys[index / 8] |= 1 << (index % 8);
                unsafe {
                    ptr::write(place, value);
                }
                InsertResult::Success(None)
            }
        }
    }

    fn expand(self, pop: usize, key: &[u8], value: V) -> InnerPtr<K, V> {
        unreachable!();
    }

    fn remove(&mut self, key: &[u8]) -> RemoveResult<V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => {
                let place = &mut self.values[index];
                let value = unsafe { ptr::read(place) };
                self.keys[index / 8] &= !(1 << (index % 8));
                RemoveResult::Success(Some(value))
            },
            Place::Empty(_) => {
                RemoveResult::Success(None)
            }
        }
    }

    fn shrink_remove(self, pop: usize, key: &[u8]) -> (InnerPtr<K, V>, V) {
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::atomic::{AtomicUsize,Ordering};

    struct Droppable<'a>(&'a AtomicUsize);
    impl<'a> Drop for Droppable<'a> {
        fn drop(&mut self) {
            self.0.fetch_add(1, Ordering::AcqRel);
        }
    }

    #[test]
    fn test_drop() {
        let drop_count = AtomicUsize::new(0);

        {
            // insert a single key
            let mut lb: LeafBitmap<u32, Droppable> = LeafBitmap::new();
            lb.insert(&[0], Droppable(&drop_count)).success();

            // inserting into an empty map should cause no drops
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // overwriting the key should drop the old key
            lb.insert(&[0], Droppable(&drop_count)).success();
            assert_eq!(drop_count.load(Ordering::Acquire), 1);
        }

        // dropping the LeafBitmap should drop its only value
        assert_eq!(drop_count.load(Ordering::Acquire), 2);

        // reset the counter
        drop_count.store(0, Ordering::Release);

        {
            let mut lb: LeafBitmap<u32, Droppable> = LeafBitmap::new();
            for i in 0..256 {
                lb.insert(&[i as u8], Droppable(&drop_count)).success();
            }

            // inserting a full bitmap should cause no drops
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // getting/get_muting should cause no drops
            lb.get(&[1]);
            lb.get_mut(&[2]);
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // removing one key should cause one drop
            lb.remove(&[42]).success();
            assert_eq!(drop_count.load(Ordering::Acquire), 1);
        }

        // discarding the LeafBitmap should drop the others
        assert_eq!(drop_count.load(Ordering::Acquire), 256);
    }
}<commit_msg>Update LeafBitmap drop to use drop_in_place()<commit_after>/// # Plans
/// Current this uses raw bit operations to provide a packed representation
/// with an interface similar to [Option<T>; N]. Once integer generics land,
/// it can instead use an abstraction layer to provide operations. Hopefully
/// that can be maintained as a separate crate.

use std::marker::PhantomData;
use std::mem;
use std::ptr;
use super::traits::JpmNode;
use super::innerptr::InnerPtr;
use ::rudymap::results::{InsertResult, RemoveResult};
use ::Key;
use nodrop::NoDrop;

pub struct LeafBitmap<K: Key, V> {
    keys: [u8; 256 / 8],
    values: NoDrop<[V; 256]>,
    pd: PhantomData<K>
}

impl<K: Key, V> LeafBitmap<K, V> {
    pub fn new() -> LeafBitmap<K, V> {
        LeafBitmap {
            keys: [0; 256 / 8],
            values: unsafe { mem::zeroed() },
            pd: PhantomData
        }
    }
}

impl<K: Key, V> Drop for LeafBitmap<K, V> {
    fn drop(&mut self) {
        for index in 0..256 {
            let occupied = self.keys[index / 8] & (1 << (index % 8));
            if occupied != 0 {
                let mut value = &mut self.values[index];
                unsafe {
                    ptr::drop_in_place(value as *mut V);
                }
            }
        }
    }
}

#[derive(Debug)]
enum Place {
    Occupied(usize),
    Empty(usize)
}

fn singleton_index(key: &[u8], keys: &[u8; 256 / 8]) -> Place {
    debug_assert_eq!(key.len(), 1);
    let index = key[0] as usize;
    let occupied = keys[index / 8] & (1 << (index % 8));
    if occupied != 0 {
        Place::Occupied(index)
    } else {
        Place::Empty(index)
    }
}

impl<K: Key, V> JpmNode<K, V> for LeafBitmap<K, V> {
    fn get(&self, key: &[u8]) -> Option<&V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => Some(&self.values[index]),
            Place::Empty(index) => None
        }
    }

    fn get_mut(&mut self, key: &[u8]) -> Option<&mut V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => Some(&mut self.values[index]),
            Place::Empty(index) => None
        }
    }

    fn insert(&mut self, key: &[u8], value: V) -> InsertResult<V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => {
                let place = &mut self.values[index];
                InsertResult::replace(place, value)
            },
            Place::Empty(index) => {
                let place = &mut self.values[index];
                self.keys[index / 8] |= 1 << (index % 8);
                unsafe {
                    ptr::write(place, value);
                }
                InsertResult::Success(None)
            }
        }
    }

    fn expand(self, pop: usize, key: &[u8], value: V) -> InnerPtr<K, V> {
        unreachable!();
    }

    fn remove(&mut self, key: &[u8]) -> RemoveResult<V> {
        match singleton_index(key, &self.keys) {
            Place::Occupied(index) => {
                let place = &mut self.values[index];
                let value = unsafe { ptr::read(place) };
                self.keys[index / 8] &= !(1 << (index % 8));
                RemoveResult::Success(Some(value))
            },
            Place::Empty(_) => {
                RemoveResult::Success(None)
            }
        }
    }

    fn shrink_remove(self, pop: usize, key: &[u8]) -> (InnerPtr<K, V>, V) {
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::atomic::{AtomicUsize,Ordering};

    struct Droppable<'a>(&'a AtomicUsize);
    impl<'a> Drop for Droppable<'a> {
        fn drop(&mut self) {
            self.0.fetch_add(1, Ordering::AcqRel);
        }
    }

    #[test]
    fn test_drop() {
        let drop_count = AtomicUsize::new(0);

        {
            // insert a single key
            let mut lb: LeafBitmap<u32, Droppable> = LeafBitmap::new();
            lb.insert(&[0], Droppable(&drop_count)).success();

            // inserting into an empty map should cause no drops
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // overwriting the key should drop the old key
            lb.insert(&[0], Droppable(&drop_count)).success();
            assert_eq!(drop_count.load(Ordering::Acquire), 1);
        }

        // dropping the LeafBitmap should drop its only value
        assert_eq!(drop_count.load(Ordering::Acquire), 2);

        // reset the counter
        drop_count.store(0, Ordering::Release);

        {
            let mut lb: LeafBitmap<u32, Droppable> = LeafBitmap::new();
            for i in 0..256 {
                lb.insert(&[i as u8], Droppable(&drop_count)).success();
            }

            // inserting a full bitmap should cause no drops
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // getting/get_muting should cause no drops
            lb.get(&[1]);
            lb.get_mut(&[2]);
            assert_eq!(drop_count.load(Ordering::Acquire), 0);

            // removing one key should cause one drop
            lb.remove(&[42]).success();
            assert_eq!(drop_count.load(Ordering::Acquire), 1);
        }

        // discarding the LeafBitmap should drop the others
        assert_eq!(drop_count.load(Ordering::Acquire), 256);
    }
}<|endoftext|>


<commit_before>use crate::syntax_highlighting::highlights::Highlights;
use crate::{HlRange, HlTag};
use syntax::ast::IsString;
use syntax::TextSize;

/// Highlight escape sequences
pub(super) fn highlight_escape_string<T: IsString>(
    stack: &mut Highlights,
    string: &T,
    start: TextSize,
) {
    string.escaped_char_ranges(&mut |piece_range, char| {
        if char.is_err() {
            return;
        }

        if string.text()[piece_range.start().into()..].starts_with('\\') {
            stack.add(HlRange {
                range: piece_range + start,
                highlight: HlTag::EscapeSequence.into(),
                binding_hash: None,
            });
        }
    });
}
<commit_msg>Fixed tidy test<commit_after>//! Syntax highlighting for escape sequences
use crate::syntax_highlighting::highlights::Highlights;
use crate::{HlRange, HlTag};
use syntax::ast::IsString;
use syntax::TextSize;

pub(super) fn highlight_escape_string<T: IsString>(
    stack: &mut Highlights,
    string: &T,
    start: TextSize,
) {
    string.escaped_char_ranges(&mut |piece_range, char| {
        if char.is_err() {
            return;
        }

        if string.text()[piece_range.start().into()..].starts_with('\\') {
            stack.add(HlRange {
                range: piece_range + start,
                highlight: HlTag::EscapeSequence.into(),
                binding_hash: None,
            });
        }
    });
}
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::convert::TryInto;
use std::io;
use std::ops::{Deref, DerefMut};
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
use std::task::{Context, Poll};

use crate::io_source::IoSource;
use crate::uring_executor::{self, Error, PendingOperation, RegisteredSource, Result};
use crate::uring_futures;
use crate::uring_mem::{BackingMemory, MemRegion};
use crate::AsyncError;
use crate::AsyncResult;
use async_trait::async_trait;

/// `UringSource` wraps FD backed IO sources for use with io_uring. It is a thin wrapper around
/// registering an IO source with the uring that provides an `IoSource` implementation.
/// Most useful functions are provided by 'IoSourceExt'.
///
/// # Example
/// ```rust
/// use std::fs::File;
/// use cros_async::{UringSource, ReadAsync};
///
/// async fn read_four_bytes(source: &UringSource<File>) -> (usize, Vec<u8>) {
///    let mem = vec![0u8; 4];
///    source.read_to_vec(0, mem).await.unwrap()
/// }
///
/// fn read_file(f: File) -> Result<(), Box<dyn std::error::Error>> {
///     let async_source = UringSource::new(f)?;
///     let read_future = read_four_bytes(&async_source);
///     futures::pin_mut!(read_future);
///     let (nread, vec) = cros_async::run_one_uring(read_future)?;
///     assert_eq!(nread, 4);
///     assert_eq!(vec.len(), 4);
///     Ok(())
/// }
/// ```
pub struct UringSource<F: AsRawFd> {
    registered_source: RegisteredSource,
    source: F,
}

impl<F: AsRawFd> UringSource<F> {
    /// Creates a new `UringSource` that wraps the given `io_source` object.
    pub fn new(io_source: F) -> Result<UringSource<F>> {
        let r = uring_executor::register_source(&io_source)?;
        Ok(UringSource {
            registered_source: r,
            source: io_source,
        })
    }

    /// Consume `self` and return the object used to create it.
    pub fn into_source(self) -> F {
        self.source
    }
}

impl<F: AsRawFd> IoSource for UringSource<F> {
    fn read_to_mem(
        &self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &[MemRegion],
    ) -> Result<PendingOperation> {
        self.registered_source
            .start_read_to_mem(file_offset, mem, mem_offsets)
    }

    fn write_from_mem(
        &self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &[MemRegion],
    ) -> Result<PendingOperation> {
        self.registered_source
            .start_write_from_mem(file_offset, mem, mem_offsets)
    }

    fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> Result<PendingOperation> {
        self.registered_source
            .start_fallocate(file_offset, len, mode)
    }

    fn fsync(&self) -> Result<PendingOperation> {
        self.registered_source.start_fsync()
    }

    // wait for the inner source to be readable and return a refernce to it.
    fn wait_readable(&self) -> Result<PendingOperation> {
        self.registered_source.poll_fd_readable()
    }

    fn poll_complete(&self, cx: &mut Context, token: &mut PendingOperation) -> Poll<Result<u32>> {
        self.registered_source.poll_complete(cx, token)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::ReadAsync for UringSource<F> {
    /// Reads from the iosource at `file_offset` and fill the given `vec`.
    async fn read_to_vec<'a>(
        &'a self,
        file_offset: u64,
        vec: Vec<u8>,
    ) -> AsyncResult<(usize, Vec<u8>)> {
        uring_futures::ReadVec::new(self, file_offset, vec)
            .await
            .map(|(n, vec)| (n as usize, vec))
            .map_err(AsyncError::Uring)
    }

    /// Wait for the FD of `self` to be readable.
    async fn wait_readable(&self) -> AsyncResult<()> {
        uring_futures::PollFd::new(self)
            .await
            .map_err(AsyncError::Uring)
    }

    /// Reads a single u64 (e.g. from an eventfd).
    async fn read_u64(&self) -> AsyncResult<u64> {
        let bytes = 0u64.to_ne_bytes().to_vec();
        let (len, bytes) = self.read_to_vec(0, bytes).await?;
        if len != bytes.len() {
            Err(AsyncError::Uring(Error::Io(io::Error::new(
                io::ErrorKind::Other,
                format!("expected to read {} bytes, but read {}", bytes.len(), len),
            ))))
        } else {
            // Will never panic because bytes is of the appropriate size.
            Ok(u64::from_ne_bytes(bytes[..].try_into().unwrap()))
        }
    }

    /// Reads to the given `mem` at the given offsets from the file starting at `file_offset`.
    async fn read_to_mem<'a>(
        &'a self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &'a [MemRegion],
    ) -> AsyncResult<usize> {
        uring_futures::ReadMem::new(self, file_offset, mem, mem_offsets)
            .await
            .map(|n| n as usize)
            .map_err(AsyncError::Uring)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::WriteAsync for UringSource<F> {
    /// Writes from the given `vec` to the file starting at `file_offset`.
    async fn write_from_vec<'a>(
        &'a self,
        file_offset: u64,
        vec: Vec<u8>,
    ) -> AsyncResult<(usize, Vec<u8>)> {
        uring_futures::WriteVec::new(self, file_offset, vec)
            .await
            .map(|(n, vec)| (n as usize, vec))
            .map_err(AsyncError::Uring)
    }

    /// Writes from the given `mem` from the given offsets to the file starting at `file_offset`.
    async fn write_from_mem<'a>(
        &'a self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &'a [MemRegion],
    ) -> AsyncResult<usize> {
        uring_futures::WriteMem::new(self, file_offset, mem, mem_offsets)
            .await
            .map(|n| n as usize)
            .map_err(AsyncError::Uring)
    }

    /// See `fallocate(2)`. Note this op is synchronous when using the Polled backend.
    async fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> AsyncResult<()> {
        uring_futures::Fallocate::new(self, file_offset, len, mode)
            .await
            .map_err(AsyncError::Uring)
    }

    /// Sync all completed write operations to the backing storage.
    async fn fsync(&self) -> AsyncResult<()> {
        uring_futures::Fsync::new(self)
            .await
            .map_err(AsyncError::Uring)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::IoSourceExt<F> for UringSource<F> {
    /// Yields the underlying IO source.
    fn into_source(self: Box<Self>) -> F {
        self.source
    }

    /// Provides a mutable ref to the underlying IO source.
    fn as_source(&self) -> &F {
        &self.source
    }

    /// Provides a ref to the underlying IO source.
    fn as_source_mut(&mut self) -> &mut F {
        &mut self.source
    }
}

impl<F: AsRawFd> Deref for UringSource<F> {
    type Target = F;

    fn deref(&self) -> &Self::Target {
        &self.source
    }
}

impl<F: AsRawFd> DerefMut for UringSource<F> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.source
    }
}

#[cfg(test)]
mod tests {
    use futures::pin_mut;
    use std::future::Future;
    use std::pin::Pin;

    use super::*;

    enum MemTestState<'a> {
        Init {
            file_offset: u64,
            mem: Rc<dyn BackingMemory>,
            mem_offsets: &'a [MemRegion],
        },
        Wait {
            token: PendingOperation,
        },
        Idle,
    }

    pub struct TestRead<'a, F: AsRawFd + Unpin> {
        inner: &'a UringSource<F>,
        state: MemTestState<'a>,
    }

    impl<'a, F: AsRawFd + Unpin> TestRead<'a, F> {
        fn new(
            io: &'a UringSource<F>,
            file_offset: u64,
            mem: Rc<dyn BackingMemory>,
            mem_offsets: &'a [MemRegion],
        ) -> Self {
            TestRead {
                inner: io,
                state: MemTestState::Init {
                    file_offset,
                    mem,
                    mem_offsets,
                },
            }
        }
    }

    impl<'a, F: AsRawFd + Unpin> Future for TestRead<'a, F> {
        type Output = Result<u32>;

        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            use MemTestState::*;

            let mut state = match std::mem::replace(&mut self.state, Idle) {
                Init {
                    file_offset,
                    mem,
                    mem_offsets,
                } => match Pin::new(self.inner).read_to_mem(file_offset, mem, mem_offsets) {
                    Ok(token) => Wait { token },
                    Err(e) => return Poll::Ready(Err(e)),
                },
                Idle => Idle,
                Wait { token } => Wait { token },
            };

            let ret = match &mut state {
                Wait { token } => Pin::new(self.inner).poll_complete(cx, token),
                _ => panic!("Invalid state in future"),
            };
            self.state = state;
            ret
        }
    }

    #[test]
    fn read_to_mem() {
        use vm_memory::{GuestAddress, GuestMemory};

        use crate::uring_mem::VecIoWrapper;

        let io_obj = Box::pin({
            // Use guest memory as a test file, it implements AsRawFd.
            let source = GuestMemory::new(&[(GuestAddress(0), 8192)]).unwrap();
            source
                .get_slice_at_addr(GuestAddress(0), 8192)
                .unwrap()
                .write_bytes(0x55);
            UringSource::new(source).unwrap()
        });

        // Start with memory filled with 0x44s.
        let buf: Rc<VecIoWrapper> = Rc::new(VecIoWrapper::from(vec![0x44; 8192]));

        let fut = TestRead::new(
            &io_obj,
            0,
            Rc::<VecIoWrapper>::clone(&buf),
            &[MemRegion {
                offset: 0,
                len: 8192,
            }],
        );
        pin_mut!(fut);
        assert_eq!(8192, crate::run_one_uring(fut).unwrap().unwrap());
        let vec: Vec<u8> = match Rc::try_unwrap(buf) {
            Ok(v) => v.into(),
            Err(_) => panic!("Too many vec refs"),
        };
        assert!(vec.iter().all(|&b| b == 0x55));
    }
}
<commit_msg>cros_async: fix unittest for uring<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::convert::TryInto;
use std::io;
use std::ops::{Deref, DerefMut};
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
use std::task::{Context, Poll};

use crate::io_source::IoSource;
use crate::uring_executor::{self, Error, PendingOperation, RegisteredSource, Result};
use crate::uring_futures;
use crate::uring_mem::{BackingMemory, MemRegion};
use crate::AsyncError;
use crate::AsyncResult;
use async_trait::async_trait;

/// `UringSource` wraps FD backed IO sources for use with io_uring. It is a thin wrapper around
/// registering an IO source with the uring that provides an `IoSource` implementation.
/// Most useful functions are provided by 'IoSourceExt'.
///
/// # Example
/// ```rust
/// use std::fs::File;
/// use cros_async::{UringSource, ReadAsync};
///
/// async fn read_four_bytes(source: &UringSource<File>) -> (usize, Vec<u8>) {
///    let mem = vec![0u8; 4];
///    source.read_to_vec(0, mem).await.unwrap()
/// }
///
/// fn read_file(f: File) -> Result<(), Box<dyn std::error::Error>> {
///     let async_source = UringSource::new(f)?;
///     let read_future = read_four_bytes(&async_source);
///     futures::pin_mut!(read_future);
///     let (nread, vec) = cros_async::run_one_uring(read_future)?;
///     assert_eq!(nread, 4);
///     assert_eq!(vec.len(), 4);
///     Ok(())
/// }
/// ```
pub struct UringSource<F: AsRawFd> {
    registered_source: RegisteredSource,
    source: F,
}

impl<F: AsRawFd> UringSource<F> {
    /// Creates a new `UringSource` that wraps the given `io_source` object.
    pub fn new(io_source: F) -> Result<UringSource<F>> {
        let r = uring_executor::register_source(&io_source)?;
        Ok(UringSource {
            registered_source: r,
            source: io_source,
        })
    }

    /// Consume `self` and return the object used to create it.
    pub fn into_source(self) -> F {
        self.source
    }
}

impl<F: AsRawFd> IoSource for UringSource<F> {
    fn read_to_mem(
        &self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &[MemRegion],
    ) -> Result<PendingOperation> {
        self.registered_source
            .start_read_to_mem(file_offset, mem, mem_offsets)
    }

    fn write_from_mem(
        &self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &[MemRegion],
    ) -> Result<PendingOperation> {
        self.registered_source
            .start_write_from_mem(file_offset, mem, mem_offsets)
    }

    fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> Result<PendingOperation> {
        self.registered_source
            .start_fallocate(file_offset, len, mode)
    }

    fn fsync(&self) -> Result<PendingOperation> {
        self.registered_source.start_fsync()
    }

    // wait for the inner source to be readable and return a refernce to it.
    fn wait_readable(&self) -> Result<PendingOperation> {
        self.registered_source.poll_fd_readable()
    }

    fn poll_complete(&self, cx: &mut Context, token: &mut PendingOperation) -> Poll<Result<u32>> {
        self.registered_source.poll_complete(cx, token)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::ReadAsync for UringSource<F> {
    /// Reads from the iosource at `file_offset` and fill the given `vec`.
    async fn read_to_vec<'a>(
        &'a self,
        file_offset: u64,
        vec: Vec<u8>,
    ) -> AsyncResult<(usize, Vec<u8>)> {
        uring_futures::ReadVec::new(self, file_offset, vec)
            .await
            .map(|(n, vec)| (n as usize, vec))
            .map_err(AsyncError::Uring)
    }

    /// Wait for the FD of `self` to be readable.
    async fn wait_readable(&self) -> AsyncResult<()> {
        uring_futures::PollFd::new(self)
            .await
            .map_err(AsyncError::Uring)
    }

    /// Reads a single u64 (e.g. from an eventfd).
    async fn read_u64(&self) -> AsyncResult<u64> {
        let bytes = 0u64.to_ne_bytes().to_vec();
        let (len, bytes) = self.read_to_vec(0, bytes).await?;
        if len != bytes.len() {
            Err(AsyncError::Uring(Error::Io(io::Error::new(
                io::ErrorKind::Other,
                format!("expected to read {} bytes, but read {}", bytes.len(), len),
            ))))
        } else {
            // Will never panic because bytes is of the appropriate size.
            Ok(u64::from_ne_bytes(bytes[..].try_into().unwrap()))
        }
    }

    /// Reads to the given `mem` at the given offsets from the file starting at `file_offset`.
    async fn read_to_mem<'a>(
        &'a self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &'a [MemRegion],
    ) -> AsyncResult<usize> {
        uring_futures::ReadMem::new(self, file_offset, mem, mem_offsets)
            .await
            .map(|n| n as usize)
            .map_err(AsyncError::Uring)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::WriteAsync for UringSource<F> {
    /// Writes from the given `vec` to the file starting at `file_offset`.
    async fn write_from_vec<'a>(
        &'a self,
        file_offset: u64,
        vec: Vec<u8>,
    ) -> AsyncResult<(usize, Vec<u8>)> {
        uring_futures::WriteVec::new(self, file_offset, vec)
            .await
            .map(|(n, vec)| (n as usize, vec))
            .map_err(AsyncError::Uring)
    }

    /// Writes from the given `mem` from the given offsets to the file starting at `file_offset`.
    async fn write_from_mem<'a>(
        &'a self,
        file_offset: u64,
        mem: Rc<dyn BackingMemory>,
        mem_offsets: &'a [MemRegion],
    ) -> AsyncResult<usize> {
        uring_futures::WriteMem::new(self, file_offset, mem, mem_offsets)
            .await
            .map(|n| n as usize)
            .map_err(AsyncError::Uring)
    }

    /// See `fallocate(2)`. Note this op is synchronous when using the Polled backend.
    async fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> AsyncResult<()> {
        uring_futures::Fallocate::new(self, file_offset, len, mode)
            .await
            .map_err(AsyncError::Uring)
    }

    /// Sync all completed write operations to the backing storage.
    async fn fsync(&self) -> AsyncResult<()> {
        uring_futures::Fsync::new(self)
            .await
            .map_err(AsyncError::Uring)
    }
}

#[async_trait(?Send)]
impl<F: AsRawFd> crate::IoSourceExt<F> for UringSource<F> {
    /// Yields the underlying IO source.
    fn into_source(self: Box<Self>) -> F {
        self.source
    }

    /// Provides a mutable ref to the underlying IO source.
    fn as_source(&self) -> &F {
        &self.source
    }

    /// Provides a ref to the underlying IO source.
    fn as_source_mut(&mut self) -> &mut F {
        &mut self.source
    }
}

impl<F: AsRawFd> Deref for UringSource<F> {
    type Target = F;

    fn deref(&self) -> &Self::Target {
        &self.source
    }
}

impl<F: AsRawFd> DerefMut for UringSource<F> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.source
    }
}

#[cfg(test)]
mod tests {
    use futures::pin_mut;
    use std::future::Future;
    use std::pin::Pin;

    use super::*;

    enum MemTestState<'a> {
        Init {
            file_offset: u64,
            mem: Rc<dyn BackingMemory>,
            mem_offsets: &'a [MemRegion],
        },
        Wait {
            token: PendingOperation,
        },
        Idle,
    }

    pub struct TestRead<'a, F: AsRawFd + Unpin> {
        inner: &'a UringSource<F>,
        state: MemTestState<'a>,
    }

    impl<'a, F: AsRawFd + Unpin> TestRead<'a, F> {
        fn new(
            io: &'a UringSource<F>,
            file_offset: u64,
            mem: Rc<dyn BackingMemory>,
            mem_offsets: &'a [MemRegion],
        ) -> Self {
            TestRead {
                inner: io,
                state: MemTestState::Init {
                    file_offset,
                    mem,
                    mem_offsets,
                },
            }
        }
    }

    impl<'a, F: AsRawFd + Unpin> Future for TestRead<'a, F> {
        type Output = Result<u32>;

        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            use MemTestState::*;

            let mut state = match std::mem::replace(&mut self.state, Idle) {
                Init {
                    file_offset,
                    mem,
                    mem_offsets,
                } => match Pin::new(self.inner).read_to_mem(file_offset, mem, mem_offsets) {
                    Ok(token) => Wait { token },
                    Err(e) => return Poll::Ready(Err(e)),
                },
                Idle => Idle,
                Wait { token } => Wait { token },
            };

            let ret = match &mut state {
                Wait { token } => Pin::new(self.inner).poll_complete(cx, token),
                _ => panic!("Invalid state in future"),
            };
            self.state = state;
            ret
        }
    }

    #[test]
    fn read_to_mem() {
        use crate::uring_mem::VecIoWrapper;
        use std::io::Write;
        use tempfile::tempfile;

        let io_obj = Box::pin({
            // Use guest memory as a test file, it implements AsRawFd.
            let mut source = tempfile().unwrap();
            let data = vec![0x55; 8192];
            source.write(&data).unwrap();
            UringSource::new(source).unwrap()
        });

        // Start with memory filled with 0x44s.
        let buf: Rc<VecIoWrapper> = Rc::new(VecIoWrapper::from(vec![0x44; 8192]));

        let fut = TestRead::new(
            &io_obj,
            0,
            Rc::<VecIoWrapper>::clone(&buf),
            &[MemRegion {
                offset: 0,
                len: 8192,
            }],
        );
        pin_mut!(fut);
        assert_eq!(8192, crate::run_one_uring(fut).unwrap().unwrap());
        let vec: Vec<u8> = match Rc::try_unwrap(buf) {
            Ok(v) => v.into(),
            Err(_) => panic!("Too many vec refs"),
        };
        assert!(vec.iter().all(|&b| b == 0x55));
    }
}
<|endoftext|>


<commit_before>extern crate protoc;

use std::ffi::OsString;
use std::io::Result;
use std::path::PathBuf;

fn main() -> Result<()> {
    let exe_suffix = if cfg!(windows) {
        ".exe"
    } else if cfg!(unix) {
        ""
    } else {
        panic!("unknown OS")
    };

    let gen_rust_binary = format!("../../target/debug/protoc-gen-rust{}", exe_suffix);
    let gen_rust_binary = PathBuf::from(gen_rust_binary).canonicalize()?;

    assert!(gen_rust_binary.is_file(), "{:?}", gen_rust_binary);

    let mut gen_rust_plugin = OsString::from("protoc-gen-rust=");
    gen_rust_plugin.push(gen_rust_binary);

    protoc::Args::new()
        .lang("rust")
        .out_dir("src")
        .plugin(gen_rust_plugin)
        .input("src/data.proto")
        .run()?;

    Ok(())
}
<commit_msg>Link to the right cargo issue<commit_after>extern crate protoc;

use std::ffi::OsString;
use std::io::Result;
use std::path::PathBuf;

fn main() -> Result<()> {
    let exe_suffix = if cfg!(windows) {
        ".exe"
    } else if cfg!(unix) {
        ""
    } else {
        panic!("unknown OS")
    };

    // TODO: https://github.com/rust-lang/cargo/issues/4316

    let gen_rust_binary = format!("../../target/debug/protoc-gen-rust{}", exe_suffix);
    let gen_rust_binary = PathBuf::from(gen_rust_binary).canonicalize()?;

    assert!(gen_rust_binary.is_file(), "{:?}", gen_rust_binary);

    let mut gen_rust_plugin = OsString::from("protoc-gen-rust=");
    gen_rust_plugin.push(gen_rust_binary);

    protoc::Args::new()
        .lang("rust")
        .out_dir("src")
        .plugin(gen_rust_plugin)
        .input("src/data.proto")
        .run()?;

    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::IoResult;
use std::io::stdio::{self, StdWriter};
use board::{Board, Edge, Side};
use geom::{Geom, Point, UP, LEFT};
use term::{self, Terminal, WriterWrapper};
use term::color::{self, Color};

enum Output<T> {
    Pretty(Box<Terminal<WriterWrapper> + Send>),
    Raw(T)
}

fn side_to_color(ty: Option<Side>) -> (Color, Color) {
    match ty {
        Some(Side::In)  => (color::BRIGHT_YELLOW, color::BLACK),
        Some(Side::Out) => (color::BLACK,         color::BRIGHT_WHITE),
        None            => (color::BRIGHT_WHITE,  color::BLACK),
    }
}

struct Printer<'a> {
    output: Output<StdWriter>,
    board: &'a Board
}

impl<'a> Printer<'a> {
    fn new(board: &'a Board) -> Printer<'a> {
        let output = if stdio::stdout_raw().isatty() {
            match term::stdout() {
                Some(t) => Output::Pretty(t),
                None    => Output::Raw(stdio::stdout_raw())
            }
        } else {
            Output::Raw(stdio::stdout_raw())
        };
        Printer { output: output, board: board }
    }

    fn write_pretty(&mut self, ty: Option<Side>, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write(s.as_bytes()));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }
    fn write_pretty_fmt(&mut self, ty: Option<Side>, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write_fmt(fmt));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }
    fn write_plain(&mut self, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write(s.as_bytes()),
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }

    fn write_plain_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write_fmt(fmt),
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }

    fn print(&mut self) -> IoResult<()> {
        let row = self.board.row();
        try!(self.label_row());
        for y in (0 .. row) {
            try!(self.edge_row(y));
            try!(self.cell_row(y));
        }
        try!(self.edge_row(row));
        try!(self.label_row());
        Ok(())
    }

    fn label_row(&mut self) -> IoResult<()> {
        try!(self.write_plain("  "));
        for x in 0 .. self.board.column() {
            try!(self.write_plain_fmt(format_args!(" {:2}", x)));
        }
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn edge_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain("  "));
        for x in (0 .. col) {
            try!(self.corner(Point(y, x)));
            try!(self.edge_h(Point(y, x)));
        }
        try!(self.corner(Point(y, col)));
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn cell_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain_fmt(format_args!("{:2}", y)));
        for x in (0 .. col) {
            try!(self.edge_v(Point(y, x)));
            try!(self.cell(Point(y, x)));
        }
        try!(self.edge_v(Point(y, col)));
        try!(self.write_plain_fmt(format_args!("{:2}\n", y)));
        Ok(())
    }

    fn corner(&mut self, p: Point) -> IoResult<()> {
        let is_same_all =
            (self.board.edge_h()[p] == Some(Edge::Cross)) &&
            (self.board.edge_h()[p + LEFT] == Some(Edge::Cross)) &&
            (self.board.edge_v()[p] == Some((Edge::Cross))) &&
            (self.board.edge_v()[p + UP] == Some((Edge::Cross)));

        let ty = if is_same_all {
            self.board.side()[p]
        } else {
            None
        };
        try!(self.write_pretty(ty, "+"));
        Ok(())
    }

    fn edge_h(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_h()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("-", None),
            None => ("~", None)
        };
        try!(self.write_pretty_fmt(ty, format_args!("{}{}", s, s)));
        Ok(())
    }

    fn edge_v(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_v()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("|", None),
            None => ("?", None)
        };
        try!(self.write_pretty(ty, s));
        Ok(())
    }

    fn cell(&mut self, p: Point) -> IoResult<()> {
        let ty = self.board.side()[p];
        match self.board[p] {
            Some(x) => try!(self.write_pretty_fmt(ty, format_args!("{} ", x))),
            None    => try!(self.write_pretty(ty, "  "))
        }
        Ok(())
    }
}

pub fn print(board: &Board) -> IoResult<()> {
    Printer::new(board).print()
}

<commit_msg>tweak pretty print<commit_after>use std::fmt;
use std::io::IoResult;
use std::io::stdio::{self, StdWriter};
use board::{Board, Edge, Side};
use geom::{Geom, Point, UP, LEFT};
use term::{self, Terminal, WriterWrapper};
use term::color::{self, Color};

enum Output<T> {
    Pretty(Box<Terminal<WriterWrapper> + Send>),
    Raw(T)
}

fn side_to_color(ty: Option<Side>) -> (Color, Color) {
    match ty {
        Some(Side::In)  => (color::BRIGHT_YELLOW, color::BLACK),
        Some(Side::Out) => (color::BLACK,         color::BRIGHT_WHITE),
        None            => (color::BRIGHT_WHITE,  color::BLACK),
    }
}

struct Printer<'a> {
    output: Output<StdWriter>,
    board: &'a Board
}

impl<'a> Printer<'a> {
    fn new(board: &'a Board) -> Printer<'a> {
        let output = if stdio::stdout_raw().isatty() {
            match term::stdout() {
                Some(t) => Output::Pretty(t),
                None    => Output::Raw(stdio::stdout_raw())
            }
        } else {
            Output::Raw(stdio::stdout_raw())
        };
        Printer { output: output, board: board }
    }

    fn write_pretty(&mut self, ty: Option<Side>, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write(s.as_bytes()));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }
    fn write_pretty_fmt(&mut self, ty: Option<Side>, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => {
                let (bg, fg) = side_to_color(ty);
                try!(term.fg(fg));
                try!(term.bg(bg));
                try!(term.write_fmt(fmt));
                try!(term.reset());
                Ok(())
            }
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }
    fn write_plain(&mut self, s: &str) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write(s.as_bytes()),
            Output::Raw(ref mut stdout) => stdout.write(s.as_bytes())
        }
    }

    fn write_plain_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
        match self.output {
            Output::Pretty(ref mut term) => term.write_fmt(fmt),
            Output::Raw(ref mut stdout) => stdout.write_fmt(fmt)
        }
    }

    fn print(&mut self) -> IoResult<()> {
        let row = self.board.row();
        try!(self.label_row());
        for y in (0 .. row) {
            try!(self.edge_row(y));
            try!(self.cell_row(y));
        }
        try!(self.edge_row(row));
        try!(self.label_row());
        Ok(())
    }

    fn label_row(&mut self) -> IoResult<()> {
        try!(self.write_plain("  "));
        for x in 0 .. self.board.column() {
            try!(self.write_plain_fmt(format_args!(" {:2}", x)));
        }
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn edge_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain("  "));
        for x in (0 .. col) {
            try!(self.corner(Point(y, x)));
            try!(self.edge_h(Point(y, x)));
        }
        try!(self.corner(Point(y, col)));
        try!(self.write_plain("\n"));
        Ok(())
    }

    fn cell_row(&mut self, y: i32) -> IoResult<()> {
        let col = self.board.column();
        try!(self.write_plain_fmt(format_args!("{:2}", y)));
        for x in (0 .. col) {
            try!(self.edge_v(Point(y, x)));
            try!(self.cell(Point(y, x)));
        }
        try!(self.edge_v(Point(y, col)));
        try!(self.write_plain_fmt(format_args!("{:2}\n", y)));
        Ok(())
    }

    fn corner(&mut self, p: Point) -> IoResult<()> {
        let l = p + LEFT;
        let u = p + UP;
        let is_same_all =
            (self.board.edge_h()[p] == Some(Edge::Cross)) &&
            (self.board.edge_h()[l] == Some(Edge::Cross)) &&
            (self.board.edge_v()[p] == Some((Edge::Cross))) &&
            (self.board.edge_v()[u] == Some((Edge::Cross)));

        let ty = if is_same_all {
            self.board.side()[p]
        } else {
            None
        };
        let is_h = self.board.edge_h()[p] == Some(Edge::Line) &&
            self.board.edge_h()[l] == Some(Edge::Line);
        let is_v = self.board.edge_v()[p] == Some(Edge::Line) &&
            self.board.edge_v()[u] == Some(Edge::Line);

        if is_same_all {
            try!(self.write_pretty(ty, "."));
        } else if is_h {
            try!(self.write_pretty(ty, "-"));
        } else if is_v {
            try!(self.write_pretty(ty, "|"));
        } else {
            try!(self.write_pretty(ty, "+"));
        }
        Ok(())
    }

    fn edge_h(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_h()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("-", None),
            None => ("~", None)
        };
        try!(self.write_pretty_fmt(ty, format_args!("{}{}", s, s)));
        Ok(())
    }

    fn edge_v(&mut self, p: Point) -> IoResult<()> {
        let (s, ty) = match self.board.edge_v()[p] {
            Some(Edge::Cross) => (" ", self.board.side()[p]),
            Some(Edge::Line)  => ("|", None),
            None => ("?", None)
        };
        try!(self.write_pretty(ty, s));
        Ok(())
    }

    fn cell(&mut self, p: Point) -> IoResult<()> {
        let ty = self.board.side()[p];
        match self.board[p] {
            Some(x) => try!(self.write_pretty_fmt(ty, format_args!("{} ", x))),
            None    => try!(self.write_pretty(ty, "  "))
        }
        Ok(())
    }
}

pub fn print(board: &Board) -> IoResult<()> {
    Printer::new(board).print()
}

<|endoftext|>


<commit_before><commit_msg>Fixed a typo<commit_after><|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

pub use ruma_identifiers::{
    device_id, device_key_id, event_id, mxc_uri, room_alias_id, room_id, room_version_id,
    server_name, server_signing_key_id, user_id, ClientSecret, DeviceId, DeviceKeyAlgorithm,
    DeviceKeyId, DeviceSignatures, DeviceSigningKeyId, EntitySignatures, EventEncryptionAlgorithm,
    EventId, KeyId, KeyName, MxcUri, RoomAliasId, RoomId, RoomOrAliasId, RoomVersionId, ServerName,
    ServerSignatures, ServerSigningKeyId, SessionId, Signatures, SigningKeyAlgorithm,
    TransactionId, UserId,
};

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://matrix.org/docs/spec/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<commit_msg>ruma: Re-export ruma_identifiers::matrix_uri<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

pub use ruma_identifiers::{
    device_id, device_key_id, event_id, matrix_uri, mxc_uri, room_alias_id, room_id,
    room_version_id, server_name, server_signing_key_id, user_id, ClientSecret, DeviceId,
    DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId, EntitySignatures,
    EventEncryptionAlgorithm, EventId, KeyId, KeyName, MatrixToUri, MxcUri, RoomAliasId, RoomId,
    RoomOrAliasId, RoomVersionId, ServerName, ServerSignatures, ServerSigningKeyId, SessionId,
    Signatures, SigningKeyAlgorithm, TransactionId, UserId,
};

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://matrix.org/docs/spec/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;
//use gif::traits::SetParameter;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path) }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<commit_msg>TODO note<commit_after>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;
//use gif::traits::SetParameter;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path) }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        // TODO: Remove?
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        handle_on_update(&mut self.ui, &mut self.new_game, &mut self.exit);
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}

fn handle_on_update(ui: &mut conrod::Ui<piston_window::Glyphs>, new_game: &mut bool, exit: &mut bool) {
    ui.set_widgets(|ui| {
        conrod::Canvas::new()
            .pad(30.)
            .color(conrod::color::rgb(0.2, 0.35, 0.45))
            .scroll_kids()
            .set(CANVAS, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .rgb(0.4, 0.75, 0.6)
            .label("New game")
            .react(|| *new_game = true)
            .set(NEW_GAME_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(NEW_GAME_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .label("Options")
            .react(|| ())
            .set(OPTIONS_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(OPTIONS_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .label("Exit")
            .react(|| *exit = true)
            .set(EXIT_BUTTON, ui);
    });
}
<commit_msg>Main menu screen: State enum<commit_after>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

enum State {
    NewGame,
    Options,
    Exit,
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        handle_on_update(&mut self.ui, &mut self.new_game, &mut self.exit);
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}

fn handle_on_update(ui: &mut conrod::Ui<piston_window::Glyphs>, new_game: &mut bool, exit: &mut bool) {
    ui.set_widgets(|ui| {
        conrod::Canvas::new()
            .pad(30.)
            .color(conrod::color::rgb(0.2, 0.35, 0.45))
            .scroll_kids()
            .set(CANVAS, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .rgb(0.4, 0.75, 0.6)
            .label("New game")
            .react(|| *new_game = true)
            .set(NEW_GAME_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(NEW_GAME_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .label("Options")
            .react(|| ())
            .set(OPTIONS_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(OPTIONS_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .label("Exit")
            .react(|| *exit = true)
            .set(EXIT_BUTTON, ui);
    });
}
<|endoftext|>


<commit_before>#![cfg_attr(test, feature(plugin))]
#![cfg_attr(test, plugin(quickcheck_macros))]

extern crate progress;

extern crate quickcheck;

use progress::Progress;

use quickcheck::TestResult;

#[test]
fn generated_with_default_values() {
    let p = Progress::default();

    assert_eq!(0, p.current());
    assert_eq!(100, p.total());
}

#[quickcheck]
fn creates_progress_bar(c: usize, t: usize) -> bool {
    let p = Progress::new(c, t);

    (p.current() == c) && (p.total() == t)
}

#[quickcheck]
fn increments_one(c: usize, t: usize) -> TestResult {
    if c >= t { return TestResult::discard() }
    let mut p = Progress::new(c, t);
    p.increment();
    TestResult::from_bool(p.current() == c + 1)
}

#[quickcheck]
fn do_not_increment_above_total(t: usize) -> bool {
    let mut p = Progress::new(t, t);
    p.increment();
    p.current() == p.total()
}

#[quickcheck]
fn decrements_one(c: usize, t: usize) -> TestResult {
    if c == 0 { return TestResult::discard() }
    let mut p = Progress::new(c, t);
    p.decrement();
    TestResult::from_bool(p.current() == c - 1)
}

#[quickcheck]
fn do_not_decrement_below_zero(t: usize) -> bool {
    let mut p = Progress::new(0, t);
    p.decrement();
    p.current() == 0
}

#[quickcheck]
fn not_finished_while_in_progress(c: usize, t: usize) -> TestResult {
    if c >= t { return TestResult::discard() }
    let p = Progress::new(c, t);
    TestResult::from_bool(!p.finished())
}

#[quickcheck]
fn finished_when_finished(t: usize) -> bool {
    let p = Progress::new(t, t);
    p.finished()
}
<commit_msg>Use builder in tests<commit_after>#![cfg_attr(test, feature(plugin))]
#![cfg_attr(test, plugin(quickcheck_macros))]

extern crate progress;

extern crate quickcheck;

use progress::builder::ProgressBuilder;

use quickcheck::TestResult;

#[test]
fn generated_with_default_values() {
    let p = ProgressBuilder::new().build();

    assert_eq!(0, p.current());
    assert_eq!(100, p.total());
}

#[quickcheck]
fn creates_progress_bar(c: usize, t: usize) -> bool {
    let p = ProgressBuilder::new()
        .set_start(c)
        .set_finish(t)
        .build();

    (p.current() == c) && (p.total() == t)
}

#[quickcheck]
fn increments_one(c: usize, t: usize) -> TestResult {
    if c >= t { return TestResult::discard() }
    let mut p = ProgressBuilder::new()
        .set_start(c)
        .set_finish(t)
        .build();
    p.increment();
    TestResult::from_bool(p.current() == c + 1)
}

#[quickcheck]
fn do_not_increment_above_total(t: usize) -> bool {
    let mut p = ProgressBuilder::new()
        .set_start(t)
        .set_finish(t)
        .build();
    p.increment();
    p.current() == p.total()
}

#[quickcheck]
fn decrements_one(c: usize, t: usize) -> TestResult {
    if c == 0 { return TestResult::discard() }
    let mut p = ProgressBuilder::new()
        .set_start(c)
        .set_finish(t)
        .build();
    p.decrement();
    TestResult::from_bool(p.current() == c - 1)
}

#[quickcheck]
fn do_not_decrement_below_zero(t: usize) -> bool {
    let mut p = ProgressBuilder::new()
        .set_finish(t)
        .build();
    p.decrement();
    p.current() == 0
}

#[quickcheck]
fn not_finished_while_in_progress(c: usize, t: usize) -> TestResult {
    if c >= t { return TestResult::discard() }
    let p = ProgressBuilder::new()
        .set_start(c)
        .set_finish(t)
        .build();
    TestResult::from_bool(!p.finished())
}

#[quickcheck]
fn finished_when_finished(t: usize) -> bool {
    let p = ProgressBuilder::new()
        .set_start(t)
        .set_finish(t)
        .build();
    p.finished()
}
<|endoftext|>