<commit_before>#[macro_use]
extern crate failure;
extern crate openssl;
extern crate rand;
extern crate xor;

use openssl::symm::{decrypt, encrypt};
use rand::Rng;
use xor::XOR;

pub const BLOCK_SIZE: usize = 16;

use failure::Error;

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum MODE {
    ECB,
    CBC,
    CTR,
}

#[derive(Debug, Fail)]
pub enum AesError {
    #[fail(display = "invalid padding")]
    InvalidPadding,

    #[fail(display = "failed to encrypt block {:?}", block)]
    EncryptionFailed { block: Vec<u8> },

    #[fail(display = "failed to decrypt block {:?}", block)]
    DecryptionFailed { block: Vec<u8> },
}

pub fn pad_inplace(u: &mut Vec<u8>, k: u8) -> Result<(), Error> {
    ensure!(k >= 2, "invalid parameter");

    let p = k - (u.len() % k as usize) as u8;
    for _ in 0..p {
        u.push(p);
    }
    Ok(())
}

pub fn unpad_inplace(u: &mut Vec<u8>, k: u8) -> Result<(), Error> {
    if !padding_valid(u, k)? {
        return Err(AesError::InvalidPadding.into());
    }

    let len_new = u.len() - u[u.len() - 1] as usize;
    u.truncate(len_new);
    Ok(())
}

fn padding_valid(u: &[u8], k: u8) -> Result<bool, Error> {
    ensure!(k >= 2, "invalid parameter");

    if u.is_empty() || u.len() % k as usize != 0 {
        return Ok(false);
    }

    let padding = u[u.len() - 1];
    if !(1 <= padding && padding <= k) {
        return Ok(false);
    }

    Ok(u[u.len() - padding as usize..]
        .iter()
        .all(|&b| b == padding))
}

pub trait Aes128 {
    fn pad(&self) -> Vec<u8>;
    fn padding_valid(&self) -> bool;
    fn encrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error>;
    fn decrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error>;
}

impl Aes128 for [u8] {
    fn pad(&self) -> Vec<u8> {
        let mut v = self.to_vec();
        pad_inplace(&mut v, BLOCK_SIZE as u8).unwrap(); // unwrap is ok
        v
    }

    fn padding_valid(&self) -> bool {
        padding_valid(self, BLOCK_SIZE as u8).unwrap()
    }

    fn encrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error> {
        match mode {
            MODE::ECB => {
                ensure!(iv.is_none(), "iv not supported for ECB mode");
                self.encrypt_aes128_ecb(key)
            }

            MODE::CBC => {
                ensure!(iv.is_some(), "iv required for CBC mode");
                self.encrypt_aes128_cbc(key, iv.unwrap())
            }

            MODE::CTR => {
                ensure!(iv.is_none(), "iv not supported for CTR mode");
                self.aes128_ctr(key)
            }
        }
    }

    fn decrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error> {
        match mode {
            MODE::ECB => {
                ensure!(iv.is_none(), "iv not supported for ECB mode");
                self.decrypt_aes128_ecb(key)
            }

            MODE::CBC => {
                ensure!(iv.is_some(), "iv required for CBC mode");
                self.decrypt_aes128_cbc(key, iv.unwrap())
            }

            MODE::CTR => {
                ensure!(iv.is_none(), "iv not supported for CTR mode");
                self.aes128_ctr(key)
            }
        }
    }
}

trait Aes128Internal {
    fn encrypt_aes128_block(&self, key: &Self) -> Result<Vec<u8>, Error>;
    fn decrypt_aes128_block(&self, key: &Self) -> Result<Vec<u8>, Error>;
    fn encrypt_aes128_ecb(&self, key: &Self) -> Result<Vec<u8>, Error>;
    fn decrypt_aes128_ecb(&self, key: &Self) -> Result<Vec<u8>, Error>;
    fn encrypt_aes128_cbc(&self, key: &Self, iv: &Self) -> Result<Vec<u8>, Error>;
    fn decrypt_aes128_cbc(&self, key: &Self, iv: &Self) -> Result<Vec<u8>, Error>;
    fn decrypt_aes128_cbc_blocks(&self, key: &Self, iv: &Self) -> Result<Vec<u8>, Error>;
    fn aes128_ctr(&self, key: &Self) -> Result<Vec<u8>, Error>;
}

impl Aes128Internal for [u8] {
    fn encrypt_aes128_block(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        ensure!(
            self.len() == BLOCK_SIZE,
            format!("input does not consist of {} bytes", BLOCK_SIZE)
        );

        // The OpenSSL call pads the cleartext before encrypting.
        let mut ciphertext = encrypt(openssl::symm::Cipher::aes_128_ecb(), key, None, self)
            .map_err(|_| AesError::EncryptionFailed {
                block: self.to_vec(),
            })?;

        ciphertext.truncate(BLOCK_SIZE);
        Ok(ciphertext)
    }

    fn decrypt_aes128_block(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        ensure!(
            self.len() == BLOCK_SIZE,
            format!("input does not consist of {} bytes", BLOCK_SIZE)
        );

        // The OpenSSL call expects a padded cleartext.
        let padding = vec![BLOCK_SIZE as u8; BLOCK_SIZE].encrypt_aes128_block(key)?;
        let mut u = self.to_vec();
        u.extend_from_slice(&padding);
        decrypt(openssl::symm::Cipher::aes_128_ecb(), key, None, &u).map_err(|_| {
            AesError::DecryptionFailed {
                block: self.to_vec(),
            }.into()
        })
    }

    fn encrypt_aes128_ecb(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        let u = self.pad();
        let mut ciphertext = Vec::new();
        for block in u.chunks(BLOCK_SIZE) {
            ciphertext.extend_from_slice(&block.encrypt_aes128_block(key)?);
        }
        Ok(ciphertext)
    }

    fn decrypt_aes128_ecb(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        if self.len() % BLOCK_SIZE != 0 {
            bail!(format!("input length not a multiple of {}", BLOCK_SIZE));
        }

        let mut cleartext = Vec::new();
        for block in self.chunks(BLOCK_SIZE) {
            cleartext.extend_from_slice(&block.decrypt_aes128_block(key)?);
        }
        unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
        Ok(cleartext)
    }

    fn encrypt_aes128_cbc(&self, key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
        let u = self.pad();
        let mut ciphertext = Vec::new();
        let mut cur = iv.to_vec();
        for block in u.chunks(BLOCK_SIZE) {
            cur = block.xor(&cur).encrypt_aes128_block(key)?;
            ciphertext.extend_from_slice(&cur);
        }
        Ok(ciphertext)
    }

    fn decrypt_aes128_cbc_blocks(&self, key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
        if self.len() % BLOCK_SIZE != 0 {
            bail!(format!("input length not a multiple of {}", BLOCK_SIZE));
        }

        let mut cleartext = Vec::new();
        let mut prev = iv;
        for block in self.chunks(BLOCK_SIZE) {
            let cur = block.decrypt_aes128_block(key)?.xor(prev);
            cleartext.extend_from_slice(&cur);
            prev = block;
        }
        Ok(cleartext)
    }

    fn decrypt_aes128_cbc(&self, key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
        let mut cleartext = self.decrypt_aes128_cbc_blocks(key, iv)?;
        unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
        Ok(cleartext)
    }

    fn aes128_ctr(&self, key: &[u8]) -> Result<Vec<u8>, Error> {
        let mut ciphertext = Vec::new();
        let mut keystream = vec![0; BLOCK_SIZE];
        for b in self.chunks(BLOCK_SIZE) {
            ciphertext.extend_from_slice(&b.xor(&keystream.encrypt_aes128_ecb(key)?));
            increment_counter(&mut keystream[BLOCK_SIZE / 2..]);
        }
        Ok(ciphertext)
    }
}

fn increment_counter(v: &mut [u8]) {
    for b in v.iter_mut() {
        *b += 1;
        if *b != 0 {
            break;
        }
    }
}

pub fn random_block() -> Vec<u8> {
    let mut rng = rand::thread_rng();
    rng.gen_iter().take(BLOCK_SIZE).collect()
}

// Returns a pair (chunks_count, fill_len), where chunks_count is the number of
// chunks resulting from dividing a message of length len into chunks of size
// BLOCK_SIZE. This count explicitly includes the last chunk, which may
// be shorter than BLOCK_SIZE. The number fill_len is the difference between
// chunks_count * BLOCK_SIZE and len.
pub fn chunks_count(len: usize) -> (usize, usize) {
    let q = (len + BLOCK_SIZE - 1) / BLOCK_SIZE;
    let r = q * BLOCK_SIZE - len;
    (q, r)
}

#[test]
fn aes_128_cbc() {
    let iv = [0; BLOCK_SIZE];
    let key = b"YELLOW SUBMARINE";
    let input = b"ABCDEFGHIJKLMNOP";
    assert_eq!(
        input.as_ref(),
        &input
            .encrypt(key, Some(&iv), MODE::CBC)
            .unwrap()
            .decrypt(key, Some(&iv), MODE::CBC)
            .unwrap()[..]
    );
}

#[test]
fn test_padding_valid() {
    assert!(padding_valid("ICE ICE BABY\x04\x04\x04\x04".as_bytes(), 16).unwrap() == true);
    assert!(padding_valid("ICE ICE BABY\x05\x05\x05\x05".as_bytes(), 16).unwrap() == false);
    assert!(padding_valid("ICE ICE BABY\x03\x03\x03".as_bytes(), 16).unwrap() == false);
    assert!(padding_valid("ICE ICE BABY\x01\x02\x03\x04".as_bytes(), 16).unwrap() == false);
    assert!(
        padding_valid(
            "ICE ICE BABY\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C".as_bytes(),
            12
        ).unwrap()
            == true
    );
}
<commit_msg>Replace artifical trait with standalone functions<commit_after>#[macro_use]
extern crate failure;
extern crate openssl;
extern crate rand;
extern crate xor;

