<commit_before>use types::{
    ValidatorRecord,
    ValidatorStatus,
};

use super::proof_of_possession::verify_proof_of_possession;
use super::registration::ValidatorRegistration;

/// The size of a validators deposit in GWei.
pub const DEPOSIT_GWEI: u64 = 32_000_000_000;

/// Inducts validators into a `CrystallizedState`.
pub struct ValidatorInductor<'a> {
    pub current_slot: u64,
    pub shard_count: u16,
    validators: &'a mut Vec<ValidatorRecord>,
    empty_validator_start: usize,
}

#[derive(Debug, PartialEq, Clone)]
pub enum ValidatorInductionError {
    InvalidShard,
    InvaidProofOfPossession,
}

impl<'a> ValidatorInductor<'a> {
    pub fn new(current_slot: u64, shard_count: u16, validators: &'a mut Vec<ValidatorRecord>)
        -> Self
    {
        Self {
            current_slot,
            shard_count,
            validators,
            empty_validator_start: 0,
        }
    }

    /// Attempt to induct a validator into the CrystallizedState.
    ///
    /// Returns an error if the registration is invalid, otherwise returns the index of the
    /// validator in `CrystallizedState.validators`.
    pub fn induct(&mut self, rego: &ValidatorRegistration)
        -> Result<usize, ValidatorInductionError>
    {
        let v = self.process_registration(rego)?;
        Ok(self.add_validator(v))
    }

    /// Verify a `ValidatorRegistration` and return a `ValidatorRecord` if valid.
    fn process_registration(&self, r: &ValidatorRegistration)
        -> Result<ValidatorRecord, ValidatorInductionError>
    {
        /*
         * Ensure withdrawal shard is not too high.
         */
        if r.withdrawal_shard > self.shard_count {
            return Err(ValidatorInductionError::InvalidShard)
        }

        /*
         * Prove validator has knowledge of their secret key.
         */
        if !verify_proof_of_possession(&r.proof_of_possession, &r.pubkey) {
            return Err(ValidatorInductionError::InvaidProofOfPossession)
        }

        Ok(ValidatorRecord {
            pubkey: r.pubkey.clone(),
            withdrawal_shard: r.withdrawal_shard,
            withdrawal_address: r.withdrawal_address,
            randao_commitment: r.randao_commitment,
            randao_last_change: self.current_slot,
            balance: DEPOSIT_GWEI,
            status: ValidatorStatus::PendingActivation as u8,
            exit_slot: 0,
        })
    }

    /// Returns the index of the first `ValidatorRecord` in the `CrystallizedState` where
    /// `validator.status == Withdrawn`. If no such record exists, `None` is returned.
    fn first_withdrawn_validator(&mut self)
        -> Option<usize>
    {
        for i in self.empty_validator_start..self.validators.len() {
            if self.validators[i].status == ValidatorStatus::Withdrawn as u8 {
                self.empty_validator_start = i + 1;
                return Some(i)
            }
        }
        None
    }

    /// Adds a `ValidatorRecord` to the `CrystallizedState` by replacing first validator where
    /// `validator.status == Withdraw`. If no such withdrawn validator exists, adds the new
    /// validator to the end of the list.
    fn add_validator(&mut self, v: ValidatorRecord)
        -> usize
    {
        match self.first_withdrawn_validator() {
            Some(i) => {
                self.validators[i] = v;
                i
            }
            None => {
                self.validators.push(v);
                self.validators.len() - 1
            }
        }
    }
}

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

    use bls::{
        Keypair,
        Signature,
    };
    use types::{
        Address,
        Hash256,
    };
    use hashing::proof_of_possession_hash;

    /// Generate a proof of possession for some keypair.
    fn get_proof_of_possession(kp: &Keypair) -> Signature {
        let pop_message = proof_of_possession_hash(&kp.pk.as_bytes());
        Signature::new_hashed(&pop_message, &kp.sk)
    }

    /// Generate a basic working ValidatorRegistration for use in tests.
    fn get_registration() -> ValidatorRegistration {
        let kp = Keypair::random();
        ValidatorRegistration {
            pubkey: kp.pk.clone(),
            withdrawal_shard: 0,
            withdrawal_address: Address::zero(),
            randao_commitment: Hash256::zero(),
            proof_of_possession: get_proof_of_possession(&kp),
        }
    }

    /// Induct a validator using the ValidatorInductor, return the result.
    fn do_induction(validator_rego: &ValidatorRegistration,
                    validators: &mut Vec<ValidatorRecord>,
                    current_slot: u64,
                    shard_count: u16)
        -> Result<usize, ValidatorInductionError>
    {
        let mut inductor = ValidatorInductor::new(
            current_slot,
            shard_count,
            validators);
        inductor.induct(&validator_rego)
    }

    #[test]
    fn test_validator_inductor_valid_empty_validators() {
        let mut validators = vec![];

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 0);
        assert_eq!(r, validators[0]);
        assert_eq!(validators.len(), 1);
    }

    #[test]
    fn test_validator_inductor_valid_all_active_validators() {
        let mut validators = vec![];
        for _ in 0..5 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Active as u8;
            validators.push(v);
        }

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 5);
        assert_eq!(r, validators[5]);
        assert_eq!(validators.len(), 6);
    }

    #[test]
    fn test_validator_inductor_valid_all_second_validator_withdrawn() {
        let mut validators = vec![];
        let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        v.status = ValidatorStatus::Active as u8;
        validators.push(v);
        for _ in 0..4 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Withdrawn as u8;
            validators.push(v);
        }

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 1);
        assert_eq!(r, validators[1]);
        assert_eq!(validators.len(), 5);
    }

    #[test]
    fn test_validator_inductor_valid_all_withdrawn_validators() {
        let mut validators = vec![];
        for _ in 0..5 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Withdrawn as u8;
            validators.push(v);
        }

        /*
         * Ensure the first validator gets the 0'th slot
         */
        let r = get_registration();
        let result = do_induction(&r, &mut validators, 0, 1024);
        assert_eq!(result.unwrap(), 0);
        assert_eq!(r, validators[0]);
        assert_eq!(validators.len(), 5);

        /*
         * Ensure the second validator gets the 1'st slot
         */
        let r_two = get_registration();
        let result = do_induction(&r_two, &mut validators, 0, 1024);
        assert_eq!(result.unwrap(), 1);
        assert_eq!(r_two, validators[1]);
        assert_eq!(validators.len(), 5);
    }

    #[test]
    fn test_validator_inductor_shard_too_high() {
        let mut validators = vec![];

        let mut r = get_registration();
        r.withdrawal_shard = 1025;

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result, Err(ValidatorInductionError::InvalidShard));
        assert_eq!(validators.len(), 0);
    }

    #[test]
    fn test_validator_inductor_shard_proof_of_possession_failure() {
        let mut validators = vec![];

        let mut r = get_registration();
        let kp = Keypair::random();
        r.proof_of_possession = get_proof_of_possession(&kp);

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result, Err(ValidatorInductionError::InvaidProofOfPossession));
        assert_eq!(validators.len(), 0);
    }
}
<commit_msg>Add to_ref method for inductor<commit_after>use types::{
    ValidatorRecord,
    ValidatorStatus,
};

use super::proof_of_possession::verify_proof_of_possession;
use super::registration::ValidatorRegistration;

/// The size of a validators deposit in GWei.
pub const DEPOSIT_GWEI: u64 = 32_000_000_000;

/// Inducts validators into a `CrystallizedState`.
pub struct ValidatorInductor<'a> {
    pub current_slot: u64,
    pub shard_count: u16,
    validators: &'a mut Vec<ValidatorRecord>,
    empty_validator_start: usize,
}

#[derive(Debug, PartialEq, Clone)]
pub enum ValidatorInductionError {
    InvalidShard,
    InvaidProofOfPossession,
}

impl<'a> ValidatorInductor<'a> {
    pub fn new(current_slot: u64, shard_count: u16, validators: &'a mut Vec<ValidatorRecord>)
        -> Self
    {
        Self {
            current_slot,
            shard_count,
            validators,
            empty_validator_start: 0,
        }
    }

    /// Attempt to induct a validator into the CrystallizedState.
    ///
    /// Returns an error if the registration is invalid, otherwise returns the index of the
    /// validator in `CrystallizedState.validators`.
    pub fn induct(&mut self, rego: &ValidatorRegistration)
        -> Result<usize, ValidatorInductionError>
    {
        let v = self.process_registration(rego)?;
        Ok(self.add_validator(v))
    }

    /// Verify a `ValidatorRegistration` and return a `ValidatorRecord` if valid.
    fn process_registration(&self, r: &ValidatorRegistration)
        -> Result<ValidatorRecord, ValidatorInductionError>
    {
        /*
         * Ensure withdrawal shard is not too high.
         */
        if r.withdrawal_shard > self.shard_count {
            return Err(ValidatorInductionError::InvalidShard)
        }

        /*
         * Prove validator has knowledge of their secret key.
         */
        if !verify_proof_of_possession(&r.proof_of_possession, &r.pubkey) {
            return Err(ValidatorInductionError::InvaidProofOfPossession)
        }

        Ok(ValidatorRecord {
            pubkey: r.pubkey.clone(),
            withdrawal_shard: r.withdrawal_shard,
            withdrawal_address: r.withdrawal_address,
            randao_commitment: r.randao_commitment,
            randao_last_change: self.current_slot,
            balance: DEPOSIT_GWEI,
            status: ValidatorStatus::PendingActivation as u8,
            exit_slot: 0,
        })
    }

    /// Returns the index of the first `ValidatorRecord` in the `CrystallizedState` where
    /// `validator.status == Withdrawn`. If no such record exists, `None` is returned.
    fn first_withdrawn_validator(&mut self)
        -> Option<usize>
    {
        for i in self.empty_validator_start..self.validators.len() {
            if self.validators[i].status == ValidatorStatus::Withdrawn as u8 {
                self.empty_validator_start = i + 1;
                return Some(i)
            }
        }
        None
    }

    /// Adds a `ValidatorRecord` to the `CrystallizedState` by replacing first validator where
    /// `validator.status == Withdraw`. If no such withdrawn validator exists, adds the new
    /// validator to the end of the list.
    fn add_validator(&mut self, v: ValidatorRecord)
        -> usize
    {
        match self.first_withdrawn_validator() {
            Some(i) => {
                self.validators[i] = v;
                i
            }
            None => {
                self.validators.push(v);
                self.validators.len() - 1
            }
        }
    }

    fn to_ref(self)
        -> &'a Vec<ValidatorRecord>
    {
        self.validators
    }
}

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

    use bls::{
        Keypair,
        Signature,
    };
    use types::{
        Address,
        Hash256,
    };
    use hashing::proof_of_possession_hash;

    /// Generate a proof of possession for some keypair.
    fn get_proof_of_possession(kp: &Keypair) -> Signature {
        let pop_message = proof_of_possession_hash(&kp.pk.as_bytes());
        Signature::new_hashed(&pop_message, &kp.sk)
    }