use openssl::symm::{decrypt, encrypt};
use rand::Rng;
use xor::XOR;

pub const BLOCK_SIZE: usize = 16;

use failure::Error;

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum MODE {
    ECB,
    CBC,
    CTR,
}

#[derive(Debug, Fail)]
pub enum AesError {
    #[fail(display = "invalid padding")]
    InvalidPadding,

    #[fail(display = "failed to encrypt block {:?}", block)]
    EncryptionFailed { block: Vec<u8> },

    #[fail(display = "failed to decrypt block {:?}", block)]
    DecryptionFailed { block: Vec<u8> },
}

pub fn pad_inplace(u: &mut Vec<u8>, k: u8) -> Result<(), Error> {
    ensure!(k >= 2, "invalid parameter");

    let p = k - (u.len() % k as usize) as u8;
    for _ in 0..p {
        u.push(p);
    }
    Ok(())
}

pub fn unpad_inplace(u: &mut Vec<u8>, k: u8) -> Result<(), Error> {
    if !padding_valid(u, k)? {
        return Err(AesError::InvalidPadding.into());
    }

    let len_new = u.len() - u[u.len() - 1] as usize;
    u.truncate(len_new);
    Ok(())
}

fn padding_valid(u: &[u8], k: u8) -> Result<bool, Error> {
    ensure!(k >= 2, "invalid parameter");

    if u.is_empty() || u.len() % k as usize != 0 {
        return Ok(false);
    }

    let padding = u[u.len() - 1];
    if !(1 <= padding && padding <= k) {
        return Ok(false);
    }

    Ok(u[u.len() - padding as usize..]
        .iter()
        .all(|&b| b == padding))
}

pub trait Aes128 {
    fn pad(&self) -> Vec<u8>;
    fn padding_valid(&self) -> bool;
    fn encrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error>;
    fn decrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error>;
}

impl Aes128 for [u8] {
    fn pad(&self) -> Vec<u8> {
        let mut v = self.to_vec();
        pad_inplace(&mut v, BLOCK_SIZE as u8).unwrap(); // unwrap is ok
        v
    }

    fn padding_valid(&self) -> bool {
        padding_valid(self, BLOCK_SIZE as u8).unwrap()
    }

    fn encrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error> {
        match mode {
            MODE::ECB => {
                ensure!(iv.is_none(), "iv not supported for ECB mode");
                encrypt_aes128_ecb(&self, key)
            }

            MODE::CBC => {
                ensure!(iv.is_some(), "iv required for CBC mode");
                encrypt_aes128_cbc(&self, key, iv.unwrap())
            }

            MODE::CTR => {
                ensure!(iv.is_none(), "iv not supported for CTR mode");
                aes128_ctr(&self, key)
            }
        }
    }

    fn decrypt(&self, key: &Self, iv: Option<&Self>, mode: MODE) -> Result<Vec<u8>, Error> {
        match mode {
            MODE::ECB => {
                ensure!(iv.is_none(), "iv not supported for ECB mode");
                decrypt_aes128_ecb(&self, key)
            }

            MODE::CBC => {
                ensure!(iv.is_some(), "iv required for CBC mode");
                decrypt_aes128_cbc(&self, key, iv.unwrap())
            }

            MODE::CTR => {
                ensure!(iv.is_none(), "iv not supported for CTR mode");
                aes128_ctr(&self, key)
            }
        }
    }
}

fn encrypt_aes128_block(input: &[u8], key: &[u8]) -> Result<Vec<u8>, Error> {
    ensure!(
        input.len() == BLOCK_SIZE,
        format!("input does not consist of {} bytes", BLOCK_SIZE)
    );

    // The OpenSSL call pads the cleartext before encrypting.
    let mut ciphertext =
        encrypt(openssl::symm::Cipher::aes_128_ecb(), key, None, input).map_err(|_| {
            AesError::EncryptionFailed {
                block: input.to_vec(),
            }
        })?;

    ciphertext.truncate(BLOCK_SIZE);
    Ok(ciphertext)
}

fn decrypt_aes128_block(input: &[u8], key: &[u8]) -> Result<Vec<u8>, Error> {
    ensure!(
        input.len() == BLOCK_SIZE,
        format!("input does not consist of {} bytes", BLOCK_SIZE)
    );

    // The OpenSSL call expects a padded cleartext.
    let padding = encrypt_aes128_block(&[BLOCK_SIZE as u8; BLOCK_SIZE], key)?;
    let mut u = input.to_vec();
    u.extend_from_slice(&padding);
    decrypt(openssl::symm::Cipher::aes_128_ecb(), key, None, &u).map_err(|_| {
        AesError::DecryptionFailed {
            block: input.to_vec(),
        }.into()
    })
}

fn encrypt_aes128_ecb(input: &[u8], key: &[u8]) -> Result<Vec<u8>, Error> {
    let u = input.pad();
    let mut ciphertext = Vec::new();
    for block in u.chunks(BLOCK_SIZE) {
        ciphertext.extend_from_slice(&encrypt_aes128_block(block, key)?);
    }
    Ok(ciphertext)
}

fn decrypt_aes128_ecb(input: &[u8], key: &[u8]) -> Result<Vec<u8>, Error> {
    if input.len() % BLOCK_SIZE != 0 {
        bail!(format!("input length not a multiple of {}", BLOCK_SIZE));
    }

    let mut cleartext = Vec::new();
    for block in input.chunks(BLOCK_SIZE) {
        cleartext.extend_from_slice(&decrypt_aes128_block(block, key)?);
    }
    unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
    Ok(cleartext)
}

fn encrypt_aes128_cbc(input: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
    let u = input.pad();
    let mut ciphertext = Vec::new();
    let mut cur = iv.to_vec();
    for block in u.chunks(BLOCK_SIZE) {
        cur = encrypt_aes128_block(&block.xor(&cur), key)?;
        ciphertext.extend_from_slice(&cur);
    }
    Ok(ciphertext)
}

fn decrypt_aes128_cbc_blocks(input: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
    if input.len() % BLOCK_SIZE != 0 {
        bail!(format!("input length not a multiple of {}", BLOCK_SIZE));
    }

    let mut cleartext = Vec::new();
    let mut prev = iv;
    for block in input.chunks(BLOCK_SIZE) {
        let cur = decrypt_aes128_block(block, key)?.xor(prev);
        cleartext.extend_from_slice(&cur);
        prev = block;
    }
    Ok(cleartext)
}