    /// Generate a basic working ValidatorRegistration for use in tests.
    fn get_registration() -> ValidatorRegistration {
        let kp = Keypair::random();
        ValidatorRegistration {
            pubkey: kp.pk.clone(),
            withdrawal_shard: 0,
            withdrawal_address: Address::zero(),
            randao_commitment: Hash256::zero(),
            proof_of_possession: get_proof_of_possession(&kp),
        }
    }

    /// Induct a validator using the ValidatorInductor, return the result.
    fn do_induction(validator_rego: &ValidatorRegistration,
                    validators: &mut Vec<ValidatorRecord>,
                    current_slot: u64,
                    shard_count: u16)
        -> Result<usize, ValidatorInductionError>
    {
        let mut inductor = ValidatorInductor::new(
            current_slot,
            shard_count,
            validators);
        inductor.induct(&validator_rego)
    }

    #[test]
    fn test_validator_inductor_valid_empty_validators() {
        let mut validators = vec![];

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 0);
        assert_eq!(r, validators[0]);
        assert_eq!(validators.len(), 1);
    }

    #[test]
    fn test_validator_inductor_valid_all_active_validators() {
        let mut validators = vec![];
        for _ in 0..5 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Active as u8;
            validators.push(v);
        }

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 5);
        assert_eq!(r, validators[5]);
        assert_eq!(validators.len(), 6);
    }

    #[test]
    fn test_validator_inductor_valid_all_second_validator_withdrawn() {
        let mut validators = vec![];
        let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
        v.status = ValidatorStatus::Active as u8;
        validators.push(v);
        for _ in 0..4 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Withdrawn as u8;
            validators.push(v);
        }

        let r = get_registration();

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result.unwrap(), 1);
        assert_eq!(r, validators[1]);
        assert_eq!(validators.len(), 5);
    }

    #[test]
    fn test_validator_inductor_valid_all_withdrawn_validators() {
        let mut validators = vec![];
        for _ in 0..5 {
            let (mut v, _) = ValidatorRecord::zero_with_thread_rand_keypair();
            v.status = ValidatorStatus::Withdrawn as u8;
            validators.push(v);
        }

        /*
         * Ensure the first validator gets the 0'th slot
         */
        let r = get_registration();
        let result = do_induction(&r, &mut validators, 0, 1024);
        assert_eq!(result.unwrap(), 0);
        assert_eq!(r, validators[0]);
        assert_eq!(validators.len(), 5);

        /*
         * Ensure the second validator gets the 1'st slot
         */
        let r_two = get_registration();
        let result = do_induction(&r_two, &mut validators, 0, 1024);
        assert_eq!(result.unwrap(), 1);
        assert_eq!(r_two, validators[1]);
        assert_eq!(validators.len(), 5);
    }

    #[test]
    fn test_validator_inductor_shard_too_high() {
        let mut validators = vec![];

        let mut r = get_registration();
        r.withdrawal_shard = 1025;

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result, Err(ValidatorInductionError::InvalidShard));
        assert_eq!(validators.len(), 0);
    }

    #[test]
    fn test_validator_inductor_shard_proof_of_possession_failure() {
        let mut validators = vec![];

        let mut r = get_registration();
        let kp = Keypair::random();
        r.proof_of_possession = get_proof_of_possession(&kp);

        let result = do_induction(&r, &mut validators, 0, 1024);

        assert_eq!(result, Err(ValidatorInductionError::InvaidProofOfPossession));
        assert_eq!(validators.len(), 0);
    }
}
<|endoftext|>


<commit_before>use crate::conversion_tables::*;

use std::error::Error;
use std::time;

pub struct ProgUpdate {
    pub reads_complete: u64,
    pub reads_partial: u64,
    pub writes_complete: u64,
    pub writes_partial: u64,
    pub bytes_total: u128,
    pub records_truncated: u32,
    pub duration: time::Duration,
}

pub struct ReadStat {
    pub reads_complete: u64,
    pub reads_partial: u64,
    pub records_truncated: u32,
}
impl std::ops::AddAssign for ReadStat {
    fn add_assign(&mut self, other: Self) {
        *self = Self {
            reads_complete: self.reads_complete + other.reads_complete,
            reads_partial: self.reads_partial + other.reads_partial,
            records_truncated: self.records_truncated + other.records_truncated,
        }
    }
}

pub struct WriteStat {
    pub writes_complete: u64,
    pub writes_partial: u64,
    pub bytes_total: u128,
}
impl std::ops::AddAssign for WriteStat {
    fn add_assign(&mut self, other: Self) {
        *self = Self {
            writes_complete: self.writes_complete + other.writes_complete,
            writes_partial: self.writes_partial + other.writes_partial,
            bytes_total: self.bytes_total + other.bytes_total,
        }
    }
}

type Cbs = usize;

/// Stores all Conv Flags that apply to the input
pub struct IConvFlags {
    pub ctable: Option<&'static ConversionTable>,
    pub block: Option<Cbs>,
    pub unblock: Option<Cbs>,
    pub swab: bool,
    pub sync: Option<u8>,
    pub noerror: bool,
}

/// Stores all Conv Flags that apply to the output
#[derive(Debug, PartialEq)]
pub struct OConvFlags {
    pub sparse: bool,
    pub excl: bool,
    pub nocreat: bool,
    pub notrunc: bool,
    pub fdatasync: bool,
    pub fsync: bool,
}

/// Stores all Flags that apply to the input
pub struct IFlags {
    pub cio: bool,
    pub direct: bool,
    pub directory: bool,
    pub dsync: bool,
    pub sync: bool,
    pub nocache: bool,
    pub nonblock: bool,
    pub noatime: bool,
    pub noctty: bool,
    pub nofollow: bool,
    pub nolinks: bool,
    pub binary: bool,
    pub text: bool,
    pub fullblock: bool,
    pub count_bytes: bool,
    pub skip_bytes: bool,
}

/// Stores all Flags that apply to the output
pub struct OFlags {
    pub append: bool,
    pub cio: bool,
    pub direct: bool,
    pub directory: bool,
    pub dsync: bool,
    pub sync: bool,
    pub nocache: bool,
    pub nonblock: bool,
    pub noatime: bool,
    pub noctty: bool,
    pub nofollow: bool,
    pub nolinks: bool,
    pub binary: bool,
    pub text: bool,
    pub seek_bytes: bool,
}

/// The value of the status cl-option.
/// Controls printing of transfer stats
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum StatusLevel {
    Progress,
    Noxfer,
    None,
}

/// The value of count=N
/// Defaults to Reads(N)
/// if iflag=count_bytes
/// then becomes Bytes(N)
pub enum CountType {
    Reads(usize),
    Bytes(usize),
}

#[derive(Debug)]
pub enum InternalError {
    WrongInputType,
    WrongOutputType,
    InvalidConvBlockUnblockCase,
}

impl std::fmt::Display for InternalError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::WrongInputType | Self::WrongOutputType => {
                write!(f, "Internal dd error: Wrong Input/Output data type")
            }
            Self::InvalidConvBlockUnblockCase => write!(
                f,
                "Internal dd error: Invalid Conversion, Block, or Unblock data"
            ),
        }
    }
}

impl Error for InternalError {}

pub mod options {
    pub const INFILE: &'static str = "if";
    pub const OUTFILE: &'static str = "of";
    pub const IBS: &'static str = "ibs";
    pub const OBS: &'static str = "obs";
    pub const BS: &'static str = "bs";
    pub const CBS: &'static str = "cbs";
    pub const COUNT: &'static str = "count";
    pub const SKIP: &'static str = "skip";
    pub const SEEK: &'static str = "seek";
    pub const STATUS: &'static str = "status";
    pub const CONV: &'static str = "conv";
    pub const IFLAG: &'static str = "iflag";
    pub const OFLAG: &'static str = "oflag";
}
<commit_msg>Update src/uu/dd/src/datastructures.rs<commit_after>// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) ctable noerror

use crate::conversion_tables::*;

use std::error::Error;
use std::time;

pub struct ProgUpdate {
    pub reads_complete: u64,
    pub reads_partial: u64,
    pub writes_complete: u64,
    pub writes_partial: u64,
    pub bytes_total: u128,
    pub records_truncated: u32,
    pub duration: time::Duration,
}

pub struct ReadStat {
    pub reads_complete: u64,
    pub reads_partial: u64,
    pub records_truncated: u32,
}
impl std::ops::AddAssign for ReadStat {
    fn add_assign(&mut self, other: Self) {
        *self = Self {
            reads_complete: self.reads_complete + other.reads_complete,
            reads_partial: self.reads_partial + other.reads_partial,
            records_truncated: self.records_truncated + other.records_truncated,
        }
    }
}

pub struct WriteStat {
    pub writes_complete: u64,
    pub writes_partial: u64,
    pub bytes_total: u128,
}
impl std::ops::AddAssign for WriteStat {
    fn add_assign(&mut self, other: Self) {
        *self = Self {
            writes_complete: self.writes_complete + other.writes_complete,
            writes_partial: self.writes_partial + other.writes_partial,
            bytes_total: self.bytes_total + other.bytes_total,
        }
    }
}

type Cbs = usize;

/// Stores all Conv Flags that apply to the input
pub struct IConvFlags {
    pub ctable: Option<&'static ConversionTable>,
    pub block: Option<Cbs>,
    pub unblock: Option<Cbs>,
    pub swab: bool,
    pub sync: Option<u8>,
    pub noerror: bool,
}

/// Stores all Conv Flags that apply to the output
#[derive(Debug, PartialEq)]
pub struct OConvFlags {
    pub sparse: bool,
    pub excl: bool,
    pub nocreat: bool,
    pub notrunc: bool,
    pub fdatasync: bool,
    pub fsync: bool,
}

/// Stores all Flags that apply to the input
pub struct IFlags {
    pub cio: bool,
    pub direct: bool,
    pub directory: bool,
    pub dsync: bool,
    pub sync: bool,
    pub nocache: bool,
    pub nonblock: bool,
    pub noatime: bool,
    pub noctty: bool,
    pub nofollow: bool,
    pub nolinks: bool,
    pub binary: bool,
    pub text: bool,
    pub fullblock: bool,
    pub count_bytes: bool,
    pub skip_bytes: bool,
}

/// Stores all Flags that apply to the output
pub struct OFlags {
    pub append: bool,
    pub cio: bool,
    pub direct: bool,
    pub directory: bool,
    pub dsync: bool,
    pub sync: bool,
    pub nocache: bool,
    pub nonblock: bool,
    pub noatime: bool,
    pub noctty: bool,
    pub nofollow: bool,
    pub nolinks: bool,
    pub binary: bool,
    pub text: bool,
    pub seek_bytes: bool,
}

/// The value of the status cl-option.
/// Controls printing of transfer stats
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum StatusLevel {
    Progress,
    Noxfer,
    None,
}

/// The value of count=N
/// Defaults to Reads(N)
/// if iflag=count_bytes
/// then becomes Bytes(N)
pub enum CountType {
    Reads(usize),
    Bytes(usize),
}

#[derive(Debug)]
pub enum InternalError {
    WrongInputType,
    WrongOutputType,
    InvalidConvBlockUnblockCase,
}

impl std::fmt::Display for InternalError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::WrongInputType | Self::WrongOutputType => {
                write!(f, "Internal dd error: Wrong Input/Output data type")
            }
            Self::InvalidConvBlockUnblockCase => write!(
                f,
                "Internal dd error: Invalid Conversion, Block, or Unblock data"
            ),
        }
    }
}

impl Error for InternalError {}

pub mod options {
    pub const INFILE: &'static str = "if";
    pub const OUTFILE: &'static str = "of";
    pub const IBS: &'static str = "ibs";
    pub const OBS: &'static str = "obs";
    pub const BS: &'static str = "bs";
    pub const CBS: &'static str = "cbs";
    pub const COUNT: &'static str = "count";
    pub const SKIP: &'static str = "skip";
    pub const SEEK: &'static str = "seek";
    pub const STATUS: &'static str = "status";
    pub const CONV: &'static str = "conv";
    pub const IFLAG: &'static str = "iflag";
    pub const OFLAG: &'static str = "oflag";
}
<|endoftext|>


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

//! `encoding` is a serialization library supporting zero-copy (de)serialization
//! of primitive types, heterogeneous structures and arrays.
//!
//! See also [the documentation page on serialization][doc:serialization].
//!
//! # Structure serialization
//!
//! Structures are in the root of any serializable Exonum object.
//! Binary representation of structures is split into two main parts:
//!
//! - **Header:** a fixed-sized part
//! - **Body:** dynamically sized part, known only after parsing the header
//!
//! To create a structure type, you can use [`message!`] and [`encoding_struct!`] macros.
//!
//! [doc:serialization]: https://exonum.com/doc/architecture/serialization/
//! [`message!`]: ../macro.message.html
//! [`encoding_struct!`]: ../macro.encoding_struct.html
//!
//! # Examples
//!
//! Consider a structure with two fields: `String` and `u64`.
//! To implement Exonum (de)serialization for this structure
//! you need to use macros like this:
//!
//! ```
//! # #[macro_use] extern crate exonum;
//! # extern crate serde;
//! # extern crate serde_json;
//! encoding_struct! {
//!     struct MyAwesomeStructure {
//!         name: &str,
//!         age: u64,
//!     }
//! }
//!
//! # fn main() {
//! let student = MyAwesomeStructure::new("Andrew", 23);
//! # drop(student);
//! # }
//! ```
//!
//! Then the internal buffer of `student` is as follows:
//!
//! | Position | Stored data | Hexadecimal form | Comment |
//! |:--------|:------:|:---------------------|:------------------------------------------|
//! | `0  => 4`  | 16    | `10 00 00 00`            | LE-encoded segment pointer to the data |
//! | `4  => 8`  | 6     | `06 00 00 00`            | LE-encoded segment size |
//! | `8  => 16` | 23    | `17 00 00 00 00 00 00 00` | number in little endian |
//! | `16 => 24` | Andrew | `41 6e 64 72 65 77` | Text bytes in UTF-8 encoding |
//!
//! # Structure fields
//!
//! ## Primitive types
//!
//! Primitive types are all fixed-sized, and located fully in the header.
// TODO explain how a signed integer is stored in memory (what codding) (ECR-155)
//!
//! | Type name | Size in Header | Info |
//! |:--------|:---------------------|:--------------------------------------------------|
//! | `u8`     | 1    | Regular byte  |
//! | `i8`     | 1    | Signed byte  |
//! | `u16`    | 2    | Short unsigned integer stored in little endian  |
//! | `i16`    | 2    | Short signed integer stored in little endian  |
//! | `u32`    | 4    | 32-bit unsigned integer stored in little endian  |
//! | `i32`    | 4    | 32-bit signed integer stored in little endian  |
//! | `u64`    | 8    | Long unsigned integer stored in little endian  |
//! | `i64`    | 8    | Long signed integer stored in little endian  |
//! | `F32`    | 4    | 32-bit floating point type stored in little endian \[1\]\[2\] |
//! | `F64`    | 8    | 64-bit floating point type stored in little endian \[1\]\[2\] |
//! | `bool`   | 1    | Stored as a byte, with `0x01` denoting true and `0x00` false \[3\] |
//!
//! \[1\]
//! Special floating point values that cannot be represented as a sequences of digits (such as
//! Infinity, NaN and signaling NaN) are not permitted.
//!
//! \[2\]
//! Floating point value serialization is hidden behind the `float_serialize` feature gate.
//!
//! \[3\]
//! Trying to represent other values as `bool` leads to undefined behavior.
//!
//! ## Segment fields
//!
//! All segment types take 8 bytes in the header: 4 for position in the buffer,
//! and 4 for the segment field size.
//!
//! ## Custom fields
//!
//! These types can be implemented as per developer's design,
//! but they should declare how many bytes they
//! write in the header using the [`field_size()`] function.
//!
//! [`field_size()`]: ./trait.Field.html#tymethod.field_size

use std::convert::From;
use std::ops::{Add, Sub, Mul, Div};

pub use self::fields::Field;
pub use self::segments::SegmentField;
pub use self::error::Error;
#[cfg(feature = "float_serialize")]
pub use self::float::{F32, F64};

#[macro_use]
pub mod serialize;

mod error;
#[macro_use]
mod fields;
mod segments;
#[macro_use]
mod spec;
#[cfg(feature = "float_serialize")]
mod float;

#[cfg(test)]
mod tests;

/// Type alias usable for reference in buffer
pub type Offset = u32;

/// Type alias that should be returned in `check` method of `Field`
pub type Result = ::std::result::Result<CheckedOffset, Error>;

// TODO replace by more generic type (ECR-156).
/// `CheckedOffset` is a type that take control over overflow,
/// so you can't panic without `unwrap`,
/// and work with this value without overflow checks.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub struct CheckedOffset {
    offset: Offset,
}

impl CheckedOffset {
    /// create checked value
    pub fn new(offset: Offset) -> CheckedOffset {
        CheckedOffset { offset: offset }
    }

    /// return unchecked offset
    pub fn unchecked_offset(self) -> Offset {
        self.offset
    }
}

macro_rules! implement_default_ops_checked {
    ($trait_name: ident $function:ident $checked_function:ident) => (
        impl $trait_name<CheckedOffset> for CheckedOffset {
            type Output = ::std::result::Result<CheckedOffset, Error>;
            fn $function(self, rhs: CheckedOffset) -> Self::Output {
                self.offset.$checked_function(rhs.offset)
                        .map(CheckedOffset::new)
                        .ok_or(Error::OffsetOverflow)
            }
        }
        impl $trait_name<Offset> for CheckedOffset {
            type Output = ::std::result::Result<CheckedOffset, Error>;
            fn $function(self, rhs: Offset) -> Self::Output {
                self.offset.$checked_function(rhs)
                        .map(CheckedOffset::new)
                        .ok_or(Error::OffsetOverflow)
            }
        }
    )
}

implement_default_ops_checked!{Add add checked_add }
implement_default_ops_checked!{Sub sub checked_sub }
implement_default_ops_checked!{Mul mul checked_mul }
implement_default_ops_checked!{Div div checked_div }

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

//! `encoding` is a serialization library supporting zero-copy (de)serialization
//! of primitive types, heterogeneous structures and arrays.
//!
//! See also [the documentation page on serialization][doc:serialization].
//!
//! # Structure serialization
//!
//! Structures are in the root of any serializable Exonum object.
//! Binary representation of structures is split into two main parts:
//!
//! - **Header:** a fixed-sized part
//! - **Body:** dynamically sized part, known only after parsing the header
//!
//! To create a structure type, you can use [`message!`] and [`encoding_struct!`] macros.
//!
//! [doc:serialization]: https://exonum.com/doc/architecture/serialization/
//! [`message!`]: ../macro.message.html
//! [`encoding_struct!`]: ../macro.encoding_struct.html
//!
//! # Examples
//!
//! Consider a structure with two fields: `String` and `u64`.
//! To implement Exonum (de)serialization for this structure
//! you need to use macros like this:
//!
//! ```
//! # #[macro_use] extern crate exonum;
//! # extern crate serde;
//! # extern crate serde_json;
//! encoding_struct! {
//!     struct MyAwesomeStructure {
//!         name: &str,
//!         age: u64,
//!     }
//! }
//!
//! # fn main() {
//! let student = MyAwesomeStructure::new("Andrew", 23);
//! # drop(student);
//! # }
//! ```
//!
//! Then the internal buffer of `student` is as follows:
//!
//! | Position | Stored data | Hexadecimal form | Comment |
//! |:--------|:------:|:---------------------|:------------------------------------------|
//! | `0  => 4`  | 16    | `10 00 00 00`            | LE-encoded segment pointer to the data |
//! | `4  => 8`  | 6     | `06 00 00 00`            | LE-encoded segment size |
//! | `8  => 16` | 23    | `17 00 00 00 00 00 00 00` | number in little endian |
//! | `16 => 24` | Andrew | `41 6e 64 72 65 77` | Text bytes in UTF-8 encoding |
//!
//! # Structure fields
//!
//! ## Primitive types
//!
//! Primitive types are all fixed-sized, and located fully in the header.
//!
//! | Type name | Size in Header | Info |
//! |:--------|:---------------------|:--------------------------------------------------|
//! | `u8`     | 1    | Regular byte  |
//! | `i8`     | 1    | Signed byte  |
//! | `u16`    | 2    | Short unsigned integer stored in little endian  |
//! | `i16`    | 2    | Short signed integer stored in little endian  |
//! | `u32`    | 4    | 32-bit unsigned integer stored in little endian  |
//! | `i32`    | 4    | 32-bit signed integer stored in little endian  |
//! | `u64`    | 8    | Long unsigned integer stored in little endian  |
//! | `i64`    | 8    | Long signed integer stored in little endian  |
//! | `F32`    | 4    | 32-bit floating point type stored in little endian \[1\]\[2\] |
//! | `F64`    | 8    | 64-bit floating point type stored in little endian \[1\]\[2\] |
//! | `bool`   | 1    | Stored as a byte, with `0x01` denoting true and `0x00` false \[3\] |
//!
//! \[1\]
//! Special floating point values that cannot be represented as a sequences of digits (such as
//! Infinity, NaN and signaling NaN) are not permitted.
//!
//! \[2\]
//! Floating point value serialization is hidden behind the `float_serialize` feature gate.
//!
//! \[3\]
//! Trying to represent other values as `bool` leads to undefined behavior.
//!
//! ## Segment fields
//!
//! All segment types take 8 bytes in the header: 4 for position in the buffer,
//! and 4 for the segment field size.
//!
//! ## Custom fields
//!
//! These types can be implemented as per developer's design,
//! but they should declare how many bytes they
//! write in the header using the [`field_size()`] function.
//!
//! [`field_size()`]: ./trait.Field.html#tymethod.field_size