fn decrypt_aes128_cbc(input: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, Error> {
    let mut cleartext = decrypt_aes128_cbc_blocks(input, key, iv)?;
    unpad_inplace(&mut cleartext, BLOCK_SIZE as u8)?;
    Ok(cleartext)
}

fn aes128_ctr(input: &[u8], key: &[u8]) -> Result<Vec<u8>, Error> {
    let mut ciphertext = Vec::new();
    let mut keystream = vec![0; BLOCK_SIZE];
    for b in input.chunks(BLOCK_SIZE) {
        ciphertext.extend_from_slice(&b.xor(&encrypt_aes128_ecb(&keystream, key)?));
        increment_counter(&mut keystream[BLOCK_SIZE / 2..]);
    }
    Ok(ciphertext)
}

fn increment_counter(v: &mut [u8]) {
    for b in v.iter_mut() {
        *b += 1;
        if *b != 0 {
            break;
        }
    }
}

pub fn random_block() -> Vec<u8> {
    let mut rng = rand::thread_rng();
    rng.gen_iter().take(BLOCK_SIZE).collect()
}

// Returns a pair (chunks_count, fill_len), where chunks_count is the number of
// chunks resulting from dividing a message of length len into chunks of size
// BLOCK_SIZE. This count explicitly includes the last chunk, which may
// be shorter than BLOCK_SIZE. The number fill_len is the difference between
// chunks_count * BLOCK_SIZE and len.
pub fn chunks_count(len: usize) -> (usize, usize) {
    let q = (len + BLOCK_SIZE - 1) / BLOCK_SIZE;
    let r = q * BLOCK_SIZE - len;
    (q, r)
}

#[test]
fn aes_128_cbc() {
    let iv = [0; BLOCK_SIZE];
    let key = b"YELLOW SUBMARINE";
    let input = b"ABCDEFGHIJKLMNOP";
    assert_eq!(
        input.as_ref(),
        &input
            .encrypt(key, Some(&iv), MODE::CBC)
            .unwrap()
            .decrypt(key, Some(&iv), MODE::CBC)
            .unwrap()[..]
    );
}

#[test]
fn test_padding_valid() {
    assert!(padding_valid("ICE ICE BABY\x04\x04\x04\x04".as_bytes(), 16).unwrap() == true);
    assert!(padding_valid("ICE ICE BABY\x05\x05\x05\x05".as_bytes(), 16).unwrap() == false);
    assert!(padding_valid("ICE ICE BABY\x03\x03\x03".as_bytes(), 16).unwrap() == false);
    assert!(padding_valid("ICE ICE BABY\x01\x02\x03\x04".as_bytes(), 16).unwrap() == false);
    assert!(
        padding_valid(
            "ICE ICE BABY\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C".as_bytes(),
            12
        ).unwrap()
            == true
    );
}
<|endoftext|>


<commit_before>//! Plan in FFTW
//!
//! See also [Using Plans] in the original document
//! [Using Plans]: http://www.fftw.org/fftw3_doc/Using-Plans.html

use crate::array::{alignment_of, AlignedAllocable, AlignedVec, Alignment};
use crate::error::*;
use crate::ffi::*;
use crate::types::{c32, c64, Flag, R2RKind, Sign};

use std::marker::PhantomData;

pub type C2CPlan64 = Plan<c64, c64, Plan64>;
pub type C2CPlan32 = Plan<c32, c32, Plan32>;
pub type R2CPlan64 = Plan<f64, c64, Plan64>;
pub type R2CPlan32 = Plan<f32, c32, Plan32>;
pub type C2RPlan64 = Plan<c64, f64, Plan64>;
pub type C2RPlan32 = Plan<c32, f32, Plan32>;
pub type R2RPlan64 = Plan<f64, f64, Plan64>;
pub type R2RPlan32 = Plan<f32, f32, Plan32>;

/// Typed wrapper of `fftw_plan`
///
/// The plan in FFTW manages the contains all information necessary to compute the transform,
/// including the pointers to the input and output arrays.
/// However, this wrapper *does not modify* this pointer once after the plan is created
/// since it should be *unsafe* in terms of Rust.
/// Instead, this plan executes a transform for different arrays with [new-array execute functions]
/// with related associated functions, e.g. `C2CPlan::c2c`.
///
/// [new-array execute functions]: http://www.fftw.org/fftw3_doc/New_002darray-Execute-Functions.html
pub struct Plan<A, B, Plan: PlanSpec> {
    plan: Plan,
    input: (usize, Alignment),
    output: (usize, Alignment),
    phantom: PhantomData<(A, B)>,
}

unsafe impl<A, B, P: PlanSpec> Send for Plan<A, B, P> {}

impl<A, B, P: PlanSpec> Drop for Plan<A, B, P> {
    fn drop(&mut self) {
        self.plan.destroy();
    }
}

impl<A, B, P: PlanSpec> Plan<A, B, P> {
    fn check(&self, in_: &[A], out: &[B]) -> Result<()> {
        if self.input != slice_info(in_) {
            return Err(Error::InputArrayMismatch {
                expect: self.input,
                actual: slice_info(in_),
            });
        }
        if self.output != slice_info(out) {
            return Err(Error::OutputArrayMismatch {
                expect: self.output,
                actual: slice_info(out),
            });
        }
        Ok(())
    }
}

/// Trait for Plan makers
pub trait PlanSpec: Clone + Copy {
    fn validate(self) -> Result<Self>;
    fn destroy(self);
    fn print(self);
}

/// Marker for 64-bit floating point FFT
pub type Plan64 = fftw_plan;
/// Marker for 32-bit floating point FFT
pub type Plan32 = fftwf_plan;

/// Trait for the plan of Complex-to-Complex transformation
pub trait C2CPlan: Sized {
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], sign: Sign, flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, sign, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Complex],
        out: &mut [Self::Complex],
        sign: Sign,
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-complex transform
    fn c2c(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Complex]) -> Result<()>;
}

/// Trait for the plan of Real-to-Complex transformation
pub trait R2CPlan: Sized {
    type Real: AlignedAllocable;
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let n_d = shape.last().unwrap();
        let n_sub = (n / n_d) * (n_d / 2 + 1);
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n_sub);
        Self::new(shape, &mut in_, &mut out, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Real],
        out: &mut [Self::Complex],
        flag: Flag,
    ) -> Result<Self>;

    /// Execute real-to-complex transform
    fn r2c(&mut self, in_: &mut [Self::Real], out: &mut [Self::Complex]) -> Result<()>;
}

/// Trait for the plan of Complex-to-Real transformation
pub trait C2RPlan: Sized {
    type Real: AlignedAllocable;
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let n_d = shape.last().unwrap();
        let n_sub = (n / n_d) * (n_d / 2 + 1);
        let mut in_ = AlignedVec::new(n_sub);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Complex],
        out: &mut [Self::Real],
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-real transform
    fn c2r(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Real]) -> Result<()>;
}

pub trait R2RPlan: Sized {
    type Real: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], kind: R2RKind, flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, kind, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Real],
        out: &mut [Self::Real],
        kind: R2RKind,
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-complex transform
    fn r2r(&mut self, in_: &mut [Self::Real], out: &mut [Self::Real]) -> Result<()>;
}