use std::convert::From;
use std::ops::{Add, Sub, Mul, Div};

pub use self::fields::Field;
pub use self::segments::SegmentField;
pub use self::error::Error;
#[cfg(feature = "float_serialize")]
pub use self::float::{F32, F64};

#[macro_use]
pub mod serialize;

mod error;
#[macro_use]
mod fields;
mod segments;
#[macro_use]
mod spec;
#[cfg(feature = "float_serialize")]
mod float;

#[cfg(test)]
mod tests;

/// Type alias usable for reference in buffer
pub type Offset = u32;

/// Type alias that should be returned in `check` method of `Field`
pub type Result = ::std::result::Result<CheckedOffset, Error>;

// TODO replace by more generic type (ECR-156).
/// `CheckedOffset` is a type that take control over overflow,
/// so you can't panic without `unwrap`,
/// and work with this value without overflow checks.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub struct CheckedOffset {
    offset: Offset,
}

impl CheckedOffset {
    /// create checked value
    pub fn new(offset: Offset) -> CheckedOffset {
        CheckedOffset { offset: offset }
    }

    /// return unchecked offset
    pub fn unchecked_offset(self) -> Offset {
        self.offset
    }
}

macro_rules! implement_default_ops_checked {
    ($trait_name: ident $function:ident $checked_function:ident) => (
        impl $trait_name<CheckedOffset> for CheckedOffset {
            type Output = ::std::result::Result<CheckedOffset, Error>;
            fn $function(self, rhs: CheckedOffset) -> Self::Output {
                self.offset.$checked_function(rhs.offset)
                        .map(CheckedOffset::new)
                        .ok_or(Error::OffsetOverflow)
            }
        }
        impl $trait_name<Offset> for CheckedOffset {
            type Output = ::std::result::Result<CheckedOffset, Error>;
            fn $function(self, rhs: Offset) -> Self::Output {
                self.offset.$checked_function(rhs)
                        .map(CheckedOffset::new)
                        .ok_or(Error::OffsetOverflow)
            }
        }
    )
}

implement_default_ops_checked!{Add add checked_add }
implement_default_ops_checked!{Sub sub checked_sub }
implement_default_ops_checked!{Mul mul checked_mul }
implement_default_ops_checked!{Div div checked_div }

impl From<Offset> for CheckedOffset {
    fn from(offset: Offset) -> CheckedOffset {
        CheckedOffset::new(offset)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(old_io)]
#![feature(io)]
#![feature(os)]
#![feature(std_misc)]
#![allow(deprecated)] // old_io Timer replacement not stable

#[macro_use]
extern crate sysfs_gpio;

use sysfs_gpio::core::{Direction, Pin};
use std::time::Duration;
use std::old_io::Timer;
use std::io;
use std::os;

struct Arguments {
    pin : u64,
    duration_ms : i64,
    period_ms : i64,
}

// export a GPIO for use.  This will not fail
// if already exported
fn blink_my_led(led : u64, duration_ms : i64, period_ms : i64) -> io::Result<()> {
    let my_led = Pin::new(led);

    try!(my_led.export());
    try_unexport!(my_led, my_led.set_direction(Direction::Low));
    let mut tmr = match Timer::new() {
        Ok(tmr) => tmr,
        Err(_) => panic!("Could not create timer!"),
    };
    let iterations = duration_ms / period_ms / 2;
    println!("./blinky {} {} {}", led, duration_ms, period_ms);
    println!("Iterations: {}", iterations);
    for _ in 0..iterations {
        try_unexport!(my_led, my_led.set_value(0));
        tmr.sleep(Duration::milliseconds(period_ms));
        try_unexport!(my_led, my_led.set_value(1));
        tmr.sleep(Duration::milliseconds(period_ms));
    }
    try_unexport!(my_led, my_led.set_value(0));
    try!(my_led.unexport());
    return Ok(());
}

fn print_usage() {
    println!("Usage: ./blinky <pin> <duration_ms> <period_ms>");
}

fn get_args() -> Option<Arguments> {
    let args = os::args();
    if args.len() != 4 { return None; }
    let pin = match args[1].parse::<u64>() { Ok(pin) => pin, Err(_) => return None, };
    let duration_ms = match args[2].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    let period_ms = match args[3].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    Some(Arguments { pin: pin, duration_ms: duration_ms, period_ms: period_ms, })
}

fn main() {
    match get_args() {
        None => print_usage(),
        Some(args) => {
            match blink_my_led(args.pin, args.duration_ms, args.period_ms) {
                Ok(()) => println!("Success!"),
                Err(err) => println!("We have a blinking problem: {}", err),
            }
        },
    }
}
<commit_msg>examples: cleanup example<commit_after>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(old_io)]
#![feature(io)]
#![feature(os)]
#![feature(std_misc)]
#![allow(deprecated)] // old_io Timer replacement not stable

#[macro_use]
extern crate sysfs_gpio;

use sysfs_gpio::core::{Direction, Pin};
use std::time::Duration;
use std::old_io::Timer;
use std::io;
use std::os;

struct Arguments {
    pin : u64,
    duration_ms : i64,
    period_ms : i64,
}

// export a GPIO for use.  This will not fail
// if already exported
fn blink_my_led(led : u64, duration_ms : i64, period_ms : i64) -> io::Result<()> {
    let my_led = Pin::new(led);

    try!(my_led.export());
    try_unexport!(my_led, my_led.set_direction(Direction::Low));
    let mut tmr = match Timer::new() {
        Ok(tmr) => tmr,
        Err(_) => panic!("Could not create timer!"),
    };
    let iterations = duration_ms / period_ms / 2;
    for _ in 0..iterations {
        try_unexport!(my_led, my_led.set_value(0));
        tmr.sleep(Duration::milliseconds(period_ms));
        try_unexport!(my_led, my_led.set_value(1));
        tmr.sleep(Duration::milliseconds(period_ms));
    }
    try_unexport!(my_led, my_led.set_value(0));
    try!(my_led.unexport());
    return Ok(());
}

fn print_usage() {
    println!("Usage: ./blinky <pin> <duration_ms> <period_ms>");
}

fn get_args() -> Option<Arguments> {
    let args = os::args();
    if args.len() != 4 { return None; }
    let pin = match args[1].parse::<u64>() { Ok(pin) => pin, Err(_) => return None, };
    let duration_ms = match args[2].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    let period_ms = match args[3].parse::<i64>() { Ok(ms) => ms, Err(_) => return None, };
    Some(Arguments { pin: pin, duration_ms: duration_ms, period_ms: period_ms, })
}

fn main() {
    match get_args() {
        None => print_usage(),
        Some(args) => {
            match blink_my_led(args.pin, args.duration_ms, args.period_ms) {
                Ok(()) => println!("Success!"),
                Err(err) => println!("We have a blinking problem: {}", err),
            }
        },
    }
}
<|endoftext|>


<commit_before>#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

#![ feature( trace_macros ) ]

use fundamental_data_type as TheModule;

#[ path = "./inc.rs" ]
mod inc;

// zzz : move to inc after implementing macro to check presence of a dependency

#[ test_tools::rustversion::nightly ]
#[ test ]
fn trybuild_tests()
{
  use test_tools::trybuild;
  println!( "current_dir : {:?}", std::env::current_dir().unwrap() );
  let t = trybuild::TestCases::new();
  t.compile_fail( "../../../rust/test/dt/fundamental_data_type/dynamic/*.rs" );
}
<commit_msg>evolve single and pair<commit_after>#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

// #![ feature( trace_macros ) ]

use fundamental_data_type as TheModule;

#[ path = "./inc.rs" ]
mod inc;

// zzz : move to inc after implementing macro to check presence of a dependency

#[ test_tools::rustversion::nightly ]
#[ test ]
fn trybuild_tests()
{
  use test_tools::trybuild;
  println!( "current_dir : {:?}", std::env::current_dir().unwrap() );
  let t = trybuild::TestCases::new();
  t.compile_fail( "../../../rust/test/dt/fundamental_data_type/dynamic/*.rs" );
}
<|endoftext|>


<commit_before>extern crate rusttype;

use rusttype::{FontCollection, PixelsXY, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font

    // Desired font pixel height
    let height: f32 = 12.5; // to get 80 chars across (fits most terminals); adjust as desired
    let pixel_height = height.ceil() as usize;

    // 2x scale in x direction to counter the aspect ratio of monospace characters.
    let scale = PixelsXY(height*2.0, height);

    // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
    // We don't want to clip the text, so we shift it down with an offset when laying it out.
    // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
    // the font. That's enough to guarantee that there's no clipping.
    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    // Glyphs to draw for "Hello!". Feel free to try other strings.
    let glyphs: Vec<PositionedGlyph> = font.layout("RustType", scale, offset).collect();

    // Find the most visually pleasing width to display
    let width = glyphs.iter().map(|g| g.h_metrics().advance_width)
        .fold(0.0, |x, y| x + y).ceil() as usize;

    println!("width: {}, height: {}", width, pixel_height);

    // Rasterise directly into ASCII art.
    let mut pixel_data = vec![b'@'; width * pixel_height];
    let mapping = b"@%#x+=:-. "; // The approximation of greyscale
    let mapping_scale = (mapping.len()-1) as f32;
    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                // v should be in the range 0.0 to 1.0
                let i = (v*mapping_scale + 0.5) as usize;
                // so something's wrong if you get $ in the output.
                let c = mapping.get(i).cloned().unwrap_or(b'$');
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                pixel_data[(x + y * width)] = c;
            })
        }
    }

    // Print it out
    let stdout = ::std::io::stdout();
    let mut handle = stdout.lock();
    for j in 0..pixel_height {
        handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
        handle.write(b"\n").unwrap();
    }
}
<commit_msg>Fixed typo in docs in example.<commit_after>extern crate rusttype;

use rusttype::{FontCollection, PixelsXY, point, PositionedGlyph};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font

    // Desired font pixel height
    let height: f32 = 12.5; // to get 80 chars across (fits most terminals); adjust as desired
    let pixel_height = height.ceil() as usize;

    // 2x scale in x direction to counter the aspect ratio of monospace characters.
    let scale = PixelsXY(height*2.0, height);

    // The origin of a line of text is at the baseline (roughly where non-descending letters sit).
    // We don't want to clip the text, so we shift it down with an offset when laying it out.
    // v_metrics.ascent is the distance between the baseline and the highest edge of any glyph in
    // the font. That's enough to guarantee that there's no clipping.
    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    // Glyphs to draw for "RustType". Feel free to try other strings.
    let glyphs: Vec<PositionedGlyph> = font.layout("RustType", scale, offset).collect();

    // Find the most visually pleasing width to display
    let width = glyphs.iter().map(|g| g.h_metrics().advance_width)
        .fold(0.0, |x, y| x + y).ceil() as usize;

    println!("width: {}, height: {}", width, pixel_height);

    // Rasterise directly into ASCII art.
    let mut pixel_data = vec![b'@'; width * pixel_height];
    let mapping = b"@%#x+=:-. "; // The approximation of greyscale
    let mapping_scale = (mapping.len()-1) as f32;
    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                // v should be in the range 0.0 to 1.0
                let i = (v*mapping_scale + 0.5) as usize;
                // so something's wrong if you get $ in the output.
                let c = mapping.get(i).cloned().unwrap_or(b'$');
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                pixel_data[(x + y * width)] = c;
            })
        }
    }

    // Print it out
    let stdout = ::std::io::stdout();
    let mut handle = stdout.lock();
    for j in 0..pixel_height {
        handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
        handle.write(b"\n").unwrap();
    }
}
<|endoftext|>