macro_rules! impl_c2c {
    ($C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl C2CPlan for Plan<$C, $C, $Plan> {
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Complex],
                out: &mut [Self::Complex],
                sign: Sign,
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    sign as i32, flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn c2c(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Complex]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_c2c!

impl_c2c!(c64, Plan64; fftw_plan_dft, fftw_execute_dft);
impl_c2c!(c32, Plan32; fftwf_plan_dft, fftwf_execute_dft);

macro_rules! impl_r2c {
    ($R:ty, $C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl R2CPlan for Plan<$R, $C, $Plan> {
            type Real = $R;
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Real],
                out: &mut [Self::Complex],
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn r2c(&mut self, in_: &mut [Self::Real], out: &mut [Self::Complex]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_r2c!

impl_r2c!(f64, c64, Plan64; fftw_plan_dft_r2c, fftw_execute_dft_r2c);
impl_r2c!(f32, c32, Plan32; fftwf_plan_dft_r2c, fftwf_execute_dft_r2c);

macro_rules! impl_c2r {
    ($R:ty, $C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl C2RPlan for Plan<$C, $R, $Plan> {
            type Real = $R;
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Complex],
                out: &mut [Self::Real],
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn c2r(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Real]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_c2r!

impl_c2r!(f64, c64, Plan64; fftw_plan_dft_c2r, fftw_execute_dft_c2r);
impl_c2r!(f32, c32, Plan32; fftwf_plan_dft_c2r, fftwf_execute_dft_c2r);

macro_rules! impl_r2r {
    ($R:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl R2RPlan for Plan<$R, $R, $Plan> {
            type Real = $R;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Real],
                out: &mut [Self::Real],
                kind: R2RKind,
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    &kind as *const _, flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn r2r(&mut self, in_: &mut [Self::Real], out: &mut [Self::Real]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_r2r!

impl_r2r!(f64, Plan64; fftw_plan_r2r, fftw_execute_r2r);
impl_r2r!(f32, Plan32; fftwf_plan_r2r, fftwf_execute_r2r);

macro_rules! impl_plan_spec {
    ($Plan:ty; $destroy_plan:ident, $print_plan:ident) => {
        impl PlanSpec for $Plan {
            fn validate(self) -> Result<Self> {
                if self.is_null() {
                    Err(Error::InvalidPlanError {})
                } else {
                    Ok(self)
                }
            }
            fn destroy(self) {
                excall! { $destroy_plan(self) }
            }
            fn print(self) {
                excall! { $print_plan(self) }
            }
        }
    };
} // impl_plan_spec!

impl_plan_spec!(Plan64; fftw_destroy_plan, fftw_print_plan);
impl_plan_spec!(Plan32; fftwf_destroy_plan, fftwf_print_plan);

// Convert [usize] -> [i32]
trait ToCInt {
    fn to_cint(&self) -> Vec<i32>;
}

impl ToCInt for [usize] {
    fn to_cint(&self) -> Vec<i32> {
        self.iter().map(|&x| x as i32).collect()
    }
}

fn slice_info<T>(a: &[T]) -> (usize, Alignment) {
    (a.len(), alignment_of(a))
}
<commit_msg>More correct Send impl for Plan.<commit_after>//! Plan in FFTW
//!
//! See also [Using Plans] in the original document
//! [Using Plans]: http://www.fftw.org/fftw3_doc/Using-Plans.html

use crate::array::{alignment_of, AlignedAllocable, AlignedVec, Alignment};
use crate::error::*;
use crate::ffi::*;
use crate::types::{c32, c64, Flag, R2RKind, Sign};

use std::marker::PhantomData;

pub type C2CPlan64 = Plan<c64, c64, Plan64>;
pub type C2CPlan32 = Plan<c32, c32, Plan32>;
pub type R2CPlan64 = Plan<f64, c64, Plan64>;
pub type R2CPlan32 = Plan<f32, c32, Plan32>;
pub type C2RPlan64 = Plan<c64, f64, Plan64>;
pub type C2RPlan32 = Plan<c32, f32, Plan32>;
pub type R2RPlan64 = Plan<f64, f64, Plan64>;
pub type R2RPlan32 = Plan<f32, f32, Plan32>;

/// Typed wrapper of `fftw_plan`
///
/// The plan in FFTW manages the contains all information necessary to compute the transform,
/// including the pointers to the input and output arrays.
/// However, this wrapper *does not modify* this pointer once after the plan is created
/// since it should be *unsafe* in terms of Rust.
/// Instead, this plan executes a transform for different arrays with [new-array execute functions]
/// with related associated functions, e.g. `C2CPlan::c2c`.
///
/// [new-array execute functions]: http://www.fftw.org/fftw3_doc/New_002darray-Execute-Functions.html
pub struct Plan<A, B, Plan: PlanSpec> {
    plan: Plan,
    input: (usize, Alignment),
    output: (usize, Alignment),
    phantom: PhantomData<(A, B)>,
}

unsafe impl<A: Send, B: Send> Send for Plan<A, B, Plan32> {}
unsafe impl<A: Send, B: Send> Send for Plan<A, B, Plan64> {}

impl<A, B, P: PlanSpec> Drop for Plan<A, B, P> {
    fn drop(&mut self) {
        self.plan.destroy();
    }
}

impl<A, B, P: PlanSpec> Plan<A, B, P> {
    fn check(&self, in_: &[A], out: &[B]) -> Result<()> {
        if self.input != slice_info(in_) {
            return Err(Error::InputArrayMismatch {
                expect: self.input,
                actual: slice_info(in_),
            });
        }
        if self.output != slice_info(out) {
            return Err(Error::OutputArrayMismatch {
                expect: self.output,
                actual: slice_info(out),
            });
        }
        Ok(())
    }
}

/// Trait for Plan makers
pub trait PlanSpec: Clone + Copy {
    fn validate(self) -> Result<Self>;
    fn destroy(self);
    fn print(self);
}

/// Marker for 64-bit floating point FFT
pub type Plan64 = fftw_plan;
/// Marker for 32-bit floating point FFT
pub type Plan32 = fftwf_plan;

/// Trait for the plan of Complex-to-Complex transformation
pub trait C2CPlan: Sized {
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], sign: Sign, flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, sign, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Complex],
        out: &mut [Self::Complex],
        sign: Sign,
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-complex transform
    fn c2c(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Complex]) -> Result<()>;
}

/// Trait for the plan of Real-to-Complex transformation
pub trait R2CPlan: Sized {
    type Real: AlignedAllocable;
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let n_d = shape.last().unwrap();
        let n_sub = (n / n_d) * (n_d / 2 + 1);
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n_sub);
        Self::new(shape, &mut in_, &mut out, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Real],
        out: &mut [Self::Complex],
        flag: Flag,
    ) -> Result<Self>;

    /// Execute real-to-complex transform
    fn r2c(&mut self, in_: &mut [Self::Real], out: &mut [Self::Complex]) -> Result<()>;
}

/// Trait for the plan of Complex-to-Real transformation
pub trait C2RPlan: Sized {
    type Real: AlignedAllocable;
    type Complex: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let n_d = shape.last().unwrap();
        let n_sub = (n / n_d) * (n_d / 2 + 1);
        let mut in_ = AlignedVec::new(n_sub);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Complex],
        out: &mut [Self::Real],
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-real transform
    fn c2r(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Real]) -> Result<()>;
}

pub trait R2RPlan: Sized {
    type Real: AlignedAllocable;

    /// Create new plan with aligned vector
    fn aligned(shape: &[usize], kind: R2RKind, flag: Flag) -> Result<Self> {
        let n: usize = shape.iter().product();
        let mut in_ = AlignedVec::new(n);
        let mut out = AlignedVec::new(n);
        Self::new(shape, &mut in_, &mut out, kind, flag)
    }

    /// Create new plan
    fn new(
        shape: &[usize],
        in_: &mut [Self::Real],
        out: &mut [Self::Real],
        kind: R2RKind,
        flag: Flag,
    ) -> Result<Self>;

    /// Execute complex-to-complex transform
    fn r2r(&mut self, in_: &mut [Self::Real], out: &mut [Self::Real]) -> Result<()>;
}

macro_rules! impl_c2c {
    ($C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl C2CPlan for Plan<$C, $C, $Plan> {
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Complex],
                out: &mut [Self::Complex],
                sign: Sign,
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    sign as i32, flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn c2c(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Complex]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_c2c!

impl_c2c!(c64, Plan64; fftw_plan_dft, fftw_execute_dft);
impl_c2c!(c32, Plan32; fftwf_plan_dft, fftwf_execute_dft);

macro_rules! impl_r2c {
    ($R:ty, $C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl R2CPlan for Plan<$R, $C, $Plan> {
            type Real = $R;
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Real],
                out: &mut [Self::Complex],
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn r2c(&mut self, in_: &mut [Self::Real], out: &mut [Self::Complex]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_r2c!

impl_r2c!(f64, c64, Plan64; fftw_plan_dft_r2c, fftw_execute_dft_r2c);
impl_r2c!(f32, c32, Plan32; fftwf_plan_dft_r2c, fftwf_execute_dft_r2c);

macro_rules! impl_c2r {
    ($R:ty, $C:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl C2RPlan for Plan<$C, $R, $Plan> {
            type Real = $R;
            type Complex = $C;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Complex],
                out: &mut [Self::Real],
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn c2r(&mut self, in_: &mut [Self::Complex], out: &mut [Self::Real]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_c2r!

impl_c2r!(f64, c64, Plan64; fftw_plan_dft_c2r, fftw_execute_dft_c2r);
impl_c2r!(f32, c32, Plan32; fftwf_plan_dft_c2r, fftwf_execute_dft_c2r);

macro_rules! impl_r2r {
    ($R:ty, $Plan:ty; $plan:ident, $exec:ident) => {
        impl R2RPlan for Plan<$R, $R, $Plan> {
            type Real = $R;
            fn new(
                shape: &[usize],
                in_: &mut [Self::Real],
                out: &mut [Self::Real],
                kind: R2RKind,
                flag: Flag,
            ) -> Result<Self> {
                let plan = excall! { $plan(
                    shape.len() as i32,
                    shape.to_cint().as_mut_ptr() as *mut _,
                    in_.as_mut_ptr(),
                    out.as_mut_ptr(),
                    &kind as *const _, flag.bits())
                }
                .validate()?;
                Ok(Self {
                    plan,
                    input: slice_info(in_),
                    output: slice_info(out),
                    phantom: PhantomData,
                })
            }
            fn r2r(&mut self, in_: &mut [Self::Real], out: &mut [Self::Real]) -> Result<()> {
                self.check(in_, out)?;
                unsafe { $exec(self.plan, in_.as_mut_ptr(), out.as_mut_ptr()) };
                Ok(())
            }
        }
    };
} // impl_r2r!

impl_r2r!(f64, Plan64; fftw_plan_r2r, fftw_execute_r2r);
impl_r2r!(f32, Plan32; fftwf_plan_r2r, fftwf_execute_r2r);

macro_rules! impl_plan_spec {
    ($Plan:ty; $destroy_plan:ident, $print_plan:ident) => {
        impl PlanSpec for $Plan {
            fn validate(self) -> Result<Self> {
                if self.is_null() {
                    Err(Error::InvalidPlanError {})
                } else {
                    Ok(self)
                }
            }
            fn destroy(self) {
                excall! { $destroy_plan(self) }
            }
            fn print(self) {
                excall! { $print_plan(self) }
            }
        }
    };
} // impl_plan_spec!

impl_plan_spec!(Plan64; fftw_destroy_plan, fftw_print_plan);
impl_plan_spec!(Plan32; fftwf_destroy_plan, fftwf_print_plan);

// Convert [usize] -> [i32]
trait ToCInt {
    fn to_cint(&self) -> Vec<i32>;
}

impl ToCInt for [usize] {
    fn to_cint(&self) -> Vec<i32> {
        self.iter().map(|&x| x as i32).collect()
    }
}

fn slice_info<T>(a: &[T]) -> (usize, Alignment) {
    (a.len(), alignment_of(a))
}
<|endoftext|>


<commit_before>use super::super::io;
use std::fmt;
use std::net::Ipv4Addr;
use std::convert::From;

/// IP header using SSE
#[derive(Debug)]
#[repr(C,packed)]
pub struct IpHeader {
    version_to_len: u32,
    id_to_foffset: u32,
    ttl_to_csum: u32,
    src_ip: u32,
    dst_ip: u32,
}

impl fmt::Display for IpHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let src = Ipv4Addr::from(self.src());
        let dst = Ipv4Addr::from(self.dst());
        write!(f,
               "{} > {} version: {} ihl: {} len: {} ttl: {} proto: {} csum: {}",
               src,
               dst,
               self.version(),
               self.ihl(),
               self.length(),
               self.ttl(),
               self.protocol(),
               self.csum())
    }
}

impl io::EndOffset for IpHeader {
    #[inline]
    fn offset(&self) -> usize {
        self.ihl() as usize * 4
    }

    #[inline]
    fn size() -> usize {
        // The struct itself is always 20 bytes.
        20
    }
}

impl IpHeader {
    #[inline]
    pub fn new() -> IpHeader {
        IpHeader {
            version_to_len: 0,
            id_to_foffset: 0,
            ttl_to_csum: 0,
            src_ip: 0,
            dst_ip: 0,
        }
    }

    #[inline]
    pub fn src(&self) -> u32 {
        let ip = u32::from_be(self.src_ip);
        ip
    }

    #[inline]
    pub fn set_src(&mut self, src: u32) {
        self.src_ip = u32::to_be(src)
    }

    #[inline]
    pub fn dst(&self) -> u32 {
        let ip = u32::from_be(self.dst_ip);
        ip
    }

    #[inline]
    pub fn set_dst(&mut self, dst: u32) {
        self.dst_ip = u32::to_be(dst);
    }

    #[inline]
    pub fn ttl(&self) -> u8 {
        let ttlpcsum = self.ttl_to_csum;
        (ttlpcsum & 0x000000ff) as u8
    }

    #[inline]
    pub fn set_ttl(&mut self, ttl: u8) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0x000000ff;
        self.ttl_to_csum = blanked | (ttl as u32);
    }

    #[inline]
    pub fn protocol(&self) -> u8 {
        let ttlpcsum = self.ttl_to_csum;
        ((ttlpcsum & 0xff00) >> 8) as u8
    }

    #[inline]
    pub fn set_protocol(&mut self, protocol: u8) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0xff00;
        self.ttl_to_csum = blanked | ((protocol as u32) << 8);
    }

    #[inline]
    pub fn csum(&self) -> u16 {
        let ttlpcsum = self.ttl_to_csum;
        ((ttlpcsum & 0xffff0000) >> 16) as u16
    }

    #[inline]
    pub fn set_csum(&mut self, csum: u16) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0xffff0000;
        self.ttl_to_csum = blanked | ((u16::to_be(csum) as u32) << 16);
    }

    #[inline]
    pub fn id(&self) -> u16 {
        let id_flag_fragment = self.id_to_foffset;
        u16::from_be((id_flag_fragment & 0xffff) as u16)
    }

    #[inline]
    pub fn set_id(&mut self, id: u16) {
        let id_flag_fragment = self.id_to_foffset;
        let blanked = id_flag_fragment & !0xffff;
        self.id_to_foffset = blanked | (u16::to_be(id) as u32);
    }

    #[inline]
    pub fn flags(&self) -> u8 {
        let id_flag_fragment = self.id_to_foffset;
        let flag_fragment = (id_flag_fragment >> 21) as u16;
        (flag_fragment & 0x7) as u8
    }

    #[inline]
    pub fn set_flags(&mut self, flags: u8) {
        self.id_to_foffset = (self.id_to_foffset & !0x00e00000) | (((flags & 0x7) as u32) << 16 + 5);
    }

    #[inline]
    pub fn fragment_offset(&self) -> u16 {
        let id_flag_fragment = self.id_to_foffset;
        let flag_fragment = (id_flag_fragment & 0xffff) as u16;
        u16::from_be(((flag_fragment & !0xe) >> 3))
    }

    #[inline]
    pub fn set_fragment_offset(&mut self, offset: u16) {
        let offset_correct = offset as u32;
        let id_to_offset_le = u32::from_be(self.id_to_foffset);
        self.id_to_foffset = u32::to_be(id_to_offset_le & !0x1fff | offset_correct);
    }

    #[inline]
    pub fn version(&self) -> u8 {
        let vihl = ((self.version_to_len & 0xf0) as u8) >> 4;
        vihl
    }

    #[inline]
    pub fn set_version(&mut self, version: u8) {
        self.version_to_len = (self.version_to_len & !0xf0) | (((version & 0xf) as u32) << 4);
    }

    #[inline]
    pub fn ihl(&self) -> u8 {
        let ihl = (self.version_to_len & 0x0f) as u8;
        ihl
    }

    #[inline]
    pub fn set_ihl(&mut self, ihl: u8) {
        self.version_to_len = (self.version_to_len & !0x0f) | ((ihl & 0x0f) as u32);
    }

    #[inline]
    pub fn dscp(&self) -> u8 {
        let dscp_ecn = ((self.version_to_len & 0xfc00) >> 10) as u8;
        dscp_ecn
    }

    #[inline]
    pub fn set_dscp(&mut self, dscp: u8) {
        self.version_to_len = (self.version_to_len & !0xfc00) | (((dscp & 0x3f) as u32) << 10);
    }

    #[inline]
    pub fn ecn(&self) -> u8 {
        let ecn = ((self.version_to_len & 0x0300) >> 8) as u8;
        ecn
    }

    #[inline]
    pub fn set_ecn(&mut self, ecn: u8) {
        self.version_to_len = (self.version_to_len & !0x0300) | (((ecn & 0x03) as u32) << 8);
    }

    #[inline]
    pub fn length(&self) -> u16 {
        ((self.version_to_len & 0xffff0000) >> 16) as u16
    }

    #[inline]
    pub fn set_length(&mut self, len: u16) {
        self.version_to_len = (self.version_to_len & !0xffff0000) | ((u16::to_be(len) as u32) << 16);
    }
}
<commit_msg>Improve performance a bit more<commit_after>use super::super::io;
use std::fmt;
use std::net::Ipv4Addr;
use std::convert::From;

/// IP header using SSE
#[derive(Debug)]
#[repr(C,packed)]
pub struct IpHeader {
    version_to_len: u32,
    id_to_foffset: u32,
    ttl_to_csum: u32,
    src_ip: u32,
    dst_ip: u32,
}

impl fmt::Display for IpHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let src = Ipv4Addr::from(self.src());
        let dst = Ipv4Addr::from(self.dst());
        write!(f,
               "{} > {} version: {} ihl: {} len: {} ttl: {} proto: {} csum: {}",
               src,
               dst,
               self.version(),
               self.ihl(),
               self.length(),
               self.ttl(),
               self.protocol(),
               self.csum())
    }
}

impl io::EndOffset for IpHeader {
    #[inline]
    fn offset(&self) -> usize {
        // FIXME: Figure out what to do with options.
        20
    }

    #[inline]
    fn size() -> usize {
        // The struct itself is always 20 bytes.
        20
    }
}

impl IpHeader {
    #[inline]
    pub fn new() -> IpHeader {
        IpHeader {
            version_to_len: 0,
            id_to_foffset: 0,
            ttl_to_csum: 0,
            src_ip: 0,
            dst_ip: 0,
        }
    }

    #[inline]
    pub fn src(&self) -> u32 {
        let ip = u32::from_be(self.src_ip);
        ip
    }

    #[inline]
    pub fn set_src(&mut self, src: u32) {
        self.src_ip = u32::to_be(src)
    }

    #[inline]
    pub fn dst(&self) -> u32 {
        let ip = u32::from_be(self.dst_ip);
        ip
    }

    #[inline]
    pub fn set_dst(&mut self, dst: u32) {
        self.dst_ip = u32::to_be(dst);
    }

    #[inline]
    pub fn ttl(&self) -> u8 {
        let ttlpcsum = self.ttl_to_csum;
        (ttlpcsum & 0x000000ff) as u8
    }

    #[inline]
    pub fn set_ttl(&mut self, ttl: u8) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0x000000ff;
        self.ttl_to_csum = blanked | (ttl as u32);
    }

    #[inline]
    pub fn protocol(&self) -> u8 {
        let ttlpcsum = self.ttl_to_csum;
        ((ttlpcsum & 0xff00) >> 8) as u8
    }

    #[inline]
    pub fn set_protocol(&mut self, protocol: u8) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0xff00;
        self.ttl_to_csum = blanked | ((protocol as u32) << 8);
    }

    #[inline]
    pub fn csum(&self) -> u16 {
        let ttlpcsum = self.ttl_to_csum;
        ((ttlpcsum & 0xffff0000) >> 16) as u16
    }

    #[inline]
    pub fn set_csum(&mut self, csum: u16) {
        let ttlpcsum = self.ttl_to_csum;
        let blanked = ttlpcsum & !0xffff0000;
        self.ttl_to_csum = blanked | ((u16::to_be(csum) as u32) << 16);
    }

    #[inline]
    pub fn id(&self) -> u16 {
        let id_flag_fragment = self.id_to_foffset;
        u16::from_be((id_flag_fragment & 0xffff) as u16)
    }

    #[inline]
    pub fn set_id(&mut self, id: u16) {
        let id_flag_fragment = self.id_to_foffset;
        let blanked = id_flag_fragment & !0xffff;
        self.id_to_foffset = blanked | (u16::to_be(id) as u32);
    }

    #[inline]
    pub fn flags(&self) -> u8 {
        let id_flag_fragment = self.id_to_foffset;
        let flag_fragment = (id_flag_fragment >> 21) as u16;
        (flag_fragment & 0x7) as u8
    }

    #[inline]
    pub fn set_flags(&mut self, flags: u8) {
        self.id_to_foffset = (self.id_to_foffset & !0x00e00000) | (((flags & 0x7) as u32) << 16 + 5);
    }

    #[inline]
    pub fn fragment_offset(&self) -> u16 {
        let id_flag_fragment = self.id_to_foffset;
        let flag_fragment = (id_flag_fragment & 0xffff) as u16;
        u16::from_be(((flag_fragment & !0xe) >> 3))
    }

    #[inline]
    pub fn set_fragment_offset(&mut self, offset: u16) {
        let offset_correct = offset as u32;
        let id_to_offset_le = u32::from_be(self.id_to_foffset);
        self.id_to_foffset = u32::to_be(id_to_offset_le & !0x1fff | offset_correct);
    }

    #[inline]
    pub fn version(&self) -> u8 {
        let vihl = ((self.version_to_len & 0xf0) as u8) >> 4;
        vihl
    }

    #[inline]
    pub fn set_version(&mut self, version: u8) {
        self.version_to_len = (self.version_to_len & !0xf0) | (((version & 0xf) as u32) << 4);
    }

    #[inline]
    pub fn ihl(&self) -> u8 {
        let ihl = (self.version_to_len & 0x0f) as u8;
        ihl
    }

    #[inline]
    pub fn set_ihl(&mut self, ihl: u8) {
        self.version_to_len = (self.version_to_len & !0x0f) | ((ihl & 0x0f) as u32);
    }

    #[inline]
    pub fn dscp(&self) -> u8 {
        let dscp_ecn = ((self.version_to_len & 0xfc00) >> 10) as u8;
        dscp_ecn
    }

    #[inline]
    pub fn set_dscp(&mut self, dscp: u8) {
        self.version_to_len = (self.version_to_len & !0xfc00) | (((dscp & 0x3f) as u32) << 10);
    }

    #[inline]
    pub fn ecn(&self) -> u8 {
        let ecn = ((self.version_to_len & 0x0300) >> 8) as u8;
        ecn
    }

    #[inline]
    pub fn set_ecn(&mut self, ecn: u8) {
        self.version_to_len = (self.version_to_len & !0x0300) | (((ecn & 0x03) as u32) << 8);
    }

    #[inline]
    pub fn length(&self) -> u16 {
        ((self.version_to_len & 0xffff0000) >> 16) as u16
    }

    #[inline]
    pub fn set_length(&mut self, len: u16) {
        self.version_to_len = (self.version_to_len & !0xffff0000) | ((u16::to_be(len) as u32) << 16);
    }
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
mod util;

use std::io;
use termion::event::Key;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use tui::backend::TermionBackend;
use tui::layout::{Constraint, Direction, Layout};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Widget};
use tui::Terminal;

use crate::util::event::{Event, Events};

fn main() -> Result<(), failure::Error> {
    // Terminal initialization
    let stdout = io::stdout().into_raw_mode()?;
    let stdout = MouseTerminal::from(stdout);
    let stdout = AlternateScreen::from(stdout);
    let backend = TermionBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;
    terminal.hide_cursor()?;

    // Setup event handlers
    let events = Events::new();

    loop {
        terminal.draw(|mut f| {
            // Wrapping block for a group
            // Just draw the block and the group on the same area and build the group
            // with at least a margin of 1
            let size = f.size();
            Block::default().borders(Borders::ALL).render(&mut f, size);
            let chunks = Layout::default()
                .direction(Direction::Vertical)
                .margin(4)
                .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                .split(f.size());
            {
                let chunks = Layout::default()
                    .direction(Direction::Horizontal)
                    .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                    .split(chunks[0]);
                Block::default()
                    .title("With background")
                    .title_style(Style::default().fg(Color::Yellow))
                    .style(Style::default().bg(Color::Green))
                    .render(&mut f, chunks[0]);
                Block::default()
                    .title("Styled title")
                    .title_style(
                        Style::default()
                            .fg(Color::White)
                            .bg(Color::Red)
                            .modifier(Modifier::BOLD),
                    )
                    .render(&mut f, chunks[1]);
            }
            {
                let chunks = Layout::default()
                    .direction(Direction::Horizontal)
                    .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                    .split(chunks[1]);
                Block::default()
                    .title("With borders")
                    .borders(Borders::ALL)
                    .render(&mut f, chunks[0]);
                Block::default()
                    .title("With styled borders")
                    .border_style(Style::default().fg(Color::Cyan))
                    .borders(Borders::LEFT | Borders::RIGHT)
                    .render(&mut f, chunks[1]);
            }
        })?;

        match events.next()? {
            Event::Input(key) => {
                if key == Key::Char('q') {
                    break;
                }
            }
            _ => {}
        }
    }
    Ok(())
}
<commit_msg>add rounded corners and double borders to block example<commit_after>#[allow(dead_code)]
mod util;

use std::io;
use termion::event::Key;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use tui::backend::TermionBackend;
use tui::layout::{Constraint, Direction, Layout};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Widget};
use tui::Terminal;

use crate::util::event::{Event, Events};

fn main() -> Result<(), failure::Error> {
    // Terminal initialization
    let stdout = io::stdout().into_raw_mode()?;
    let stdout = MouseTerminal::from(stdout);
    let stdout = AlternateScreen::from(stdout);
    let backend = TermionBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;
    terminal.hide_cursor()?;

    // Setup event handlers
    let events = Events::new();

    loop {
        terminal.draw(|mut f| {
            // Wrapping block for a group
            // Just draw the block and the group on the same area and build the group
            // with at least a margin of 1
            let size = f.size();
            Block::default()
                .borders(Borders::ALL)
                .title("Main block with round corners")
                .rounded()
                .render(&mut f, size);
            let chunks = Layout::default()
                .direction(Direction::Vertical)
                .margin(4)
                .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                .split(f.size());
            {
                let chunks = Layout::default()
                    .direction(Direction::Horizontal)
                    .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                    .split(chunks[0]);
                Block::default()
                    .title("With background")
                    .title_style(Style::default().fg(Color::Yellow))
                    .style(Style::default().bg(Color::Green))
                    .render(&mut f, chunks[0]);
                Block::default()
                    .title("Styled title")
                    .title_style(
                        Style::default()
                            .fg(Color::White)
                            .bg(Color::Red)
                            .modifier(Modifier::BOLD),
                    )
                    .render(&mut f, chunks[1]);
            }
            {
                let chunks = Layout::default()
                    .direction(Direction::Horizontal)
                    .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                    .split(chunks[1]);
                Block::default()
                    .title("With borders")
                    .borders(Borders::ALL)
                    .render(&mut f, chunks[0]);
                Block::default()
                    .title("With styled and double borders")
                    .border_style(Style::default().fg(Color::Cyan))
                    .borders(Borders::LEFT | Borders::RIGHT)
                    .double_border()
                    .render(&mut f, chunks[1]);
            }
        })?;

        match events.next()? {
            Event::Input(key) => {
                if key == Key::Char('q') {
                    break;
                }
            }
            _ => {}
        }
    }
    Ok(())
}
<|endoftext|>


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

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }

    fn elapse(&self, elapsed: Duration) -> Self {
        FrameInfo::new(self.frame, elapsed)
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn started(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: Some(Default::default()),
        }
    }

    pub fn start(&mut self) {
        self.current = Some(Default::default());
    }

    pub fn frame(&self) -> Option<u32> {
        self.current.as_ref().map(|c| c.frame)
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    pub fn animate(&mut self, delta: Duration) {
        self.current = self.current.as_ref().map_or(Some(Default::default()), |frame| {
            let elapsed = frame.elapsed + delta;
            elapsed.checked_sub(self.duration)
                .map_or(Some(frame.elapse(elapsed)), |r| self.next(frame, r))
        });
    }

    fn next(&self, current: &FrameInfo, remaining: Duration) -> Option<FrameInfo> {
        let frame = (current.frame + 1) % self.max;
        if frame > 0 || self.repeat {
            Some(FrameInfo::new(frame, remaining))
        } else {
            None
        }
    }
}

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

    #[test]
    fn new_animator() {
        let animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_none());
    }

    #[test]
    fn started_animator() {
        let animator = FrameAnimator::started(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn start() {
        let mut animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        animator.start();
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }
}
<commit_msg>testing + fixing of animate/repeat logic<commit_after>use std::time::Duration;

#[derive(Default, Clone)]
struct FrameInfo {
    frame: u32,
    elapsed: Duration,
}

impl FrameInfo {
    fn new(frame: u32, elapsed: Duration) -> Self {
        FrameInfo {
            frame: frame,
            elapsed: elapsed,
        }
    }

    fn elapse(&self, elapsed: Duration) -> Self {
        FrameInfo::new(self.frame, elapsed)
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: Option<FrameInfo>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: None,
        }
    }

    pub fn started(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: Some(Default::default()),
        }
    }

    pub fn start(&mut self) {
        self.current = Some(Default::default());
    }

    pub fn frame(&self) -> Option<u32> {
        self.current.as_ref().map(|c| c.frame)
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    pub fn animate(&mut self, delta: Duration) {
        self.current = self.current.as_ref().map_or(Some(Default::default()),
                                                    |f| self.next(f.frame, f.elapsed + delta));
    }

    fn next(&self, current: u32, elapsed: Duration) -> Option<FrameInfo> {
        let mut frame = current;
        let mut remaining = elapsed;
        while remaining >= self.duration {
            frame += 1;
            remaining = remaining - self.duration;
        }
        if frame < self.max || self.repeat {
            Some(FrameInfo::new(frame % self.max, remaining))
        } else {
            None
        }
    }
}

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

    #[test]
    fn new_animator() {
        let animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_none());
    }

    #[test]
    fn started_animator() {
        let animator = FrameAnimator::started(3, Duration::from_secs(5), true);
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn start() {
        let mut animator = FrameAnimator::new(3, Duration::from_secs(5), true);
        animator.start();
        assert!(animator.frame().is_some());
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn animate() {
        let mut animator = FrameAnimator::started(6, Duration::from_secs(5), true);

        animator.animate(Duration::from_secs(5));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 2);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 3);

        animator.animate(Duration::from_secs(10));
        assert_eq!(animator.frame().unwrap(), 5);
    }

    #[test]
    fn repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), true);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(4));
        assert_eq!(animator.frame().unwrap(), 0);
    }

    #[test]
    fn no_repeat() {
        let mut animator = FrameAnimator::started(2, Duration::from_secs(2), false);

        animator.animate(Duration::from_secs(2));
        assert_eq!(animator.frame().unwrap(), 1);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none());

        animator.start();
        animator.animate(Duration::from_secs(1));
        assert_eq!(animator.frame().unwrap(), 0);

        animator.animate(Duration::from_secs(3));
        assert!(animator.frame().is_none())
    }
}
<|endoftext|>


<commit_before>pub fn sync() {
    atomic_module();
    mpsc_module();
}

fn atomic_module() {
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;

    let spinlock = Arc::new(AtomicUsize::new(1));

    let spinlock_clone = spinlock.clone();
    let thread = thread::spawn(move || {
        spinlock_clone.store(0, Ordering::SeqCst);
    });

    // wait for the other thread to release the lock
    while spinlock.load(Ordering::SeqCst) != 0 { }

    if let Err(panic) = thread.join() {
        println!("Thread had an error: {:?}", panic);
    }

    use std::sync::atomic::ATOMIC_USIZE_INIT;

    static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

    let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
    println!("live threads: {}", old_thread_count + 1);

    use std::sync::atomic::AtomicBool;

    let atomic_true = AtomicBool::new(true);
    let atomic_false = AtomicBool::new(false);

    let mut some_bool = AtomicBool::new(true);
    assert_eq!(true, *some_bool.get_mut());
    *some_bool.get_mut() = false;
    assert_eq!(false, some_bool.load(Ordering::SeqCst));

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.into_inner());

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.load(Ordering::Relaxed));

    let some_bool = AtomicBool::new(true);
    some_bool.store(false, Ordering::Relaxed);
    assert_eq!(false, some_bool.load(Ordering::Relaxed));

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.swap(false, Ordering::Relaxed));
    assert_eq!(false, some_bool.load(Ordering::Relaxed));
}