<commit_before>// quiz.rs
// This is a quiz for the following sections:
// - Tests

// This quiz isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests that we get the result
// we expect to get when we call `times_two` with a negative number.
// No hints, you can do this :)

// I AM NOT DONE

pub fn times_two(num: i32) -> i32 {
    num * 2
}

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

    #[test]
    fn returns_twice_of_positive_numbers() {
        assert_eq!(times_two(4), ???);
    }

    #[test]
    fn returns_twice_of_negative_numbers() {
        // TODO write an assert for `times_two(-4)`
    }
}
<commit_msg>fix: fix quiz naming inconsistency (#421)<commit_after>// quiz3.rs
// This is a quiz for the following sections:
// - Tests

// This quiz isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests that we get the result
// we expect to get when we call `times_two` with a negative number.
// No hints, you can do this :)

// I AM NOT DONE

pub fn times_two(num: i32) -> i32 {
    num * 2
}

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

    #[test]
    fn returns_twice_of_positive_numbers() {
        assert_eq!(times_two(4), ???);
    }

    #[test]
    fn returns_twice_of_negative_numbers() {
        // TODO write an assert for `times_two(-4)`
    }
}
<|endoftext|>


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

use context::GraphicsContextMethods;

use libc::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
use std::ptr::null;
use sync::Arc;

// Constants.

static GLX_RGBA: c_int = 4;
/*static GLX_RED_SIZE: c_int = 8;
static GLX_GREEN_SIZE: c_int = 9;
static GLX_BLUE_SIZE: c_int = 10;*/
static GLX_DEPTH_SIZE: c_int = 12;

static ATTRIBUTES: [c_int, ..4] = [
    GLX_RGBA,
    GLX_DEPTH_SIZE, 24,
    0,
];

// External bindings to Xlib.

// Opaque structures.
struct _XPrivate;
struct _XrmHashBucketRec;
struct Depth;
struct GLXContextOpaque;
struct Visual;

// Sadly we need to copy some of this definition in here because the Xlib macros need to access it.
struct Display {
    ext_data: *XExtData,
    private1: *_XPrivate,
    fd: c_int,
    private2: c_int,
    proto_major_version: c_int,
    proto_minor_version: c_int,
    vendor: *c_char,
    private3: XID,
    private4: XID,
    private5: XID,
    private6: c_int,
    resource_alloc: *c_void,
    byte_order: c_int,
    bitmap_unit: c_int,
    bitmap_pad: c_int,
    bitmap_bit_order: c_int,
    nformats: c_int,
    pixmap_format: *ScreenFormat,
    private8: c_int,
    release: c_int,
    private9: *_XPrivate,
    private10: *_XPrivate,
    qlen: c_int,
    last_request_read: c_ulong,
    request: c_ulong,
    private11: XPointer,
    private12: XPointer,
    private13: XPointer,
    private14: XPointer,
    max_request_size: c_uint,
    db: *_XrmHashBucketRec,
    private15: *c_void,
    display_name: *c_char,

    // FIXME(pcwalton): These are needed for some reason...
    pad: *c_void,
    pad1: *c_void,

    default_screen: c_int,
    nscreens: c_int,
    screens: *Screen,
}

struct Screen {
    ext_data: *XExtData,
    display: *Display,
    root: Window,
    width: c_int,
    height: c_int,
    mwidth: c_int,
    mheight: c_int,
    ndepths: c_int,
    depths: *Depth,
    root_depth: c_int,
    root_visual: *Visual,
    default_gc: GC,
    cmap: Colormap,
    white_pixel: c_ulong,
    black_pixel: c_ulong,
    max_maps: c_int,
    min_maps: c_int,
    backing_store: c_int,
    save_unders: Bool,
    root_input_mask: c_long,
    pad: *c_void,
}

struct ScreenFormat;
struct XExtData;

struct XVisualInfo {
    visual: *Visual,
    visualid: VisualID,
    screen: c_int,
    depth: c_int,
    class: c_int,
    red_mask: c_ulong,
    green_mask: c_ulong,
    blue_mask: c_ulong,
    colormap_size: c_int,
    bits_per_rgb: c_int,
}

type Bool = c_int;
type Colormap = XID;
type Drawable = c_uint;                 // compatible with Window
type GC = *c_void;
type GLXContext = *GLXContextOpaque;
type GLXDrawable = c_uint;              // compatible with GLXPixmap
type GLXPixmap = c_uint;                // compatible with GLXDrawable
type Pixmap = c_uint;
type VisualID = c_ulong;
type Window = c_uint;                   // compatible with Drawable
type XID = c_uint;
type XPointer = *c_void;

#[link(name = "X11")]
#[link(name = "GL")]
extern {
    fn XOpenDisplay(n: c_int) -> *Display;
    fn XCreatePixmap(display: *Display, d: Drawable, width: c_uint, height: c_uint, depth: c_uint)
                     -> Pixmap;

    fn glXChooseVisual(dpy: *Display, screen: c_int, attribList: *c_int) -> *XVisualInfo;
    fn glXCreateContext(dpy: *Display, vis: *XVisualInfo, shareList: GLXContext, direct: Bool)
                        -> GLXContext;
    fn glXCreateGLXPixmap(dpy: *Display, vis: *XVisualInfo, pixmap: Pixmap) -> GLXPixmap;
    fn glXMakeContextCurrent(dpy: *Display, draw: GLXDrawable, read: GLXDrawable, ctx: GLXContext)
                             -> Bool;
}

// X11 macros

fn DefaultScreen(dpy: *Display) -> c_int {
    unsafe {
        (*dpy).default_screen
    }
}
fn RootWindow(dpy: *Display, scr: c_int) -> Window {
    unsafe {
        (*ScreenOfDisplay(dpy, scr)).root
    }
}
fn ScreenOfDisplay(dpy: *Display, scr: c_int) -> *Screen {
    unsafe {
        (&(*dpy).screens).offset(scr as int)
    }
}

// Implementation

/// Linux-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    display: *Display,
    pixmap: GLXPixmap,
    context: Arc<GLXContext>,
}

impl GraphicsContext {
    // Creates a new, possibly shared, GLX context.
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        let (display, visual, pixmap) = GraphicsContext::create_display_visual_and_pixmap();

        unsafe {
            let context = match share_context {
                None => glXCreateContext(display, visual, null(), 1),
                Some(share_context) => {
                    let native_share_context = share_context.native();
                    glXCreateContext(display, visual, *native_share_context, 1)
                }
            };

            assert!(context != null());

            GraphicsContext {
                display: display,
                pixmap: pixmap,
                context: Arc::new(context),
            }
        }
    }

    fn create_display_visual_and_pixmap() -> (*Display, *XVisualInfo, GLXPixmap) {
        unsafe {
            // Get a connection.
            let display = XOpenDisplay(0);

            // Get an appropriate visual.
            let visual = glXChooseVisual(display, DefaultScreen(display), &ATTRIBUTES[0]);

            // Create the pixmap.
            let root_window = RootWindow(display, DefaultScreen(display));
            let pixmap = XCreatePixmap(display, root_window, 10, 10, 24);
            let glx_pixmap = glXCreateGLXPixmap(display, visual, pixmap);

            debug!("XCreatePixmap returned {}, glXCreateGLXPixmap returned {}",
                   pixmap,
                   glx_pixmap);

            (display, visual, glx_pixmap)
        }
    }
}

impl GraphicsContextMethods<GLXContext> for GraphicsContext {
    /// Wraps the given instance of the native GLX graphics context, bumping the reference count in
    /// the process.
    fn wrap(instance: Arc<GLXContext>) -> GraphicsContext {
        let (display, _, pixmap) = GraphicsContext::create_display_visual_and_pixmap();
        GraphicsContext {
            display: display,
            pixmap: pixmap,
            context: instance.clone(),
        }
    }

    /// Returns the underlying native 3D context.
    fn native(&self) -> Arc<GLXContext> {
        self.context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
    fn make_current(&self) {
        unsafe {
            let result = glXMakeContextCurrent(self.display,
                                               self.pixmap,
                                               self.pixmap,
                                               *self.context);
            assert!(result != 0);
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContext {
            display: self.display,
            pixmap: self.pixmap,
            context: self.context.clone(),
        }
    }
}

<commit_msg>Make GLXContext public. Used in pub sigs<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use context::GraphicsContextMethods;

use libc::{c_char, c_int, c_long, c_uint, c_ulong, c_void};
use std::ptr::null;
use sync::Arc;

// Constants.

static GLX_RGBA: c_int = 4;
/*static GLX_RED_SIZE: c_int = 8;
static GLX_GREEN_SIZE: c_int = 9;
static GLX_BLUE_SIZE: c_int = 10;*/
static GLX_DEPTH_SIZE: c_int = 12;

static ATTRIBUTES: [c_int, ..4] = [
    GLX_RGBA,
    GLX_DEPTH_SIZE, 24,
    0,
];

// External bindings to Xlib.

// Opaque structures.
struct _XPrivate;
struct _XrmHashBucketRec;
struct Depth;
struct GLXContextOpaque;
struct Visual;

// Sadly we need to copy some of this definition in here because the Xlib macros need to access it.
struct Display {
    ext_data: *XExtData,
    private1: *_XPrivate,
    fd: c_int,
    private2: c_int,
    proto_major_version: c_int,
    proto_minor_version: c_int,
    vendor: *c_char,
    private3: XID,
    private4: XID,
    private5: XID,
    private6: c_int,
    resource_alloc: *c_void,
    byte_order: c_int,
    bitmap_unit: c_int,
    bitmap_pad: c_int,
    bitmap_bit_order: c_int,
    nformats: c_int,
    pixmap_format: *ScreenFormat,
    private8: c_int,
    release: c_int,
    private9: *_XPrivate,
    private10: *_XPrivate,
    qlen: c_int,
    last_request_read: c_ulong,
    request: c_ulong,
    private11: XPointer,
    private12: XPointer,
    private13: XPointer,
    private14: XPointer,
    max_request_size: c_uint,
    db: *_XrmHashBucketRec,
    private15: *c_void,
    display_name: *c_char,

    // FIXME(pcwalton): These are needed for some reason...
    pad: *c_void,
    pad1: *c_void,

    default_screen: c_int,
    nscreens: c_int,
    screens: *Screen,
}

struct Screen {
    ext_data: *XExtData,
    display: *Display,
    root: Window,
    width: c_int,
    height: c_int,
    mwidth: c_int,
    mheight: c_int,
    ndepths: c_int,
    depths: *Depth,
    root_depth: c_int,
    root_visual: *Visual,
    default_gc: GC,
    cmap: Colormap,
    white_pixel: c_ulong,
    black_pixel: c_ulong,
    max_maps: c_int,
    min_maps: c_int,
    backing_store: c_int,
    save_unders: Bool,
    root_input_mask: c_long,
    pad: *c_void,
}

struct ScreenFormat;
struct XExtData;

struct XVisualInfo {
    visual: *Visual,
    visualid: VisualID,
    screen: c_int,
    depth: c_int,
    class: c_int,
    red_mask: c_ulong,
    green_mask: c_ulong,
    blue_mask: c_ulong,
    colormap_size: c_int,
    bits_per_rgb: c_int,
}

type Bool = c_int;
type Colormap = XID;
type Drawable = c_uint;                 // compatible with Window
type GC = *c_void;
pub type GLXContext = *GLXContextOpaque;
type GLXDrawable = c_uint;              // compatible with GLXPixmap
type GLXPixmap = c_uint;                // compatible with GLXDrawable
type Pixmap = c_uint;
type VisualID = c_ulong;
type Window = c_uint;                   // compatible with Drawable
type XID = c_uint;
type XPointer = *c_void;

#[link(name = "X11")]
#[link(name = "GL")]
extern {
    fn XOpenDisplay(n: c_int) -> *Display;
    fn XCreatePixmap(display: *Display, d: Drawable, width: c_uint, height: c_uint, depth: c_uint)
                     -> Pixmap;

    fn glXChooseVisual(dpy: *Display, screen: c_int, attribList: *c_int) -> *XVisualInfo;
    fn glXCreateContext(dpy: *Display, vis: *XVisualInfo, shareList: GLXContext, direct: Bool)
                        -> GLXContext;
    fn glXCreateGLXPixmap(dpy: *Display, vis: *XVisualInfo, pixmap: Pixmap) -> GLXPixmap;
    fn glXMakeContextCurrent(dpy: *Display, draw: GLXDrawable, read: GLXDrawable, ctx: GLXContext)
                             -> Bool;
}

// X11 macros

fn DefaultScreen(dpy: *Display) -> c_int {
    unsafe {
        (*dpy).default_screen
    }
}
fn RootWindow(dpy: *Display, scr: c_int) -> Window {
    unsafe {
        (*ScreenOfDisplay(dpy, scr)).root
    }
}
fn ScreenOfDisplay(dpy: *Display, scr: c_int) -> *Screen {
    unsafe {
        (&(*dpy).screens).offset(scr as int)
    }
}

// Implementation

/// Linux-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    display: *Display,
    pixmap: GLXPixmap,
    context: Arc<GLXContext>,
}

impl GraphicsContext {
    // Creates a new, possibly shared, GLX context.
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        let (display, visual, pixmap) = GraphicsContext::create_display_visual_and_pixmap();

        unsafe {
            let context = match share_context {
                None => glXCreateContext(display, visual, null(), 1),
                Some(share_context) => {
                    let native_share_context = share_context.native();
                    glXCreateContext(display, visual, *native_share_context, 1)
                }
            };

            assert!(context != null());

            GraphicsContext {
                display: display,
                pixmap: pixmap,
                context: Arc::new(context),
            }
        }
    }

    fn create_display_visual_and_pixmap() -> (*Display, *XVisualInfo, GLXPixmap) {
        unsafe {
            // Get a connection.
            let display = XOpenDisplay(0);

            // Get an appropriate visual.
            let visual = glXChooseVisual(display, DefaultScreen(display), &ATTRIBUTES[0]);

            // Create the pixmap.
            let root_window = RootWindow(display, DefaultScreen(display));
            let pixmap = XCreatePixmap(display, root_window, 10, 10, 24);
            let glx_pixmap = glXCreateGLXPixmap(display, visual, pixmap);

            debug!("XCreatePixmap returned {}, glXCreateGLXPixmap returned {}",
                   pixmap,
                   glx_pixmap);

            (display, visual, glx_pixmap)
        }
    }
}

impl GraphicsContextMethods<GLXContext> for GraphicsContext {
    /// Wraps the given instance of the native GLX graphics context, bumping the reference count in
    /// the process.
    fn wrap(instance: Arc<GLXContext>) -> GraphicsContext {
        let (display, _, pixmap) = GraphicsContext::create_display_visual_and_pixmap();
        GraphicsContext {
            display: display,
            pixmap: pixmap,
            context: instance.clone(),
        }
    }

    /// Returns the underlying native 3D context.
    fn native(&self) -> Arc<GLXContext> {
        self.context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
    fn make_current(&self) {
        unsafe {
            let result = glXMakeContextCurrent(self.display,
                                               self.pixmap,
                                               self.pixmap,
                                               *self.context);
            assert!(result != 0);
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContext {
            display: self.display,
            pixmap: self.pixmap,
            context: self.context.clone(),
        }
    }
}

<|endoftext|>


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

use dom::bindings::callback::ReportExceptions;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived};
use dom::bindings::js::{JSRef, OptionalSettable, OptionalRootable, Root};
use dom::eventtarget::{Capturing, Bubbling, EventTarget};
use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing, EventMethods};
use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for;

// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
                              pseudo_target: Option<JSRef<'b, EventTarget>>,
                              event: &JSRef<Event>) -> bool {
    assert!(!event.deref().dispatching.deref().get());

    event.target.assign(Some(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    }));
    event.dispatching.deref().set(true);

    let type_ = event.Type();

    //TODO: no chain if not participating in a tree
    let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() {
        let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap();
        target_node.ancestors().map(|ancestor| {
            let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor);
            ancestor_target.unrooted().root()
        }).collect()
    } else {
        vec!()
    };

    event.deref().phase.deref().set(PhaseCapturing);

    //FIXME: The "callback this value" should be currentTarget

    /* capturing */
    for cur_target in chain.as_slice().iter().rev() {
        let stopped = match cur_target.get_listeners_for(type_.as_slice(), Capturing) {
            Some(listeners) => {
                event.current_target.assign(Some(cur_target.deref().clone()));
                for listener in listeners.iter() {
                    // Explicitly drop any exception on the floor.
                    let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                    if event.deref().stop_immediate.deref().get() {
                        break;
                    }
                }

                event.deref().stop_propagation.deref().get()
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.deref().stop_propagation.deref().get() {
        event.phase.deref().set(PhaseAtTarget);
        event.current_target.assign(Some(target.clone()));

        let opt_listeners = target.deref().get_listeners(type_.as_slice());
        for listeners in opt_listeners.iter() {
            for listener in listeners.iter() {
                // Explicitly drop any exception on the floor.
                let _ = listener.HandleEvent_(target, event, ReportExceptions);

                if event.deref().stop_immediate.deref().get() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() {
        event.deref().phase.deref().set(PhaseBubbling);

        for cur_target in chain.iter() {
            let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) {
                Some(listeners) => {
                    event.deref().current_target.assign(Some(cur_target.deref().clone()));
                    for listener in listeners.iter() {
                        // Explicitly drop any exception on the floor.
                        let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                        if event.deref().stop_immediate.deref().get() {
                            break;
                        }
                    }

                    event.deref().stop_propagation.deref().get()
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget().root();
    match target {
        Some(mut target) => {
            let node: Option<&JSRef<Node>> = NodeCast::to_ref(&mut *target);
            match node {
                Some(node) =>{
                    let vtable = vtable_for(node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    // Root ordering restrictions mean we need to unroot the chain entries
    // in the same order they were rooted.
    while chain.len() > 0 {
        let _ = chain.pop();
    }

    event.dispatching.deref().set(false);
    event.phase.deref().set(PhaseNone);
    event.current_target.set(None);

    !event.DefaultPrevented()
}
<commit_msg>Cleanup a mutable variable in dispatch_event.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::callback::ReportExceptions;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived};
use dom::bindings::js::{JSRef, OptionalSettable, OptionalRootable, Root};
use dom::eventtarget::{Capturing, Bubbling, EventTarget};
use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing, EventMethods};
use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for;

// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
                              pseudo_target: Option<JSRef<'b, EventTarget>>,
                              event: &JSRef<Event>) -> bool {
    assert!(!event.deref().dispatching.deref().get());

    event.target.assign(Some(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    }));
    event.dispatching.deref().set(true);

    let type_ = event.Type();

    //TODO: no chain if not participating in a tree
    let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() {
        let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap();
        target_node.ancestors().map(|ancestor| {
            let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor);
            ancestor_target.unrooted().root()
        }).collect()
    } else {
        vec!()
    };

    event.deref().phase.deref().set(PhaseCapturing);

    //FIXME: The "callback this value" should be currentTarget

    /* capturing */
    for cur_target in chain.as_slice().iter().rev() {
        let stopped = match cur_target.get_listeners_for(type_.as_slice(), Capturing) {
            Some(listeners) => {
                event.current_target.assign(Some(cur_target.deref().clone()));
                for listener in listeners.iter() {
                    // Explicitly drop any exception on the floor.
                    let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                    if event.deref().stop_immediate.deref().get() {
                        break;
                    }
                }

                event.deref().stop_propagation.deref().get()
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.deref().stop_propagation.deref().get() {
        event.phase.deref().set(PhaseAtTarget);
        event.current_target.assign(Some(target.clone()));

        let opt_listeners = target.deref().get_listeners(type_.as_slice());
        for listeners in opt_listeners.iter() {
            for listener in listeners.iter() {
                // Explicitly drop any exception on the floor.
                let _ = listener.HandleEvent_(target, event, ReportExceptions);

                if event.deref().stop_immediate.deref().get() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() {
        event.deref().phase.deref().set(PhaseBubbling);

        for cur_target in chain.iter() {
            let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) {
                Some(listeners) => {
                    event.deref().current_target.assign(Some(cur_target.deref().clone()));
                    for listener in listeners.iter() {
                        // Explicitly drop any exception on the floor.
                        let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);

                        if event.deref().stop_immediate.deref().get() {
                            break;
                        }
                    }

                    event.deref().stop_propagation.deref().get()
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget().root();
    match target {
        Some(target) => {
            let node: Option<&JSRef<Node>> = NodeCast::to_ref(&*target);
            match node {
                Some(node) => {
                    let vtable = vtable_for(node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    // Root ordering restrictions mean we need to unroot the chain entries
    // in the same order they were rooted.
    while chain.len() > 0 {
        let _ = chain.pop();
    }

    event.dispatching.deref().set(false);
    event.phase.deref().set(PhaseNone);
    event.current_target.set(None);

    !event.DefaultPrevented()
}
<|endoftext|>


<commit_before>//! A simple module for creating an OFS disk image

use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::cmp::min;
use std::mem;

/// The size of a sector in bytes
pub const SECTOR_SIZE: u32 = 512; // bytes

const INODE_SIZE: usize = 128; // bytes
const DNODE_SIZE: usize = 512; // bytes

/// Represents an OFS disk image, which can be written to a file
pub struct OFSImage {
    /// The number of inodes in the fs
    num_inodes: u32,

    /// The number of dnodes in the fs
    num_dnodes: u32,

    /// A list of inodes
    inodes: Vec<Option<Inode>>,

    /// A list of dnodes
    dnodes: Vec<Option<Dnode>>,
}

#[derive(Clone, Copy)]
#[repr(C, packed)]
struct Inode {
    name: [u8; 12],         // file name (up to 12B)
    uid: u32,             // owner UID
    gid: u32,             // group GID
    user_perm: u8,          // user permissions
    group_perm: u8,         // group permissions
    all_perm: u8,           // everyone permissions
    flags:u8,               // various flags
    size: u32,            // file size in bytes
    data: u32,            // index of Dnode with contents
    created: u32,       // date created
    modified: u32,      // date last modified
    parents: [u32; 10],
    children: [u32; 12],
}

impl Inode {
    fn new() -> Inode {
        Inode {
            name: [0; 12],
            uid: 0,
            gid: 0,
            user_perm: 0,
            group_perm: 0,
            all_perm: 0,
            flags: 0,
            size: 0,
            data: 0,
            created: 0,
            modified: 0,
            parents: [0; 10],
            children: [0; 12],
        }
    }
}

#[derive(Copy)]
#[repr(C, packed)]
struct Dnode {
    bytes: [u8; DNODE_SIZE], // contents
}

impl Clone for Dnode {
    fn clone(&self) -> Dnode {
        let mut cloned = [0; DNODE_SIZE];
        for d in 0..cloned.len() {
            cloned[d] = self.bytes[d];
        }
        Dnode {
            bytes: cloned
        }
    }
}

impl OFSImage {
    /// Create a new OFSImage with the given numbers of inodes and dnodes.
    pub fn new(num_inodes: u32, num_dnodes: u32) -> OFSImage {
        let mut inodes = Vec::with_capacity(num_inodes as usize);
        let mut dnodes = Vec::with_capacity(num_dnodes as usize);

        for _ in 0..num_inodes {
            inodes.push(None)
        }

        for _ in 0..num_dnodes {
            dnodes.push(None)
        }

        OFSImage {
            num_inodes: num_inodes,
            num_dnodes: num_dnodes,
            inodes: inodes,
            dnodes: dnodes,
        }
    }

    /// Allocate an inode in the file system and return mutable reference to it.
    pub fn alloc_inode(&mut self) -> &mut Inode {
        let first_free = (0..self.num_inodes)
            .find(|i| self.inodes.get_mut(*i as usize).unwrap().is_none())
            .unwrap_or_else(|| panic!("No inodes left!")) as usize;

        *self.inodes.get_mut(first_free).unwrap() = Some(Inode::new());

        self.inodes.get_mut(first_free)
                   .unwrap()
                   .as_mut()
                   .unwrap()
    }

    /// Allocate a dnode in the file system and return its dnode index.
    pub fn alloc_dnode(&mut self) -> usize {
        let first_free = (0..self.num_dnodes)
            .find(|i| self.dnodes.get_mut(*i as usize).unwrap().is_none())
            .unwrap_or_else(|| panic!("No dnodes left!")) as usize;

        *self.dnodes.get_mut(first_free).unwrap() = Some(Dnode {
            bytes: [0; DNODE_SIZE],
        });

        first_free
    }

    /// Get the `i`th dnode.
    ///
    /// # Panics
    /// if the `i`th dnode is not allocated
    pub fn get_dnode(&mut self, i: u32) -> &mut Dnode {
        self.dnodes.get_mut(i as usize)
                   .unwrap()
                   .as_mut()
                   .unwrap_or_else(|| panic!("dnode {} is not allocated", i))
    }

    /// Copy the file (on the host machine) to the OFS image. No guarantees are made about
    /// the order of inodes or dnodes chosen.
    pub fn add_file(&mut self, file: &str) {
        // open the file and read it
        if !Path::new(file).is_file() {
            println!("Error! No such file or directory '{}'.", file);
            exit(1);
        }
        let mut f = File::open(file).ok().unwrap(); // TODO: check if exists

        // get the file size (bytes)
        let size = f.metadata().ok().unwrap().len();

        // create the dnodes
        let mut remaining = size;
        let mut first_dnode = 0;

        let mut next_dnode = first_dnode;
        while remaining > DNODE_SIZE as u64 {
            // allocate a dnode
            let prev_dnode = next_dnode;
            next_dnode = self.alloc_dnode();
            if remaining == size {
                // don't forget where the file begins ;)
                first_dnode = next_dnode;
            } else {
                // chain the dnodes
                let dnode = self.get_dnode(prev_dnode as u32);
                dnode.bytes[DNODE_SIZE-1] = ((next_dnode >> 24) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-2] = ((next_dnode >> 16) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-3] = ((next_dnode >>  8) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-4] = ((next_dnode      ) & 0xFF) as u8;
            }

            // read DNODE_SIZE - 4 bytes
            let mut buf = [0; DNODE_SIZE-4]; // last 32-bit word is for the next-ptr
            let _ = f.read_exact(&mut buf).ok().unwrap();

            // copy to the dnode
            let mut dnode_bytes = [0; DNODE_SIZE];
            for i in 0..(DNODE_SIZE-4) {
                dnode_bytes[i] = buf[i];
            }

            let dnode = self.get_dnode(next_dnode as u32);
            dnode.bytes = dnode_bytes;

            // update counter
            remaining -= (DNODE_SIZE-4) as u64;
        }

        // create the last dnode
        let last_dnode_idx = self.alloc_dnode() as u32;
        {
            let last_dnode = self.get_dnode(last_dnode_idx);
            let _ = f.read_exact(&mut last_dnode.bytes);
        }

        if size > DNODE_SIZE as u64 {
            let second_last = self.get_dnode(next_dnode as u32);
            second_last.bytes[DNODE_SIZE-1] = ((last_dnode_idx >> 24) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-2] = ((last_dnode_idx >> 16) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-3] = ((last_dnode_idx >>  8) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-4] = ((last_dnode_idx      ) & 0xFF) as u8;
        }

        // create the inode
        let inode = self.alloc_inode();

        let basename_str = Path::new(file)
            .canonicalize()
            .expect("Cannot canonicalize file path!")
            .file_name()
            .unwrap()
            .to_os_string();

        let basename = basename_str
            .to_str()
            .unwrap();

        inode.size = size as u32;
        for i in 0..min(12, basename.len()) {
            inode.name[i] = basename.char_at(i) as u8;
        }
        inode.data = first_dnode as u32;

        println!("Added file '{}' to image.", basename);
    }

    /// Write the bytes of this OFSImage to the given file.
    pub fn burn(&self, file: &str) {
        let outfile = File::create(file).expect(format!("Cannot write to file '{}'", file).as_str());
        let mut wbuf = BufWriter::new(outfile); // buffer writes

        // metadata sector
        let mut buf = [0; SECTOR_SIZE as usize];

        // magic bytes
        buf[0] = 'O' as u8;
        buf[1] = 'F' as u8;
        buf[2] = 'S' as u8;

        // inode count
        buf[7] = ((self.num_inodes >> 24) & 0xFF) as u8;
        buf[6] = ((self.num_inodes >> 16) & 0xFF) as u8;
        buf[5] = ((self.num_inodes >>  8) & 0xFF) as u8;
        buf[4] = ((self.num_inodes      ) & 0xFF) as u8;

        // dnode count
        buf[11] = ((self.num_dnodes >> 24) & 0xFF) as u8;
        buf[10]= ((self.num_dnodes >> 16) & 0xFF) as u8;
        buf[9] = ((self.num_dnodes >>  8) & 0xFF) as u8;
        buf[8] = ((self.num_dnodes      ) & 0xFF) as u8;

        let _ = wbuf.write_all(&buf);

        // inode bitmap
        let inode_bitmap_sectors = (self.num_inodes as f64 / SECTOR_SIZE as f64 / 8.0).ceil() as usize;
        for i in 0..inode_bitmap_sectors {
            buf = [0; SECTOR_SIZE as usize];

            // create this section of the bit map
            for j in 0..(SECTOR_SIZE * 8) as usize {
                if self.inodes.get(i*SECTOR_SIZE as usize *8 + j).unwrap().is_some() {
                    buf[j/8] |= (1 << (j % 8)) as u8;
                }
            }

            let _ = wbuf.write_all(&buf);
        }

        // dnode bitmap
        let dnode_bitmap_sectors = (self.num_dnodes as f64 / SECTOR_SIZE as f64 / 8.0).ceil() as usize;
        for i in 0..dnode_bitmap_sectors {
            buf = [0; SECTOR_SIZE as usize];

            // create this section of the bit map
            for j in 0..(SECTOR_SIZE * 8) as usize {
                if self.dnodes.get(i*SECTOR_SIZE as usize *8 + j).unwrap().is_some() {
                    buf[j/8] |= (1 << (j % 8)) as u8;
                }
            }

            let _ = wbuf.write_all(&buf);
        }

        // inodes
        let inodes_per_sector = SECTOR_SIZE as usize / INODE_SIZE;
        let mut inode_ct = 0;
        let mut inode_buf = [Inode::new(); SECTOR_SIZE as usize / INODE_SIZE];

        for inode_opt in self.inodes.iter() {
            inode_buf[inode_ct % inodes_per_sector] = match *inode_opt {
                Some(ref inode) => (*inode).clone(),
                None => Inode::new(),
            };

            inode_ct += 1;

            if inode_ct % (SECTOR_SIZE as usize / INODE_SIZE) == 0 {
                let _ = wbuf.write_all(unsafe { &mem::transmute::<_, [u8; SECTOR_SIZE as usize]>(inode_buf) });
            }
        }

        // dnodes
        let dnodes_per_sector = SECTOR_SIZE as usize / DNODE_SIZE;
        let mut dnode_ct = 0;
        let mut dnode_buf = [Dnode { bytes: [0; DNODE_SIZE] }; SECTOR_SIZE as usize / DNODE_SIZE];

        for dnode_opt in self.dnodes.iter() {
            dnode_buf[dnode_ct % dnodes_per_sector] = match *dnode_opt {
                Some(ref dnode) => {
                    (*dnode).clone()
                },
                None => Dnode { bytes: [0; DNODE_SIZE] },
            };

            dnode_ct += 1;

            if dnode_ct % dnodes_per_sector == 0 {
                let _ = wbuf.write_all(unsafe { &mem::transmute::<_, [u8; SECTOR_SIZE as usize]>(dnode_buf) });
            }
        }

        // flush the buffer
        let _ = wbuf.flush();

        println!("Burned image to file '{}'.", file);
    }
}
<commit_msg>Fix typos in mkfs.rs<commit_after>//! A simple module for creating an OFS disk image

use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;
use std::path::Path;
use std::process::exit;
use std::cmp::min;
use std::mem;

/// The size of a sector in bytes
pub const SECTOR_SIZE: u32 = 512; // bytes

const INODE_SIZE: usize = 128; // bytes
const DNODE_SIZE: usize = 512; // bytes

/// Represents an OFS disk image, which can be written to a file
pub struct OFSImage {
    /// The number of inodes in the fs
    num_inodes: u32,

    /// The number of dnodes in the fs
    num_dnodes: u32,

    /// A list of inodes
    inodes: Vec<Option<Inode>>,

    /// A list of dnodes
    dnodes: Vec<Option<Dnode>>,
}

#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct Inode {
    name: [u8; 12],         // file name (up to 12B)
    uid: u32,             // owner UID
    gid: u32,             // group GID
    user_perm: u8,          // user permissions
    group_perm: u8,         // group permissions
    all_perm: u8,           // everyone permissions
    flags:u8,               // various flags
    size: u32,            // file size in bytes TODO: for now this must a multiple of 4
    data: u32,            // index of Dnode with contents
    created: u32,       // date created
    modified: u32,      // date last modified
    links: [u32; 22],
}

impl Inode {
    fn new() -> Inode {
        Inode {
            name: [0; 12],
            uid: 0,
            gid: 0,
            user_perm: 0,
            group_perm: 0,
            all_perm: 0,
            flags: 0,
            size: 0,
            data: 0,
            created: 0,
            modified: 0,
            links: [0; 22],
        }
    }
}

#[derive(Copy)]
#[repr(C, packed)]
struct Dnode {
    bytes: [u8; DNODE_SIZE], // contents
}

impl Clone for Dnode {
    fn clone(&self) -> Dnode {
        let mut cloned = [0; DNODE_SIZE];
        for d in 0..cloned.len() {
            cloned[d] = self.bytes[d];
        }
        Dnode {
            bytes: cloned
        }
    }
}

impl OFSImage {
    /// Create a new OFSImage with the given numbers of inodes and dnodes.
    pub fn new(num_inodes: u32, num_dnodes: u32) -> OFSImage {
        let mut inodes = Vec::with_capacity(num_inodes as usize);
        let mut dnodes = Vec::with_capacity(num_dnodes as usize);

        for _ in 0..num_inodes {
            inodes.push(None)
        }

        for _ in 0..num_dnodes {
            dnodes.push(None)
        }

        OFSImage {
            num_inodes: num_inodes,
            num_dnodes: num_dnodes,
            inodes: inodes,
            dnodes: dnodes,
        }
    }

    /// Allocate an inode in the file system and return mutable reference to it.
    pub fn alloc_inode(&mut self) -> &mut Inode {
        let first_free = (0..self.num_inodes)
            .find(|i| self.inodes.get_mut(*i as usize).unwrap().is_none())
            .unwrap_or_else(|| panic!("No inodes left!")) as usize;

        *self.inodes.get_mut(first_free).unwrap() = Some(Inode::new());

        self.inodes.get_mut(first_free)
                   .unwrap()
                   .as_mut()
                   .unwrap()
    }

    /// Allocate a dnode in the file system and return its dnode index.
    pub fn alloc_dnode(&mut self) -> usize {
        let first_free = (0..self.num_dnodes)
            .find(|i| self.dnodes.get_mut(*i as usize).unwrap().is_none())
            .unwrap_or_else(|| panic!("No dnodes left!")) as usize;

        *self.dnodes.get_mut(first_free).unwrap() = Some(Dnode {
            bytes: [0; DNODE_SIZE],
        });

        first_free
    }

    /// Get the `i`th dnode.
    ///
    /// # Panics
    /// if the `i`th dnode is not allocated
    pub fn get_dnode(&mut self, i: u32) -> &mut Dnode {
        self.dnodes.get_mut(i as usize)
                   .unwrap()
                   .as_mut()
                   .unwrap_or_else(|| panic!("dnode {} is not allocated", i))
    }

    /// Copy the file (on the host machine) to the OFS image. No guarantees are made about
    /// the order of inodes or dnodes chosen.
    pub fn add_file(&mut self, file: &str) {
        // open the file and read it
        if !Path::new(file).is_file() {
            println!("Error! No such file or directory '{}'.", file);
            exit(1);
        }
        let mut f = File::open(file).ok().unwrap(); // TODO: check if exists

        // get the file size (bytes)
        let size = f.metadata().ok().unwrap().len();

        // create the dnodes
        let mut remaining = size;
        let mut first_dnode = 0;

        let mut next_dnode = first_dnode;
        while remaining > DNODE_SIZE as u64 {
            // allocate a dnode
            let prev_dnode = next_dnode;
            next_dnode = self.alloc_dnode();
            if remaining == size {
                // don't forget where the file begins ;)
                first_dnode = next_dnode;
            } else {
                // chain the dnodes
                let dnode = self.get_dnode(prev_dnode as u32);
                dnode.bytes[DNODE_SIZE-1] = ((next_dnode >> 24) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-2] = ((next_dnode >> 16) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-3] = ((next_dnode >>  8) & 0xFF) as u8;
                dnode.bytes[DNODE_SIZE-4] = ((next_dnode      ) & 0xFF) as u8;
            }

            // read DNODE_SIZE - 4 bytes
            let mut buf = [0; DNODE_SIZE-4]; // last 32-bit word is for the next-ptr
            let _ = f.read_exact(&mut buf).ok().unwrap();

            // copy to the dnode
            let mut dnode_bytes = [0; DNODE_SIZE];
            for i in 0..(DNODE_SIZE-4) {
                dnode_bytes[i] = buf[i];
            }

            let dnode = self.get_dnode(next_dnode as u32);
            dnode.bytes = dnode_bytes;

            // update counter
            remaining -= (DNODE_SIZE-4) as u64;
        }

        // create the last dnode
        let last_dnode_idx = self.alloc_dnode() as u32;
        {
            let last_dnode = self.get_dnode(last_dnode_idx);
            let _ = f.read_exact(&mut last_dnode.bytes);
        }

        if size > DNODE_SIZE as u64 {
            let second_last = self.get_dnode(next_dnode as u32);
            second_last.bytes[DNODE_SIZE-1] = ((last_dnode_idx >> 24) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-2] = ((last_dnode_idx >> 16) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-3] = ((last_dnode_idx >>  8) & 0xFF) as u8;
            second_last.bytes[DNODE_SIZE-4] = ((last_dnode_idx      ) & 0xFF) as u8;
        }

        // create the inode
        let inode = self.alloc_inode();

        let basename_str = Path::new(file)
            .canonicalize()
            .expect("Cannot canonicalize file path!")
            .file_name()
            .unwrap()
            .to_os_string();

        let basename = basename_str
            .to_str()
            .unwrap();

        inode.size = size as u32;
        for i in 0..min(12, basename.len()) {
            inode.name[i] = basename.char_at(i) as u8;
        }
        inode.data = first_dnode as u32;

        println!("Added file '{}' to image.", basename);
    }

    /// Write the bytes of this OFSImage to the given file.
    pub fn burn(&self, file: &str) {
        let outfile = File::create(file).expect(format!("Cannot write to file '{}'", file).as_str());
        let mut wbuf = BufWriter::new(outfile); // buffer writes

        // metadata sector
        let mut buf = [0; SECTOR_SIZE as usize];

        // magic bytes
        buf[0] = 'O' as u8;
        buf[1] = 'F' as u8;
        buf[2] = 'S' as u8;

        // inode count
        buf[7] = ((self.num_inodes >> 24) & 0xFF) as u8;
        buf[6] = ((self.num_inodes >> 16) & 0xFF) as u8;
        buf[5] = ((self.num_inodes >>  8) & 0xFF) as u8;
        buf[4] = ((self.num_inodes      ) & 0xFF) as u8;

        // dnode count
        buf[11] = ((self.num_dnodes >> 24) & 0xFF) as u8;
        buf[10]= ((self.num_dnodes >> 16) & 0xFF) as u8;
        buf[9] = ((self.num_dnodes >>  8) & 0xFF) as u8;
        buf[8] = ((self.num_dnodes      ) & 0xFF) as u8;

        let _ = wbuf.write_all(&buf);

        // inode bitmap
        let inode_bitmap_sectors = (self.num_inodes as f64 / SECTOR_SIZE as f64 / 8.0).ceil() as usize;
        for i in 0..inode_bitmap_sectors {
            buf = [0; SECTOR_SIZE as usize];

            // create this section of the bit map
            for j in 0..(SECTOR_SIZE * 8) as usize {
                if self.inodes.get(i*SECTOR_SIZE as usize *8 + j).unwrap().is_some() {
                    buf[j/8] |= (1 << (j % 8)) as u8;
                }
            }

            let _ = wbuf.write_all(&buf);
        }

        // dnode bitmap
        let dnode_bitmap_sectors = (self.num_dnodes as f64 / SECTOR_SIZE as f64 / 8.0).ceil() as usize;
        for i in 0..dnode_bitmap_sectors {
            buf = [0; SECTOR_SIZE as usize];

            // create this section of the bit map
            for j in 0..(SECTOR_SIZE * 8) as usize {
                if self.dnodes.get(i*SECTOR_SIZE as usize *8 + j).unwrap().is_some() {
                    buf[j/8] |= (1 << (j % 8)) as u8;
                }
            }

            let _ = wbuf.write_all(&buf);
        }

        // inodes
        let inodes_per_sector = SECTOR_SIZE as usize / INODE_SIZE;
        let mut inode_ct = 0;
        let mut inode_buf = [Inode::new(); SECTOR_SIZE as usize / INODE_SIZE];

        for inode_opt in self.inodes.iter() {
            inode_buf[inode_ct % inodes_per_sector] = match *inode_opt {
                Some(ref inode) => (*inode).clone(),
                None => Inode::new(),
            };

            inode_ct += 1;

            if inode_ct % (SECTOR_SIZE as usize / INODE_SIZE) == 0 {
                let _ = wbuf.write_all(unsafe { &mem::transmute::<_, [u8; SECTOR_SIZE as usize]>(inode_buf) });
            }
        }

        // dnodes
        let dnodes_per_sector = SECTOR_SIZE as usize / DNODE_SIZE;
        let mut dnode_ct = 0;
        let mut dnode_buf = [Dnode { bytes: [0; DNODE_SIZE] }; SECTOR_SIZE as usize / DNODE_SIZE];

        for dnode_opt in self.dnodes.iter() {
            dnode_buf[dnode_ct % dnodes_per_sector] = match *dnode_opt {
                Some(ref dnode) => {
                    (*dnode).clone()
                },
                None => Dnode { bytes: [0; DNODE_SIZE] },
            };

            dnode_ct += 1;

            if dnode_ct % dnodes_per_sector == 0 {
                let _ = wbuf.write_all(unsafe { &mem::transmute::<_, [u8; SECTOR_SIZE as usize]>(dnode_buf) });
            }
        }

        // flush the buffer
        let _ = wbuf.flush();

        println!("Burned image to file '{}'.", file);
    }
}
<|endoftext|>