fn mpsc_module() {
    use std::thread;
    use std::sync::mpsc::channel;

    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(10).unwrap();
    });
    assert_eq!(10, rx.recv().unwrap());

    // shared usage

    // create a shared channel that can be sent along from many threads
    // tx (transmission) is the sending half, and rx (receiving) is the receiving half
    let (tx, rx) = channel();
    for i in 0..10 {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(i).unwrap();
        });
    }

    for _ in 0..10 {
        let j = rx.recv().unwrap();
        assert!(0 <= j && j < 10);
    }

    // propagating panics

    // the call to recv() will return an error because the channel has already hung up (or been deallocated)
    let (tx, rx) = channel::<i32>();
    drop(tx);
    assert!(rx.recv().is_err());

    use std::sync::mpsc::sync_channel;

    let (tx, rx) = sync_channel::<i32>(0);
    thread::spawn(move || {
        // this will wait for the parent thread to start receiving
        tx.send(53).unwrap();
    });
    rx.recv().unwrap();
}
<commit_msg>[Rust] STD Library - Modules - sync<commit_after>pub fn sync() {
    atomic_module();
    mpsc_module();
    arc_struct();
}

fn atomic_module() {
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;

    let spinlock = Arc::new(AtomicUsize::new(1));

    let spinlock_clone = spinlock.clone();
    let thread = thread::spawn(move || {
        spinlock_clone.store(0, Ordering::SeqCst);
    });

    // wait for the other thread to release the lock
    while spinlock.load(Ordering::SeqCst) != 0 { }

    if let Err(panic) = thread.join() {
        println!("Thread had an error: {:?}", panic);
    }

    use std::sync::atomic::ATOMIC_USIZE_INIT;

    static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

    let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
    println!("live threads: {}", old_thread_count + 1);

    use std::sync::atomic::AtomicBool;

    let atomic_true = AtomicBool::new(true);
    let atomic_false = AtomicBool::new(false);

    let mut some_bool = AtomicBool::new(true);
    assert_eq!(true, *some_bool.get_mut());
    *some_bool.get_mut() = false;
    assert_eq!(false, some_bool.load(Ordering::SeqCst));

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.into_inner());

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.load(Ordering::Relaxed));

    let some_bool = AtomicBool::new(true);
    some_bool.store(false, Ordering::Relaxed);
    assert_eq!(false, some_bool.load(Ordering::Relaxed));

    let some_bool = AtomicBool::new(true);
    assert_eq!(true, some_bool.swap(false, Ordering::Relaxed));
    assert_eq!(false, some_bool.load(Ordering::Relaxed));
}

fn mpsc_module() {
    use std::thread;
    use std::sync::mpsc::channel;

    let (tx, rx) = channel();
    thread::spawn(move || {
        tx.send(10).unwrap();
    });
    assert_eq!(10, rx.recv().unwrap());

    // shared usage

    // create a shared channel that can be sent along from many threads
    // tx (transmission) is the sending half, and rx (receiving) is the receiving half
    let (tx, rx) = channel();
    for i in 0..10 {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(i).unwrap();
        });
    }

    for _ in 0..10 {
        let j = rx.recv().unwrap();
        assert!(0 <= j && j < 10);
    }

    // propagating panics

    // the call to recv() will return an error because the channel has already hung up (or been deallocated)
    let (tx, rx) = channel::<i32>();
    drop(tx);
    assert!(rx.recv().is_err());

    use std::sync::mpsc::sync_channel;

    let (tx, rx) = sync_channel::<i32>(0);
    thread::spawn(move || {
        // this will wait for the parent thread to start receiving
        tx.send(53).unwrap();
    });
    rx.recv().unwrap();
}

fn arc_struct() {
    use std::sync::Arc;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use std::thread;

    let five = Arc::new(5);

    for _ in 0..10 {
        let five = five.clone();

        thread::spawn(move || {
            println!("{:?}", five);
        });
    }

    println!("", );

    let val = Arc::new(AtomicUsize::new(5));

    for _ in 0..10 {
        let val = val.clone();

        thread::spawn(move || {
            let v = val.fetch_add(1, Ordering::SeqCst);
            println!("{:?}", v);
        });
    }

    let five = Arc::new(5);

    let weak_five = Arc::downgrade(&five);
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{IResult, digit, hex_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(do_parse!(
                        tag_s!(".") >>
                        opt!(digit) >>
                        ()
                    )) >>
                    opt!(exponential_part) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                digit >>
                opt!(exponential_part) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(tag_s!("0") >> ())
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(xid_continue) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
        |
        eof
    ));

    fn eof(i: &str) -> IResult<&str, &str> {
        eof!(i,)
    }

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

}<commit_msg>Unit test numeric_literal<commit_after>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{IResult, digit, hex_digit, oct_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
            |
            octal_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(complete!(do_parse!(
                        tag_s!(".") >>
                        opt!(complete!(digit)) >>
                        ()
                    ))) >>
                    opt!(complete!(exponential_part)) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                complete!(digit) >>
                opt!(complete!(exponential_part)) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(
            tag_s!("0") >>
            not!(digit) >>
            not!(tag_s!("x")) >>
            not!(tag_s!("X")) >>
            ()
        )
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(octal_integer_literal<&str, f64>, do_parse!(
        tag_s!("0") >>
        octal: oct_digit >>
        (i64::from_str_radix(octal, 8).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(xid_continue) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
        |
        eof
    ));

    fn eof(i: &str) -> IResult<&str, &str> {
        eof!(i,)
    }

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

    #[cfg(test)]
    mod tests {
        use nom::{ErrorKind, Needed};
        use super::*;

        #[test]
        fn numeric_literal() {
            assert_eq!(super::numeric_literal(""), IResult::Incomplete(Needed::Size(1)));

            // Decimal
            assert_eq!(super::numeric_literal("42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal("0"), IResult::Done("", NumericLiteral(0_f64)));
            assert_eq!(super::numeric_literal("42.42e-4"), IResult::Done("", NumericLiteral(42.42e-4_f64)));
            assert_eq!(super::numeric_literal(".42"), IResult::Done("", NumericLiteral(0.42_f64)));
            assert_eq!(super::numeric_literal("42."), IResult::Done("", NumericLiteral(42_f64)));

            assert_eq!(super::numeric_literal("+42"), IResult::Error(ErrorKind::Alt)); // Identity is unary expression
            assert_eq!(super::numeric_literal("-42"), IResult::Error(ErrorKind::Alt)); // Negation is unary expression
            assert_eq!(super::numeric_literal("."), IResult::Error(ErrorKind::Alt));

            // Octal
            assert_eq!(super::numeric_literal("042"), IResult::Done("", NumericLiteral(34_f64)));

            // Hex
            assert_eq!(super::numeric_literal("0x42"), IResult::Done("", NumericLiteral(66_f64)));
            assert_eq!(super::numeric_literal("0X42"), IResult::Done("", NumericLiteral(66_f64)));
        }
    }
}<|endoftext|>


<commit_before>use std::fmt::Write as _;

use protobuf::reflect::FileDescriptor;
use protobuf::Message;

use crate::gen::code_writer::CodeWriter;
use crate::gen::inside::protobuf_crate_path;
use crate::gen::paths::proto_path_to_fn_file_descriptor;
use crate::gen::rust::snippets::expr_vec_with_capacity;
use crate::gen::scope::FileScope;
use crate::gen::scope::Scope;
use crate::gen::scope::WithScope;
use crate::Customize;

fn escape_byte(s: &mut String, b: u8) {
    if b == b'\n' {
        write!(s, "\\n").unwrap();
    } else if b == b'\r' {
        write!(s, "\\r").unwrap();
    } else if b == b'\t' {
        write!(s, "\\t").unwrap();
    } else if b == b'\\' || b == b'"' {
        write!(s, "\\{}", b as char).unwrap();
    } else if b == b'\0' {
        write!(s, "\\0").unwrap();
    // ASCII printable except space
    } else if b > 0x20 && b < 0x7f {
        write!(s, "{}", b as char).unwrap();
    } else {
        write!(s, "\\x{:02x}", b).unwrap();
    }
}

fn write_file_descriptor(
    file_descriptor: &FileDescriptor,
    customize: &Customize,
    w: &mut CodeWriter,
) {
    w.write_line("/// `FileDescriptor` object which allows dynamic access to files");
    w.pub_fn(
        &format!(
            "file_descriptor() -> {}::reflect::FileDescriptor",
            protobuf_crate_path(customize)
        ),
        |w| {
            w.lazy_static(
                "file_descriptor_lazy",
                &format!(
                    "{}::reflect::GeneratedFileDescriptor",
                    protobuf_crate_path(customize)
                ),
                &format!("{}", protobuf_crate_path(customize)),
            );
            w.block(
                "let file_descriptor = file_descriptor_lazy.get(|| {",
                "});",
                |w| {
                    let deps = &file_descriptor.proto().dependency;
                    w.write_line(&format!(
                        "let mut deps = {};",
                        expr_vec_with_capacity(&format!("{}", deps.len()))
                    ));
                    for f in deps {
                        w.write_line(&format!(
                            "deps.push({}());",
                            proto_path_to_fn_file_descriptor(f, customize)
                        ));
                    }

                    let scope = FileScope { file_descriptor };

                    let messages = scope.find_messages_except_map();
                    w.write_line(&format!(
                        "let mut messages = {};",
                        expr_vec_with_capacity(&format!("{}", messages.len()))
                    ));
                    for m in &messages {
                        w.write_line(&format!(
                            "messages.push({}::generated_message_descriptor_data());",
                            m.rust_name_to_file(),
                        ));
                    }

                    let enums = scope.find_enums();
                    w.write_line(&format!(
                        "let mut enums = {};",
                        expr_vec_with_capacity(&format!("{}", enums.len()))
                    ));
                    for e in &enums {
                        w.write_line(&format!(
                            "enums.push({}::generated_enum_descriptor_data());",
                            e.rust_name_to_file(),
                        ));
                    }

                    w.write_line(&format!(
                        "{}::reflect::GeneratedFileDescriptor::new_generated(",
                        protobuf_crate_path(&customize),
                    ));
                    w.indented(|w| {
                        w.write_line(&format!("file_descriptor_proto(),"));
                        w.write_line(&format!("deps,"));
                        w.write_line(&format!("messages,"));
                        w.write_line(&format!("enums,"));
                    });
                    w.write_line(")");
                },
            );
            w.write_line(&format!(
                "{}::reflect::FileDescriptor::new_generated_2(file_descriptor)",
                protobuf_crate_path(&customize),
            ));
        },
    );
}

pub(crate) fn write_file_descriptor_data(
    file: &FileDescriptor,
    customize: &Customize,
    w: &mut CodeWriter,
) {
    let fdp_bytes = file.proto().write_to_bytes().unwrap();
    w.write_line("static file_descriptor_proto_data: &'static [u8] = b\"\\");
    w.indented(|w| {
        const MAX_LINE_LEN: usize = 72;

        let mut s = String::new();
        for &b in &fdp_bytes {
            let prev_len = s.len();
            escape_byte(&mut s, b);
            let truncate = s.len() > MAX_LINE_LEN;
            if truncate {
                s.truncate(prev_len);
            }
            if truncate || s.len() == MAX_LINE_LEN {
                write!(s, "\\").unwrap();
                w.write_line(&s);
                s.clear();
            }
            if truncate {
                escape_byte(&mut s, b);
            }
        }
        if !s.is_empty() {
            write!(s, "\\").unwrap();
            w.write_line(&s);
            s.clear();
        }
    });
    w.write_line("\";");
    w.write_line("");
    w.write_line("/// `FileDescriptorProto` object which was a source for this generated file");
    w.pub_fn(
        &format!(
            "file_descriptor_proto() -> &'static {protobuf_crate}::descriptor::FileDescriptorProto",
            protobuf_crate=protobuf_crate_path(customize)
        ),
        |w| {
            w.lazy_static_decl_get(
                "file_descriptor_proto_lazy",
                &format!(
                    "{protobuf_crate}::descriptor::FileDescriptorProto",
                    protobuf_crate=protobuf_crate_path(customize)
                ),
                &format!("{}", protobuf_crate_path(customize)),
                |w| {
                    w.write_line(&format!(
                        "{protobuf_crate}::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()",
                        protobuf_crate=protobuf_crate_path(customize)
                    ));
                },
            );
        },
    );
    w.write_line("");
    write_file_descriptor(file, &customize, w);
}

/// Code to generate call `module::file_descriptor()`.
pub(crate) fn file_descriptor_call_expr(scope: &Scope) -> String {
    format!(
        "{}()",
        scope
            .rust_path_to_file()
            .to_reverse()
            .append_ident("file_descriptor".into())
    )
}
<commit_msg>Generate file_descriptor_proto function as private<commit_after>use std::fmt::Write as _;

use protobuf::reflect::FileDescriptor;
use protobuf::Message;

use crate::gen::code_writer::CodeWriter;
use crate::gen::inside::protobuf_crate_path;
use crate::gen::paths::proto_path_to_fn_file_descriptor;
use crate::gen::rust::snippets::expr_vec_with_capacity;
use crate::gen::scope::FileScope;
use crate::gen::scope::Scope;
use crate::gen::scope::WithScope;
use crate::Customize;

fn escape_byte(s: &mut String, b: u8) {
    if b == b'\n' {
        write!(s, "\\n").unwrap();
    } else if b == b'\r' {
        write!(s, "\\r").unwrap();
    } else if b == b'\t' {
        write!(s, "\\t").unwrap();
    } else if b == b'\\' || b == b'"' {
        write!(s, "\\{}", b as char).unwrap();
    } else if b == b'\0' {
        write!(s, "\\0").unwrap();
    // ASCII printable except space
    } else if b > 0x20 && b < 0x7f {
        write!(s, "{}", b as char).unwrap();
    } else {
        write!(s, "\\x{:02x}", b).unwrap();
    }
}

fn write_file_descriptor(
    file_descriptor: &FileDescriptor,
    customize: &Customize,
    w: &mut CodeWriter,
) {
    w.write_line("/// `FileDescriptor` object which allows dynamic access to files");
    w.pub_fn(
        &format!(
            "file_descriptor() -> {}::reflect::FileDescriptor",
            protobuf_crate_path(customize)
        ),
        |w| {
            w.lazy_static(
                "file_descriptor_lazy",
                &format!(
                    "{}::reflect::GeneratedFileDescriptor",
                    protobuf_crate_path(customize)
                ),
                &format!("{}", protobuf_crate_path(customize)),
            );
            w.block(
                "let file_descriptor = file_descriptor_lazy.get(|| {",
                "});",
                |w| {
                    let deps = &file_descriptor.proto().dependency;
                    w.write_line(&format!(
                        "let mut deps = {};",
                        expr_vec_with_capacity(&format!("{}", deps.len()))
                    ));
                    for f in deps {
                        w.write_line(&format!(
                            "deps.push({}());",
                            proto_path_to_fn_file_descriptor(f, customize)
                        ));
                    }

                    let scope = FileScope { file_descriptor };

                    let messages = scope.find_messages_except_map();
                    w.write_line(&format!(
                        "let mut messages = {};",
                        expr_vec_with_capacity(&format!("{}", messages.len()))
                    ));
                    for m in &messages {
                        w.write_line(&format!(
                            "messages.push({}::generated_message_descriptor_data());",
                            m.rust_name_to_file(),
                        ));
                    }

                    let enums = scope.find_enums();
                    w.write_line(&format!(
                        "let mut enums = {};",
                        expr_vec_with_capacity(&format!("{}", enums.len()))
                    ));
                    for e in &enums {
                        w.write_line(&format!(
                            "enums.push({}::generated_enum_descriptor_data());",
                            e.rust_name_to_file(),
                        ));
                    }

                    w.write_line(&format!(
                        "{}::reflect::GeneratedFileDescriptor::new_generated(",
                        protobuf_crate_path(&customize),
                    ));
                    w.indented(|w| {
                        w.write_line(&format!("file_descriptor_proto(),"));
                        w.write_line(&format!("deps,"));
                        w.write_line(&format!("messages,"));
                        w.write_line(&format!("enums,"));
                    });
                    w.write_line(")");
                },
            );
            w.write_line(&format!(
                "{}::reflect::FileDescriptor::new_generated_2(file_descriptor)",
                protobuf_crate_path(&customize),
            ));
        },
    );
}

pub(crate) fn write_file_descriptor_data(
    file: &FileDescriptor,
    customize: &Customize,
    w: &mut CodeWriter,
) {
    let fdp_bytes = file.proto().write_to_bytes().unwrap();
    w.write_line("static file_descriptor_proto_data: &'static [u8] = b\"\\");
    w.indented(|w| {
        const MAX_LINE_LEN: usize = 72;

        let mut s = String::new();
        for &b in &fdp_bytes {
            let prev_len = s.len();
            escape_byte(&mut s, b);
            let truncate = s.len() > MAX_LINE_LEN;
            if truncate {
                s.truncate(prev_len);
            }
            if truncate || s.len() == MAX_LINE_LEN {
                write!(s, "\\").unwrap();
                w.write_line(&s);
                s.clear();
            }
            if truncate {
                escape_byte(&mut s, b);
            }
        }
        if !s.is_empty() {
            write!(s, "\\").unwrap();
            w.write_line(&s);
            s.clear();
        }
    });
    w.write_line("\";");
    w.write_line("");
    w.write_line("/// `FileDescriptorProto` object which was a source for this generated file");
    w.def_fn(
        &format!(
            "file_descriptor_proto() -> &'static {protobuf_crate}::descriptor::FileDescriptorProto",
            protobuf_crate=protobuf_crate_path(customize)
        ),
        |w| {
            w.lazy_static_decl_get(
                "file_descriptor_proto_lazy",
                &format!(
                    "{protobuf_crate}::descriptor::FileDescriptorProto",
                    protobuf_crate=protobuf_crate_path(customize)
                ),
                &format!("{}", protobuf_crate_path(customize)),
                |w| {
                    w.write_line(&format!(
                        "{protobuf_crate}::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()",
                        protobuf_crate=protobuf_crate_path(customize)
                    ));
                },
            );
        },
    );
    w.write_line("");
    write_file_descriptor(file, &customize, w);
}

/// Code to generate call `module::file_descriptor()`.
pub(crate) fn file_descriptor_call_expr(scope: &Scope) -> String {
    format!(
        "{}()",
        scope
            .rust_path_to_file()
            .to_reverse()
            .append_ident("file_descriptor".into())
    )
}
<|endoftext|>