<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 CoreOS, Inc.
//
// 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.

use std::cmp;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

impl Default for ProgressState {
    fn default() -> ProgressState {
        ProgressState::Probe
    }
}

#[derive(Debug, Default, Clone)]
pub struct Progress {
    pub matched: u64,
    pub next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    pub state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    pub paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pub pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    pub recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    pub ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.recent_active = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    pub fn snapshot_failure(&mut self) {
        self.pending_snapshot = 0;
    }

    // maybe_snapshot_abort unsets pendingSnapshot if Match is equal or higher than
    // the pendingSnapshot
    pub fn maybe_snapshot_abort(&self) -> bool {
        self.state == ProgressState::Snapshot && self.matched >= self.pending_snapshot
    }

    // maybe_update returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let need_update = self.matched < n;
        if need_update {
            self.matched = n;
            self.resume();
        };

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        need_update
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybe_decr_to returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_decr_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx == 0 || self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default, Clone)]
pub struct Inflights {
    // the starting index in the buffer
    start: usize,
    // number of inflights in the buffer
    count: usize,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    // full returns true if the inflights is full.
    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> usize {
        self.buffer.capacity()
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        assert!(next <= self.buffer.len());
        if next == self.buffer.len() {
            self.buffer.push(inflight);
        } else {
            self.buffer[next] = inflight;
        }
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start] {
            // out of the left side of the window
            return;
        }

        let mut i = 0usize;
        let mut idx = self.start;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() {
                idx -= self.cap();
            }

            i += 1;
        }

        // free i inflights and set new start index
        self.count -= i;
        self.start = idx;
    }

    pub fn free_first_one(&mut self) {
        let start = self.buffer[self.start];
        self.free_to(start);
    }

    // resets frees all inflights.
    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<commit_msg>raft: do not change RecentActive when resetState for progress. (#831)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 CoreOS, Inc.
//
// 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.

use std::cmp;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

impl Default for ProgressState {
    fn default() -> ProgressState {
        ProgressState::Probe
    }
}

#[derive(Debug, Default, Clone)]
pub struct Progress {
    pub matched: u64,
    pub next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    pub state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    pub paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pub pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    pub recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    pub ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    pub fn snapshot_failure(&mut self) {
        self.pending_snapshot = 0;
    }

    // maybe_snapshot_abort unsets pendingSnapshot if Match is equal or higher than
    // the pendingSnapshot
    pub fn maybe_snapshot_abort(&self) -> bool {
        self.state == ProgressState::Snapshot && self.matched >= self.pending_snapshot
    }

    // maybe_update returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let need_update = self.matched < n;
        if need_update {
            self.matched = n;
            self.resume();
        };

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        need_update
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybe_decr_to returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_decr_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx == 0 || self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default, Clone)]
pub struct Inflights {
    // the starting index in the buffer
    start: usize,
    // number of inflights in the buffer
    count: usize,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    // full returns true if the inflights is full.
    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> usize {
        self.buffer.capacity()
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        assert!(next <= self.buffer.len());
        if next == self.buffer.len() {
            self.buffer.push(inflight);
        } else {
            self.buffer[next] = inflight;
        }
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start] {
            // out of the left side of the window
            return;
        }

        let mut i = 0usize;
        let mut idx = self.start;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() {
                idx -= self.cap();
            }

            i += 1;
        }

        // free i inflights and set new start index
        self.count -= i;
        self.start = idx;
    }

    pub fn free_first_one(&mut self) {
        let start = self.buffer[self.start];
        self.free_to(start);
    }

    // resets frees all inflights.
    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<|endoftext|>


<commit_before>use common::volatile_cell::VolatileCell;

pub struct Pin {
    pub select: VolatileCell<Function>,
    pub control: VolatileCell<u32>,
}

pub struct Registers {
    pub diom0: Pin,
    pub diom1: Pin,
    pub diom2: Pin,
    pub diom3: Pin,
    pub diom4: Pin,

    pub dioa0: Pin,
    pub dioa1: Pin,
    pub dioa2: Pin,
    pub dioa3: Pin,
    pub dioa4: Pin,
    pub dioa5: Pin,
    pub dioa6: Pin,
    pub dioa7: Pin,
    pub dioa8: Pin,
    pub dioa9: Pin,
    pub dioa10: Pin,
    pub dioa11: Pin,
    pub dioa12: Pin,
    pub dioa13: Pin,
    pub dioa14: Pin,

    pub diob0: Pin,
    pub diob1: Pin,
    pub diob2: Pin,
    pub diob3: Pin,
    pub diob4: Pin,
    pub diob5: Pin,
    pub diob6: Pin,
    pub diob7: Pin,
}

pub const PINMUX: *mut Registers = 0x40060000 as *mut Registers;

#[repr(u32)]
pub enum Function {
    Default = 0,
    Gpio0Gpio0 = 1,
    Gpio0Gpio1 = 2,
    Gpio0Gpio2 = 3,
    Gpio0Gpio3 = 4,
    Gpio0Gpio4 = 5,
    Gpio0Gpio5 = 6,
    Gpio0Gpio6 = 7,
    Gpio0Gpio7 = 8,
    Gpio0Gpio8 = 9,
    Gpio0Gpio9 = 10,
    Gpio0Gpio10 = 11,
    Gpio0Gpio11 = 12,
    Gpio0Gpio12 = 13,
    Gpio0Gpio13 = 14,
    Gpio0Gpio14 = 15,
    Gpio0Gpio15 = 16,
    Gpio1Gpio0 = 17,
    Gpio1Gpio1 = 18,
    Gpio1Gpio2 = 19,
    Gpio1Gpio3 = 20,
    Gpio1Gpio4 = 21,
    Gpio1Gpio5 = 22,
    Gpio1Gpio6 = 23,
    Gpio1Gpio7 = 24,
    Gpio1Gpio8 = 25,
    Gpio1Gpio9 = 26,
    Gpio1Gpio10 = 27,
    Gpio1Gpio11 = 28,
    Gpio1Gpio12 = 29,
    Gpio1Gpio13 = 30,
    Gpio1Gpio14 = 31,
    Gpio1Gpio15 = 32,
    I2C0Scl = 33,
    I2C0Sda = 34,
    I2C1Scl = 35,
    I2C1SDA = 36,
    I2cs0Scl = 37,
    I2cs0Sda = 38,
    PmuBrownoutDet = 39,
    PmuTestbus0 = 40,
    PmuTestbus1 = 41,
    PmuTestbus2 = 42,
    PmuTestbus3 = 43,
    PmuTestbus4 = 44,
    PmuTestbus5 = 45,
    PmuTestbus6 = 46,
    PmuTestbus7 = 47,
    Rtc0RtcClkTest = 48,
    Spi1Spiclk = 49,
    Spi1Spicsb = 50,
    Spi1Spimiso = 51,
    Spi1Spimosi = 52,
    Sps0Testbus0 = 53,
    Sps0Testbus1 = 54,
    Sps0Testbus2 = 55,
    Sps0Testbus3 = 56,
    Sps0Testbus4 = 57,
    Sps0Testbus5 = 58,
    Sps0Testbus6 = 59,
    Sps0Testbus7 = 60,
    Temp0TstAdcClk = 61,
    Temp0TstAdcHiSer = 62,
    Temp0TstAdcLoSer = 63,
    Temp0TstAdcVldSer = 64,
    Trng0TrngRoDiv = 65,
    Trng0TrngRoRefDiv = 66,
    Uart0Cts = 67,
    Uart0Rts = 68,
    Uart0Rx = 69,
    Uart0Tx = 70,
    Uart1Cts = 71,
    Uart1Rts = 72,
    Uart1Rx = 73,
    Uart1Tx = 74,
    Uart2Cts = 75,
    Uart2Rts = 76,
    Uart2Rx = 77,
    Uart2Tx = 78,
    Usb0ExtDmPullupEn = 79,
    Usb0ExtDpRpu1Enb = 80,
    Usb0ExtDpRpu2Enb = 81,
    Usb0ExtFsEdgeSel = 82,
    Usb0ExtRxDmi = 83,
    Usb0ExtRxDpi = 84,
    Usb0ExtRxRcv = 85,
    Usb0ExtSuspendb = 86,
    Usb0ExtTxDmo = 87,
    Usb0ExtTxDpo = 88,
    Usb0ExtTxOeb = 89,
    Volt0TstNegGlitchDet = 90,
    Volt0TstPosGlitchDet = 91,
    Xo0Testbus0 = 92,
    Xo0Testbus1 = 93,
    Xo0Testbus2 = 94,
    Xo0Testbus3 = 95,
    Xo0Testbus4 = 96,
    Xo0Testbus5 = 97,
    Xo0testbus6 = 98,
    Xo0Testbus7 = 99,
}
<commit_msg>Add other direction for Hotel pinmux<commit_after>use common::volatile_cell::VolatileCell;

pub struct Pin {
    pub select: VolatileCell<Function>,
    pub control: VolatileCell<u32>,
}

pub struct Peripheral {
    pub select: VolatileCell<SelectablePin>
}

pub struct Registers {
    pub diom0: Pin,
    pub diom1: Pin,
    pub diom2: Pin,
    pub diom3: Pin,
    pub diom4: Pin,

    pub dioa0: Pin,
    pub dioa1: Pin,
    pub dioa2: Pin,
    pub dioa3: Pin,
    pub dioa4: Pin,
    pub dioa5: Pin,
    pub dioa6: Pin,
    pub dioa7: Pin,
    pub dioa8: Pin,
    pub dioa9: Pin,
    pub dioa10: Pin,
    pub dioa11: Pin,
    pub dioa12: Pin,
    pub dioa13: Pin,
    pub dioa14: Pin,

    pub diob0: Pin,
    pub diob1: Pin,
    pub diob2: Pin,
    pub diob3: Pin,
    pub diob4: Pin,
    pub diob5: Pin,
    pub diob6: Pin,
    pub diob7: Pin,

    pub resetb: Pin,
    pub vio0: Pin,
    pub vio1: Pin,

    pub gpio0_gpio0: Peripheral,
    pub gpio0_gpio1: Peripheral,
    pub gpio0_gpio2: Peripheral,
    pub gpio0_gpio3: Peripheral,
    pub gpio0_gpio4: Peripheral,
    pub gpio0_gpio5: Peripheral,
    pub gpio0_gpio6: Peripheral,
    pub gpio0_gpio7: Peripheral,
    pub gpio0_gpio8: Peripheral,
    pub gpio0_gpio9: Peripheral,
    pub gpio0_gpio10: Peripheral,
    pub gpio0_gpio11: Peripheral,
    pub gpio0_gpio12: Peripheral,
    pub gpio0_gpio13: Peripheral,
    pub gpio0_gpio14: Peripheral,
    pub gpio0_gpio15: Peripheral,

    pub gpio1_gpio0: Peripheral,
    pub gpio1_gpio1: Peripheral,
    pub gpio1_gpio2: Peripheral,
    pub gpio1_gpio3: Peripheral,
    pub gpio1_gpio4: Peripheral,
    pub gpio1_gpio5: Peripheral,
    pub gpio1_gpio6: Peripheral,
    pub gpio1_gpio7: Peripheral,
    pub gpio1_gpio8: Peripheral,
    pub gpio1_gpio9: Peripheral,
    pub gpio1_gpio10: Peripheral,
    pub gpio1_gpio11: Peripheral,
    pub gpio1_gpio12: Peripheral,
    pub gpio1_gpio13: Peripheral,
    pub gpio1_gpio14: Peripheral,
    pub gpio1_gpio15: Peripheral,

    pub i2c0_scl: Peripheral,
    pub i2c0_sda: Peripheral,
    pub i2c1_scl: Peripheral,
    pub i2c1_sda: Peripheral,
    pub i2cs0_scl: Peripheral,
    pub i2cs0_sda: Peripheral,
    pub pmu_brownout_det: Peripheral,
    pub pmu_testbus0: Peripheral,
    pub pmu_testbus1: Peripheral,
    pub pmu_testbus2: Peripheral,
    pub pmu_testbus3: Peripheral,
    pub pmu_testbus4: Peripheral,
    pub pmu_testbus5: Peripheral,
    pub pmu_testbus6: Peripheral,
    pub pmu_testbus7: Peripheral,
    pub rtc0_rtc_clk_test: Peripheral,
    pub spi1_spiclk: Peripheral,
    pub spi1_spicsb: Peripheral,
    pub spi1_spimiso: Peripheral,
    pub spi1_spimosi: Peripheral,
    pub sps0_testbus0: Peripheral,
    pub sps0_testbus1: Peripheral,
    pub sps0_testbus2: Peripheral,
    pub sps0_testbus3: Peripheral,
    pub sps0_testbus4: Peripheral,
    pub sps0_testbus5: Peripheral,
    pub sps0_testbus6: Peripheral,
    pub sps0_testbus7: Peripheral,
    pub temp0_tst_adc_clk: Peripheral,
    pub temp0_tst_adc_hi_ser: Peripheral,
    pub temp0_tst_adc_lo_ser: Peripheral,
    pub temp0_tst_adc_vld_ser: Peripheral,
    pub trng0_trng_ro_div: Peripheral,
    pub trng0_trng_ro_ref_div: Peripheral,
    pub uart0_cts: Peripheral,
    pub uart0_rts: Peripheral,
    pub uart0_rx: Peripheral,
    pub uart0_tx: Peripheral,
    pub uart1_cts: Peripheral,
    pub uart1_rts: Peripheral,
    pub uart1_rx: Peripheral,
    pub uart1_tx: Peripheral,
    pub uart2_cts: Peripheral,
    pub uart2_rts: Peripheral,
    pub uart2_rx: Peripheral,
    pub uart2_tx: Peripheral,
    pub usb0_ext_dm_pullup_en: Peripheral,
    pub usb0_ext_dp_rpu1_enb: Peripheral,
    pub usb0_ext_dp_rpu2_enb: Peripheral,
    pub usb0_ext_fs_edge_sel: Peripheral,
    pub usb0_ext_rx_dmi: Peripheral,
    pub usb0_ext_rx_dpi: Peripheral,
    pub usb0_ext_rx_rcv: Peripheral,
    pub usb0_ext_suspendb: Peripheral,
    pub usb0_ext_tx_dmo: Peripheral,
    pub usb0_ext_tx_dpo: Peripheral,
    pub usb0_ext_tx_oeb: Peripheral,
    pub volt0_tst_neg_glitch_det: Peripheral,
    pub volt0_tst_pos_glitch_det: Peripheral,
    pub xo0_testbus0: Peripheral,
    pub xo0_testbus1: Peripheral,
    pub xo0_testbus2: Peripheral,
    pub xo0_testbus3: Peripheral,
    pub xo0_testbus4: Peripheral,
    pub xo0_testbus5: Peripheral,
    pub xo0_testbus6: Peripheral,
    pub xo0_testbus7: Peripheral,
}

pub const PINMUX: *mut Registers = 0x40060000 as *mut Registers;

#[repr(u32)]
pub enum SelectablePin {
    Vio1 = 1,
    Vio0 = 2,
    Diob7 = 3,
    Diob6 = 4,
    Diob5 = 5,
    Diob4 = 6,
    Diob3 = 7,
    Diob2 = 8,
    Diob1 = 9,
    Diob0 = 10,
    Dioa14 = 11,
    Dioa13 = 12,
    Dioa12 = 13,
    Dioa11 = 14,
    Dioa10 = 15,
    Dioa9 = 16,
    Dioa8 = 17,
    Dioa7 = 18,
    Dioa6 = 19,
    Dioa5 = 20,
    Dioa4 = 21,
    Dioa3 = 22,
    Dioa2 = 23,
    Dioa1 = 24,
    Dioa0 = 25,
    Diom4 = 26,
    Diom3 = 27,
    Diom2 = 28,
    Diom1 = 29,
    Diom0 = 30,
}

#[repr(u32)]
pub enum Function {
    Default = 0,
    Gpio0Gpio0 = 1,
    Gpio0Gpio1 = 2,
    Gpio0Gpio2 = 3,
    Gpio0Gpio3 = 4,
    Gpio0Gpio4 = 5,
    Gpio0Gpio5 = 6,
    Gpio0Gpio6 = 7,
    Gpio0Gpio7 = 8,
    Gpio0Gpio8 = 9,
    Gpio0Gpio9 = 10,
    Gpio0Gpio10 = 11,
    Gpio0Gpio11 = 12,
    Gpio0Gpio12 = 13,
    Gpio0Gpio13 = 14,
    Gpio0Gpio14 = 15,
    Gpio0Gpio15 = 16,
    Gpio1Gpio0 = 17,
    Gpio1Gpio1 = 18,
    Gpio1Gpio2 = 19,
    Gpio1Gpio3 = 20,
    Gpio1Gpio4 = 21,
    Gpio1Gpio5 = 22,
    Gpio1Gpio6 = 23,
    Gpio1Gpio7 = 24,
    Gpio1Gpio8 = 25,
    Gpio1Gpio9 = 26,
    Gpio1Gpio10 = 27,
    Gpio1Gpio11 = 28,
    Gpio1Gpio12 = 29,
    Gpio1Gpio13 = 30,
    Gpio1Gpio14 = 31,
    Gpio1Gpio15 = 32,
    I2C0Scl = 33,
    I2C0Sda = 34,
    I2C1Scl = 35,
    I2C1SDA = 36,
    I2cs0Scl = 37,
    I2cs0Sda = 38,
    PmuBrownoutDet = 39,
    PmuTestbus0 = 40,
    PmuTestbus1 = 41,
    PmuTestbus2 = 42,
    PmuTestbus3 = 43,
    PmuTestbus4 = 44,
    PmuTestbus5 = 45,
    PmuTestbus6 = 46,
    PmuTestbus7 = 47,
    Rtc0RtcClkTest = 48,
    Spi1Spiclk = 49,
    Spi1Spicsb = 50,
    Spi1Spimiso = 51,
    Spi1Spimosi = 52,
    Sps0Testbus0 = 53,
    Sps0Testbus1 = 54,
    Sps0Testbus2 = 55,
    Sps0Testbus3 = 56,
    Sps0Testbus4 = 57,
    Sps0Testbus5 = 58,
    Sps0Testbus6 = 59,
    Sps0Testbus7 = 60,
    Temp0TstAdcClk = 61,
    Temp0TstAdcHiSer = 62,
    Temp0TstAdcLoSer = 63,
    Temp0TstAdcVldSer = 64,
    Trng0TrngRoDiv = 65,
    Trng0TrngRoRefDiv = 66,
    Uart0Cts = 67,
    Uart0Rts = 68,
    Uart0Rx = 69,
    Uart0Tx = 70,
    Uart1Cts = 71,
    Uart1Rts = 72,
    Uart1Rx = 73,
    Uart1Tx = 74,
    Uart2Cts = 75,
    Uart2Rts = 76,
    Uart2Rx = 77,
    Uart2Tx = 78,
    Usb0ExtDmPullupEn = 79,
    Usb0ExtDpRpu1Enb = 80,
    Usb0ExtDpRpu2Enb = 81,
    Usb0ExtFsEdgeSel = 82,
    Usb0ExtRxDmi = 83,
    Usb0ExtRxDpi = 84,
    Usb0ExtRxRcv = 85,
    Usb0ExtSuspendb = 86,
    Usb0ExtTxDmo = 87,
    Usb0ExtTxDpo = 88,
    Usb0ExtTxOeb = 89,
    Volt0TstNegGlitchDet = 90,
    Volt0TstPosGlitchDet = 91,
    Xo0Testbus0 = 92,
    Xo0Testbus1 = 93,
    Xo0Testbus2 = 94,
    Xo0Testbus3 = 95,
    Xo0Testbus4 = 96,
    Xo0Testbus5 = 97,
    Xo0testbus6 = 98,
    Xo0Testbus7 = 99,
}
<|endoftext|>


<commit_before>use std::any::Any;
use hyper::net::Fresh;
use hyper::server::Response as UnwrappedResponse;

pub struct Response<'a, T: Any = Fresh> {
    res: UnwrappedResponse<'a, T>
}

impl<'a> Response<'a, Fresh> {
    pub fn wrap_response<'b>(res: UnwrappedResponse<'b, Fresh>) -> Response<'b, Fresh> {
        Response { res: res }
    }

    pub fn send(self, body: &[u8]) {
        self.res.send(body).unwrap();
    }
}
<commit_msg>response methods<commit_after>use std::io::{self, Write};
use std::any::Any;
use hyper::net::{Fresh, Streaming};
use hyper::server::Response as UnwrappedResponse;
use hyper::header::Headers;
use hyper::status::StatusCode;

pub struct Response<'a, T: Any = Fresh> {
    res: UnwrappedResponse<'a, T>
}

impl<'a> Response<'a, Fresh> {
    pub fn wrap_response<'b>(res: UnwrappedResponse<'b, Fresh>) -> Response<'b, Fresh> {
        Response { res: res }
    }

    #[inline]
    pub fn status_mut(&mut self) -> &mut StatusCode {
        self.res.status_mut()
    }

    #[inline]
    pub fn headers_mut(&mut self) -> &mut Headers {
        self.res.headers_mut()
    }

    #[inline]
    pub fn send(self, body: &[u8]) -> io::Result<()> {
        self.res.send(body)
    }

    #[inline]
    pub fn start(self) -> io::Result<Response<'a, Streaming>> {
        match self.res.start() {
            Ok(res) => Ok(Response { res: res }),
            Err(e) => Err(e)
        }
    }
}

impl<'a> Response<'a, Streaming> {
    #[inline]
    pub fn end(self) -> io::Result<()> {
        self.res.end()
    }
}

impl<'a> Write for Response<'a, Streaming> {
    #[inline]
    fn write(&mut self, msg: &[u8]) -> io::Result<usize> {
        self.res.write(msg)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.res.flush()
    }
}
<|endoftext|>


<commit_before>use std::io::{IoResult, File};
use std::io::util::copy;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```rust
    /// response.send("hello world");
    /// ```
    pub fn send (&mut self, text: &str) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.as_bytes());
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = Some(response_writer.headers.content_type
                                                        .clone()
                                                        .unwrap_or(get_media_type("txt").unwrap()));
        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<commit_msg>refactor(response): cleanup syntax<commit_after>use std::io::{IoResult, File};
use std::io::util::copy;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```rust
    /// response.send("hello world");
    /// ```
    pub fn send (&mut self, text: &str) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.as_bytes());
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = response_writer.headers.content_type
                                                                      .clone()
                                                                      .or(get_media_type("txt"));

        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<|endoftext|>


<commit_before>use rustc_serialize::json::{Json, ToJson};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendTextRequest {
    openid: String,
    account: Option<String>,
    content: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendImageRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendVoiceRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendVideoRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
    thumb_media_id: String,
    title: Option<String>,
    description: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendMusicRequest {
    openid: String,
    account: Option<String>,
    music_url: String,
    hq_music_url: String,
    thumb_media_id: String,
    title: Option<String>,
    description: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Article {
    title: String,
    url: String,
    description: Option<String>,
    image: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendArticlesRequest {
    openid: String,
    account: Option<String>,
    articles: Vec<Article>,
}

impl SendTextRequest {
    pub fn new(openid: &str, content: &str) -> SendTextRequest {
        SendTextRequest {
            openid: openid.to_owned(),
            content: content.to_owned(),
            account: None,
        }
    }

    pub fn with_account(openid: &str, content: &str, account: &str) -> SendTextRequest {
        SendTextRequest {
            openid: openid.to_owned(),
            content: content.to_owned(),
            account: Some(account.to_owned()),
        }
    }
}

impl ToJson for SendTextRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "text",
                "touser": (self.openid),
                "text": {"content": (self.content)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "text",
                "touser": (self.openid),
                "text": {"content": (self.content)},
            })
        }
    }
}

make_encodable!(SendTextRequest);

impl SendImageRequest {
    pub fn new(openid: &str, media_id: &str) -> SendImageRequest {
        SendImageRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
        }
    }

    pub fn with_account(openid: &str, media_id: &str, account: &str) -> SendImageRequest {
        SendImageRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
        }
    }
}
impl ToJson for SendImageRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "image",
                "touser": (self.openid),
                "image": {"media_id": (self.media_id)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "image",
                "touser": (self.openid),
                "image": {"media_id": (self.media_id)},
            })
        }
    }
}

make_encodable!(SendImageRequest);

impl SendVoiceRequest {
    pub fn new(openid: &str, media_id: &str) -> SendVoiceRequest {
        SendVoiceRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
        }
    }

    pub fn with_account(openid: &str, media_id: &str, account: &str) -> SendVoiceRequest {
        SendVoiceRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
        }
    }
}

impl ToJson for SendVoiceRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "voice",
                "touser": (self.openid),
                "voice": {"media_id": (self.media_id)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "voice",
                "touser": (self.openid),
                "voice": {"media_id": (self.media_id)},
            })
        }
    }
}

make_encodable!(SendVoiceRequest);

impl SendVideoRequest {
    pub fn new(openid: &str, media_id: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendVideoRequest {
        SendVideoRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }

    pub fn with_account(openid: &str, account: &str, media_id: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendVideoRequest {
        SendVideoRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }
}

impl ToJson for SendVideoRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "video",
                "touser": (self.openid),
                "video": {
                    "media_id": (self.media_id),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "video",
                "touser": (self.openid),
                "video": {
                    "media_id": (self.media_id),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
            })
        }
    }
}

make_encodable!(SendVideoRequest);
<commit_msg>Impl SendVideoRequest<commit_after>use rustc_serialize::json::{Json, ToJson};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendTextRequest {
    openid: String,
    account: Option<String>,
    content: String,
}

impl SendTextRequest {
    pub fn new(openid: &str, content: &str) -> SendTextRequest {
        SendTextRequest {
            openid: openid.to_owned(),
            content: content.to_owned(),
            account: None,
        }
    }

    pub fn with_account(openid: &str, content: &str, account: &str) -> SendTextRequest {
        SendTextRequest {
            openid: openid.to_owned(),
            content: content.to_owned(),
            account: Some(account.to_owned()),
        }
    }
}

impl ToJson for SendTextRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "text",
                "touser": (self.openid),
                "text": {"content": (self.content)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "text",
                "touser": (self.openid),
                "text": {"content": (self.content)},
            })
        }
    }
}

make_encodable!(SendTextRequest);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendImageRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
}

impl SendImageRequest {
    pub fn new(openid: &str, media_id: &str) -> SendImageRequest {
        SendImageRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
        }
    }

    pub fn with_account(openid: &str, media_id: &str, account: &str) -> SendImageRequest {
        SendImageRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
        }
    }
}
impl ToJson for SendImageRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "image",
                "touser": (self.openid),
                "image": {"media_id": (self.media_id)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "image",
                "touser": (self.openid),
                "image": {"media_id": (self.media_id)},
            })
        }
    }
}

make_encodable!(SendImageRequest);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendVoiceRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
}

impl SendVoiceRequest {
    pub fn new(openid: &str, media_id: &str) -> SendVoiceRequest {
        SendVoiceRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
        }
    }

    pub fn with_account(openid: &str, media_id: &str, account: &str) -> SendVoiceRequest {
        SendVoiceRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
        }
    }
}

impl ToJson for SendVoiceRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "voice",
                "touser": (self.openid),
                "voice": {"media_id": (self.media_id)},
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "voice",
                "touser": (self.openid),
                "voice": {"media_id": (self.media_id)},
            })
        }
    }
}

make_encodable!(SendVoiceRequest);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendVideoRequest {
    openid: String,
    account: Option<String>,
    media_id: String,
    thumb_media_id: String,
    title: Option<String>,
    description: Option<String>,
}

impl SendVideoRequest {
    pub fn new(openid: &str, media_id: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendVideoRequest {
        SendVideoRequest {
            openid: openid.to_owned(),
            account: None,
            media_id: media_id.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }

    pub fn with_account(openid: &str, account: &str, media_id: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendVideoRequest {
        SendVideoRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            media_id: media_id.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }
}

impl ToJson for SendVideoRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "video",
                "touser": (self.openid),
                "video": {
                    "media_id": (self.media_id),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "video",
                "touser": (self.openid),
                "video": {
                    "media_id": (self.media_id),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
            })
        }
    }
}

make_encodable!(SendVideoRequest);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendMusicRequest {
    openid: String,
    account: Option<String>,
    music_url: String,
    hq_music_url: String,
    thumb_media_id: String,
    title: Option<String>,
    description: Option<String>,
}

impl SendMusicRequest {
    pub fn new(openid: &str, music_url: &str, hq_music_url: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendMusicRequest {
        SendMusicRequest {
            openid: openid.to_owned(),
            account: None,
            music_url: music_url.to_owned(),
            hq_music_url: hq_music_url.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }

    pub fn with_account(openid: &str, account: &str, music_url: &str, hq_music_url: &str, thumb_media_id: &str, title: Option<String>, description: Option<String>) -> SendMusicRequest {
        SendMusicRequest {
            openid: openid.to_owned(),
            account: Some(account.to_owned()),
            music_url: music_url.to_owned(),
            hq_music_url: hq_music_url.to_owned(),
            thumb_media_id: thumb_media_id.to_owned(),
            title: title,
            description: description,
        }
    }
}

impl ToJson for SendMusicRequest {
    fn to_json(&self) -> Json {
        if let Some(ref account) = self.account {
            json!({
                "msgtype": "music",
                "touser": (self.openid),
                "music": {
                    "musicurl": (self.music_url),
                    "hqmusicurl": (self.hq_music_url),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
                "customservice": {"kf_account": (account)},
            })
        } else {
            json!({
                "msgtype": "music",
                "touser": (self.openid),
                "music": {
                    "musicurl": (self.music_url),
                    "hqmusicurl": (self.hq_music_url),
                    "thumb_media_id": (self.thumb_media_id),
                    "title": (self.title),
                    "description": (self.description),
                },
            })
        }
    }
}

make_encodable!(SendMusicRequest);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Article {
    title: String,
    url: String,
    description: Option<String>,
    image: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SendArticlesRequest {
    openid: String,
    account: Option<String>,
    articles: Vec<Article>,
}
<|endoftext|>


<commit_before>use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
use std::sync::mpsc::{Sender, Receiver};
use core::marker::PhantomData;

use communication::Observer;

pub trait Pushable<T> { fn push(&mut self, data: T); }        // like observer
pub trait Pullable<T> { fn pull(&mut self) -> Option<T>; }    // like iterator

impl<T:'static> Pushable<T> for Rc<RefCell<Vec<T>>> { fn push(&mut self, data: T) { self.borrow_mut().push(data); } }
impl<T:'static> Pullable<T> for Rc<RefCell<Vec<T>>> { fn pull(&mut self) -> Option<T> { self.borrow_mut().pop() } }

impl<T:Send+'static> Pushable<T> for Sender<T> { fn push(&mut self, data: T) { self.send(data).ok().expect("send error"); } }
impl<T:Send+'static> Pullable<T> for Receiver<T> { fn pull(&mut self) -> Option<T> { self.try_recv().ok() }}

impl<T:Send> Pushable<T> for Box<Pushable<T>> { fn push(&mut self, data: T) { (**self).push(data); } }
impl<T:Send> Pullable<T> for Box<Pullable<T>> { fn pull(&mut self) -> Option<T> { (**self).pull() } }

pub struct PushableObserver<T:Send, D:Send+Clone, P: Pushable<(T, Vec<D>)>> {
    pub data:       Vec<D>,
    pub pushable:   P,
    pub phantom:    PhantomData<T>,
}

impl<T:Send+Clone, D:Send+Clone, P: Pushable<(T, Vec<D>)>> Observer for PushableObserver<T,D,P> {
    type Time = T;
    type Data = D;
    #[inline(always)] fn open(&mut self,_time: &T) { }
    #[inline(always)] fn push(&mut self, data: &D) { self.data.push(data.clone()); }
    #[inline(always)] fn shut(&mut self, time: &T) {
        if self.data.len() > 0 {
            self.pushable.push((time.clone(), mem::replace(&mut self.data, Vec::new())));
        }
    }
}
<commit_msg>Make the implementations of Pushable and Pullable more generic<commit_after>use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
use std::sync::mpsc::{Sender, Receiver};
use core::marker::PhantomData;

use communication::Observer;

pub trait Pushable<T> { fn push(&mut self, data: T); }        // like observer
pub trait Pullable<T> { fn pull(&mut self) -> Option<T>; }    // like iterator

impl<T> Pushable<T> for Vec<T> { fn push(&mut self, data: T) { self.push(data); } }
impl<T> Pullable<T> for Vec<T> { fn pull(&mut self) -> Option<T> { self.pop() } }

impl<T:Send> Pushable<T> for Sender<T> { fn push(&mut self, data: T) { self.send(data).ok().expect("send error"); } }
impl<T:Send> Pullable<T> for Receiver<T> { fn pull(&mut self) -> Option<T> { self.try_recv().ok() }}

impl<T, P: ?Sized + Pushable<T>> Pushable<T> for Box<P> { fn push(&mut self, data: T) { (**self).push(data); } }
impl<T, P: ?Sized + Pullable<T>> Pullable<T> for Box<P> { fn pull(&mut self) -> Option<T> { (**self).pull() } }

impl<T, P: Pushable<T>> Pushable<T> for Rc<RefCell<P>> { fn push(&mut self, data: T) { self.borrow_mut().push(data); } }
impl<T, P: Pullable<T>> Pullable<T> for Rc<RefCell<P>> { fn pull(&mut self) -> Option<T> { self.borrow_mut().pull() } }

pub struct PushableObserver<T:Send, D:Send+Clone, P: Pushable<(T, Vec<D>)>> {
    pub data:       Vec<D>,
    pub pushable:   P,
    pub phantom:    PhantomData<T>,
}

impl<T:Send+Clone, D:Send+Clone, P: Pushable<(T, Vec<D>)>> Observer for PushableObserver<T,D,P> {
    type Time = T;
    type Data = D;
    #[inline(always)] fn open(&mut self,_time: &T) { }
    #[inline(always)] fn push(&mut self, data: &D) { self.data.push(data.clone()); }
    #[inline(always)] fn shut(&mut self, time: &T) {
        if self.data.len() > 0 {
            self.pushable.push((time.clone(), mem::replace(&mut self.data, Vec::new())));
        }
    }
}
<|endoftext|>


<commit_before>use flowgger::config::Config;
use openssl::bn::BigNum;
use openssl::dh::DH;
use openssl::ssl::*;
use openssl::x509::X509FileType;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use openssl::x509::X509;

pub mod tls_input;
#[cfg(feature = "coroutines")]
pub mod tlsco_input;

pub use super::Input;

const DEFAULT_CERT: &'static str = "flowgger.pem";
const DEFAULT_CIPHERS: &'static str = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
const DEFAULT_COMPRESSION: bool = false;
const DEFAULT_FRAMING: &'static str = "line";
const DEFAULT_KEY: &'static str = "flowgger.pem";
const DEFAULT_LISTEN: &'static str = "0.0.0.0:6514";
#[cfg(feature = "coroutines")]
const DEFAULT_THREADS: usize = 1;
const DEFAULT_TIMEOUT: u64 = 3600;
const DEFAULT_TLS_METHOD: &'static str = "any";
const DEFAULT_VERIFY_PEER: bool = false;
const TLS_VERIFY_DEPTH: u32 = 6;

#[derive(Clone)]
pub struct TlsConfig {
    framing: String,
    threads: usize,
    arc_ctx: Arc<SslContext>
}

#[cfg(feature = "ecdh")]
fn set_ecdh(ctx: &mut SslContext) {
    ctx.set_ecdh_auto(true).unwrap();
}

#[cfg(not(feature = "ecdh"))]
fn set_ecdh(ctx: &mut SslContext) {
    let _ = ctx;
}

fn set_fs(ctx: &mut SslContext) {
    let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap();
    let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap();
    let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap();
    let dh = DH::from_params(p, g, q).unwrap();
    ctx.set_tmp_dh(dh).unwrap();
    set_ecdh(ctx);
}

#[cfg(feature = "coroutines")]
fn get_default_threads(config: &Config) -> usize {
    config.lookup("input.tls_threads").map_or(DEFAULT_THREADS, |x| x.as_integer().
        expect("input.tls_threads must be an unsigned integer") as usize)
}

#[cfg(not(feature = "coroutines"))]
fn get_default_threads(_config: &Config) -> usize {
    1
}

pub fn config_parse(config: &Config) -> (TlsConfig, String, u64) {
    let listen = config.lookup("input.listen").map_or(DEFAULT_LISTEN, |x| x.as_str().
        expect("input.listen must be an ip:port string")).to_owned();
    let threads = get_default_threads(&config);
    let cert = config.lookup("input.tls_cert").map_or(DEFAULT_CERT, |x| x.as_str().
        expect("input.tls_cert must be a path to a .pem file")).to_owned();
    let key = config.lookup("input.tls_key").map_or(DEFAULT_KEY, |x| x.as_str().
        expect("input.tls_key must be a path to a .pem file")).to_owned();
    let ciphers = config.lookup("input.tls_ciphers").map_or(DEFAULT_CIPHERS, |x| x.as_str().
        expect("input.tls_ciphers must be a string with a cipher suite")).to_owned();
    let tls_method = match config.lookup("input.tls_method").map_or(DEFAULT_TLS_METHOD, |x| x.as_str().
        expect("input.tls_method must be a string with the TLS method")).to_lowercase().as_ref() {
            "any" | "sslv23" => SslMethod::Sslv23,
            "tlsv1" | "tlsv1.0" => SslMethod::Tlsv1,
            "tlsv1.1" => SslMethod::Tlsv1_1,
            "tlsv1.2" => SslMethod::Tlsv1_2,
            _ => panic!(r#"TLS method must be "any", "TLSv1.0", "TLSv1.1" or "TLSv1.2""#)
    };
    let verify_peer = config.lookup("input.tls_verify_peer").map_or(DEFAULT_VERIFY_PEER, |x| x.as_bool().
        expect("input.tls_verify_peer must be a boolean"));
    let ca_file: Option<PathBuf> = config.lookup("input.tls_ca_file").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_ca_file must be a path to a file"))));
    let compression = config.lookup("input.tls_compression").map_or(DEFAULT_COMPRESSION, |x| x.as_bool().
        expect("input.tls_compression must be a boolean"));
    let extra_chain_path: Option<PathBuf> = config.lookup("input.tls_cert_chain").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_extra_chain_path must be a path to a file"))));
    let timeout = config.lookup("input.timeout").map_or(DEFAULT_TIMEOUT, |x| x.as_integer().
        expect("input.timeout must be an integer") as u64);
    let framing = if config.lookup("input.framed").map_or(false, |x| x.as_bool().
        expect("input.framed must be a boolean")) {
        "syslen"
    } else {
        DEFAULT_FRAMING
    };
    let framing = config.lookup("input.framing").map_or(framing, |x| x.as_str().
        expect(r#"input.framing must be a string set to "line", "nul" or "syslen""#)).to_owned();
    let mut ctx = SslContext::new(tls_method).unwrap();
    if verify_peer == false {
        ctx.set_verify(SSL_VERIFY_NONE, None);
    } else {
        ctx.set_verify_depth(TLS_VERIFY_DEPTH);
        ctx.set_verify(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, None);
        if let Some(ca_file) = ca_file {
            ctx.set_CA_file(&ca_file).expect("Unable to read the trusted CA file");
        }
    }
    if let Some(extra_chain_path) = extra_chain_path {
         let mut extra_chain_file = File::open(extra_chain_path.as_path())
             .ok()
             .expect("Failed to open the extra chain cert file");
         let extra_chain_cert = X509::from_pem(&mut extra_chain_file).ok().expect("unable to load the provided extra chain cert");
         ctx.add_extra_chain_cert(&extra_chain_cert).expect("Unable to read the certificate chain");
    }

    let mut opts = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    if compression == false {
        opts = opts | SSL_OP_NO_COMPRESSION;
    }
    ctx.set_options(opts);
    set_fs(&mut ctx);
    ctx.set_certificate_file(&Path::new(&cert), X509FileType::PEM).
        expect("Unable to read the TLS certificate");
    ctx.set_private_key_file(&Path::new(&key), X509FileType::PEM).
        expect("Unable to read the TLS key");
    ctx.set_cipher_list(&ciphers).expect("Unsupported cipher suite");
    let arc_ctx = Arc::new(ctx);
    let tls_config = TlsConfig {
        framing: framing,
        threads: threads,
        arc_ctx: arc_ctx
    };
    (tls_config, listen, timeout)
}
<commit_msg>TLS: allow to set CA file when the user wants (to use cert chain completion feature) and variables renaming<commit_after>use flowgger::config::Config;
use openssl::bn::BigNum;
use openssl::dh::DH;
use openssl::ssl::*;
use openssl::x509::X509FileType;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use openssl::x509::X509;

pub mod tls_input;
#[cfg(feature = "coroutines")]
pub mod tlsco_input;

pub use super::Input;

const DEFAULT_CERT: &'static str = "flowgger.pem";
const DEFAULT_CIPHERS: &'static str = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
const DEFAULT_COMPRESSION: bool = false;
const DEFAULT_FRAMING: &'static str = "line";
const DEFAULT_KEY: &'static str = "flowgger.pem";
const DEFAULT_LISTEN: &'static str = "0.0.0.0:6514";
#[cfg(feature = "coroutines")]
const DEFAULT_THREADS: usize = 1;
const DEFAULT_TIMEOUT: u64 = 3600;
const DEFAULT_TLS_METHOD: &'static str = "any";
const DEFAULT_VERIFY_PEER: bool = false;
const TLS_VERIFY_DEPTH: u32 = 6;

#[derive(Clone)]
pub struct TlsConfig {
    framing: String,
    threads: usize,
    arc_ctx: Arc<SslContext>
}

#[cfg(feature = "ecdh")]
fn set_ecdh(ctx: &mut SslContext) {
    ctx.set_ecdh_auto(true).unwrap();
}

#[cfg(not(feature = "ecdh"))]
fn set_ecdh(ctx: &mut SslContext) {
    let _ = ctx;
}

fn set_fs(ctx: &mut SslContext) {
    let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap();
    let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap();
    let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap();
    let dh = DH::from_params(p, g, q).unwrap();
    ctx.set_tmp_dh(dh).unwrap();
    set_ecdh(ctx);
}

#[cfg(feature = "coroutines")]
fn get_default_threads(config: &Config) -> usize {
    config.lookup("input.tls_threads").map_or(DEFAULT_THREADS, |x| x.as_integer().
        expect("input.tls_threads must be an unsigned integer") as usize)
}

#[cfg(not(feature = "coroutines"))]
fn get_default_threads(_config: &Config) -> usize {
    1
}

pub fn config_parse(config: &Config) -> (TlsConfig, String, u64) {
    let listen = config.lookup("input.listen").map_or(DEFAULT_LISTEN, |x| x.as_str().
        expect("input.listen must be an ip:port string")).to_owned();
    let threads = get_default_threads(&config);
    let cert = config.lookup("input.tls_cert").map_or(DEFAULT_CERT, |x| x.as_str().
        expect("input.tls_cert must be a path to a .pem file")).to_owned();
    let key = config.lookup("input.tls_key").map_or(DEFAULT_KEY, |x| x.as_str().
        expect("input.tls_key must be a path to a .pem file")).to_owned();
    let ciphers = config.lookup("input.tls_ciphers").map_or(DEFAULT_CIPHERS, |x| x.as_str().
        expect("input.tls_ciphers must be a string with a cipher suite")).to_owned();
    let tls_method = match config.lookup("input.tls_method").map_or(DEFAULT_TLS_METHOD, |x| x.as_str().
        expect("input.tls_method must be a string with the TLS method")).to_lowercase().as_ref() {
            "any" | "sslv23" => SslMethod::Sslv23,
            "tlsv1" | "tlsv1.0" => SslMethod::Tlsv1,
            "tlsv1.1" => SslMethod::Tlsv1_1,
            "tlsv1.2" => SslMethod::Tlsv1_2,
            _ => panic!(r#"TLS method must be "any", "TLSv1.0", "TLSv1.1" or "TLSv1.2""#)
    };
    let verify_peer = config.lookup("input.tls_verify_peer").map_or(DEFAULT_VERIFY_PEER, |x| x.as_bool().
        expect("input.tls_verify_peer must be a boolean"));
    let ca_file: Option<PathBuf> = config.lookup("input.tls_ca_file").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_ca_file must be a path to a file"))));
    let compression = config.lookup("input.tls_compression").map_or(DEFAULT_COMPRESSION, |x| x.as_bool().
        expect("input.tls_compression must be a boolean"));
    let cert_chain_file_path: Option<PathBuf> = config.lookup("input.tls_cert_chain").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_cert_chain must be a path to a file"))));
    let timeout = config.lookup("input.timeout").map_or(DEFAULT_TIMEOUT, |x| x.as_integer().
        expect("input.timeout must be an integer") as u64);
    let framing = if config.lookup("input.framed").map_or(false, |x| x.as_bool().
        expect("input.framed must be a boolean")) {
        "syslen"
    } else {
        DEFAULT_FRAMING
    };
    let framing = config.lookup("input.framing").map_or(framing, |x| x.as_str().
        expect(r#"input.framing must be a string set to "line", "nul" or "syslen""#)).to_owned();
    let mut ctx = SslContext::new(tls_method).unwrap();
    if verify_peer == false {
        ctx.set_verify(SSL_VERIFY_NONE, None);
    } else {
        ctx.set_verify_depth(TLS_VERIFY_DEPTH);
        ctx.set_verify(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, None);
    }
    if let Some(ca_file) = ca_file {
            ctx.set_CA_file(&ca_file).expect("Unable to read the trusted CA file");
    }
    if let Some(cert_chain_file_path) = cert_chain_file_path {
         let mut cert_chain_file = File::open(cert_chain_file_path.as_path())
             .ok()
             .expect("Failed to open the extra chain cert file");
         let cert_chain_x509 = X509::from_pem(&mut cert_chain_file).ok().expect("unable to load the provided extra chain cert");
         ctx.add_extra_chain_cert(&cert_chain_x509).expect("Unable to read the certificate chain");
    }

    let mut opts = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    if compression == false {
        opts = opts | SSL_OP_NO_COMPRESSION;
    }
    ctx.set_options(opts);
    set_fs(&mut ctx);
    ctx.set_certificate_file(&Path::new(&cert), X509FileType::PEM).
        expect("Unable to read the TLS certificate");
    ctx.set_private_key_file(&Path::new(&key), X509FileType::PEM).
        expect("Unable to read the TLS key");
    ctx.set_cipher_list(&ciphers).expect("Unsupported cipher suite");
    let arc_ctx = Arc::new(ctx);
    let tls_config = TlsConfig {
        framing: framing,
        threads: threads,
        arc_ctx: arc_ctx
    };
    (tls_config, listen, timeout)
}
<|endoftext|>


<commit_before>//! This is a template file.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Added private data section to template.<commit_after>//! This is a template file.

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

// None

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_expect_fail(test: &mut Object) -> ExpectFail {
    ExpectFail {
        source: test.remove("source").unwrap().into_string(),
        error: test.remove("error").unwrap().into_string(),
        options: None
    }
}

fn parse_expect_pass(test: &mut Object) -> ExpectPass {
    ExpectPass {
        source: test.remove("source").unwrap().into_string(),
        expected: test.remove("expected").unwrap(),
        options: None
    }
}

fn nullary(token: Token) -> Box<Fn(&mut Object) -> Option<Token>> {
    Box::new(|_| { Some(token) })
}

fn deserialize_token(mut data: Json) -> Token {
    let mut obj = data.as_object_mut().unwrap();
    let ty = obj.remove("type").unwrap().into_string();

    let mut matchers: HashMap<&str, Box<Fn(&mut Object) -> Option<Token>>> = HashMap::new();
    matchers.insert("LBrace", Box::new(|_| -> Option<Token> { Some(Token::LBrace) }));
    matchers.insert("DecimalInt", Box::new(|data| -> Option<Token> {
        match data.remove("value") {
            None => None,
            Some(str) => Some(Token::DecimalInt(str.into_string()))
        }
    }));
    let f = matchers.get("DecimalInt").unwrap();
    let mut data = Json::from_str("{\"type\":\"DecimalInt\",\"value\":\"11.3\"}").unwrap();
    let obj = data.as_object_mut().unwrap();
    f(obj).unwrap()
}

fn parse_test(mut test: Json) -> TestCase {
    let obj = test.as_object_mut().unwrap();
    if obj.contains_key("error") {
        TestCase::Fail(parse_expect_fail(obj))
    } else {
        TestCase::Pass(parse_expect_pass(obj))
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<commit_msg>trying FnOnce since I know I want to move the token in and only call the function once, but mysterious new compiler error src/test/mod.rs:91:5: 91:6 error: cannot move out of borrowed content src/test/mod.rs:91     f(obj).unwrap()                        ^ src/test/mod.rs:91:5: 91:6 error: cannot move a value of type for<'r> core::ops::FnOnce(&'r mut collections::btree::map::BTreeMap<collections::string::String, rustc_serialize::json::Json>) -> core::option::Option<token::Token>: the size of for<'r> core::ops::FnOnce(&'r mut collections::btree::map::BTreeMap<collections::string::String, rustc_serialize::json::Json>) -> core::option::Option<token::Token> cannot be statically determined [E0161] src/test/mod.rs:91     f(obj).unwrap()                        ^<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_expect_fail(test: &mut Object) -> ExpectFail {
    ExpectFail {
        source: test.remove("source").unwrap().into_string(),
        error: test.remove("error").unwrap().into_string(),
        options: None
    }
}

fn parse_expect_pass(test: &mut Object) -> ExpectPass {
    ExpectPass {
        source: test.remove("source").unwrap().into_string(),
        expected: test.remove("expected").unwrap(),
        options: None
    }
}

fn nullary(token: Token) -> Box<FnOnce(&mut Object) -> Option<Token>> {
    Box::new(|_| { Some(token) })
}

fn deserialize_token(mut data: Json) -> Token {
    let mut obj = data.as_object_mut().unwrap();
    let ty = obj.remove("type").unwrap().into_string();

    let mut matchers: HashMap<&str, Box<FnOnce(&mut Object) -> Option<Token>>> = HashMap::new();
    matchers.insert("LBrace", Box::new(|_| -> Option<Token> { Some(Token::LBrace) }));
    matchers.insert("DecimalInt", Box::new(|data| -> Option<Token> {
        match data.remove("value") {
            None => None,
            Some(str) => Some(Token::DecimalInt(str.into_string()))
        }
    }));
    let f = matchers.get("DecimalInt").unwrap();
    let mut data = Json::from_str("{\"type\":\"DecimalInt\",\"value\":\"11.3\"}").unwrap();
    let obj = data.as_object_mut().unwrap();
    f(obj).unwrap()
}

fn parse_test(mut test: Json) -> TestCase {
    let obj = test.as_object_mut().unwrap();
    if obj.contains_key("error") {
        TestCase::Fail(parse_expect_fail(obj))
    } else {
        TestCase::Pass(parse_expect_pass(obj))
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_test(mut test: Json) -> TestCase {
    unimplemented!()
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<commit_msg>flesh out the basic JSON decoding for test descriptors<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_expect_fail(test: &mut Object) -> ExpectFail {
    ExpectFail {
        source: test.remove("source").unwrap().into_string(),
        error: test.remove("error").unwrap().into_string(),
        options: None
    }
}

fn parse_expect_pass(test: &mut Object) -> ExpectPass {
    ExpectPass {
        source: test.remove("source").unwrap().into_string(),
        expected: test.remove("expected").unwrap(),
        options: None
    }
}

fn parse_test(mut test: Json) -> TestCase {
    let obj = test.as_object_mut().unwrap();
    if obj.contains_key("error") {
        TestCase::Fail(parse_expect_fail(obj))
    } else {
        TestCase::Pass(parse_expect_pass(obj))
    }
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<|endoftext|>


<commit_before>use std::marker;
use std::string::ToString;

pub trait FrameRate {
  const FPS: u32;

  fn get_fps() -> u32 {
    Self::FPS
  }
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2400;

impl FrameRate for FrameRate2400 {
  const FPS: u32 = 24;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2500;

impl FrameRate for FrameRate2500 {
  const FPS: u32 = 25;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate3000;

impl FrameRate for FrameRate3000 {
  const FPS: u32 = 30;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate5000;

impl FrameRate for FrameRate5000 {
  const FPS: u32 = 50;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate6000;

impl FrameRate for FrameRate6000 {
  const FPS: u32 = 60;
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode<FrameRate> {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: marker::PhantomData<FrameRate>,
}

impl<FrameRate> ToString for Timecode<FrameRate> {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl<FR: FrameRate> From<u32> for Timecode<FR> {
  fn from(frames: u32) -> Self {
    let fps = FR::get_fps();

    let hours = frames / (60 * 60 * fps);
    let minutes = (frames / (60 * fps)) - hours * 60;
    let seconds = (frames / fps) - minutes * 60 - hours * 60 * 60;
    let frame = frames - seconds * fps - minutes * 60 * fps - hours * 60 * 60 * fps;
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData,
    }
  }
}

impl<FrameRate> Timecode<FrameRate> {
  pub fn parse_smpte_331m(data: &[u8]) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::<FrameRate>::parse_smpte_12m(&data[1..]),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8]) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::<FrameRate>::get_number(data[0], mask_tens_2);
    let seconds = Timecode::<FrameRate>::get_number(data[1], mask_tens_3);
    let minutes = Timecode::<FrameRate>::get_number(data[2], mask_tens_3);
    let hours = Timecode::<FrameRate>::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode::<FrameRate> {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData::<FrameRate>,
    })
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60 * 10);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60);
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60 - 1);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 - 1);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2400>::from(24);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(23);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2500>::from(25);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2500>::from(24);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);
}
<commit_msg>add from_ebu_smpte_time_and_control method with tests<commit_after>use std::marker;
use std::string::ToString;

pub trait FrameRate {
  const FPS: u32;

  fn get_fps() -> u32 {
    Self::FPS
  }
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2400;

impl FrameRate for FrameRate2400 {
  const FPS: u32 = 24;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate2500;

impl FrameRate for FrameRate2500 {
  const FPS: u32 = 25;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate3000;

impl FrameRate for FrameRate3000 {
  const FPS: u32 = 30;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate5000;

impl FrameRate for FrameRate5000 {
  const FPS: u32 = 50;
}

#[derive(Debug, PartialEq)]
pub struct FrameRate6000;

impl FrameRate for FrameRate6000 {
  const FPS: u32 = 60;
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode<FrameRate> {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: marker::PhantomData<FrameRate>,
}

impl<FrameRate> ToString for Timecode<FrameRate> {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl<FR: FrameRate> From<u32> for Timecode<FR> {
  fn from(frames: u32) -> Self {
    let fps = FR::get_fps();

    let hours = frames / (60 * 60 * fps);
    let minutes = (frames / (60 * fps)) - hours * 60;
    let seconds = (frames / fps) - minutes * 60 - hours * 60 * 60;
    let frame = frames - seconds * fps - minutes * 60 * fps - hours * 60 * 60 * fps;
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData,
    }
  }
}

impl<FrameRate> Timecode<FrameRate> {
  pub fn parse_smpte_331m(data: &[u8]) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::<FrameRate>::parse_smpte_12m(&data[1..]),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8]) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::<FrameRate>::get_number(data[0], mask_tens_2);
    let seconds = Timecode::<FrameRate>::get_number(data[1], mask_tens_3);
    let minutes = Timecode::<FrameRate>::get_number(data[2], mask_tens_3);
    let hours = Timecode::<FrameRate>::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode::<FrameRate> {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate: marker::PhantomData::<FrameRate>,
    })
  }

  // used in STL format (EBU Tech 3264)
  pub fn from_ebu_smpte_time_and_control(data: &[u8; 4]) -> Self {
    Timecode::<FrameRate> {
      hours: data[0],
      minutes: data[1],
      seconds: data[2],
      frame: data[3],
      drop_frame: false,
      color_frame: false,
      frame_rate: marker::PhantomData::<FrameRate>,
    }
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60 * 10);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60);
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 * 60 - 1);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(24 * 60 - 1);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2400>::from(24);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2400>::from(23);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::<FrameRate2500>::from(25);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2500>::from(24);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);

  let timecode = Timecode::<FrameRate2500>::from_ebu_smpte_time_and_control(&[10, 0, 0, 0]);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2500>::from_ebu_smpte_time_and_control(&[0, 10, 0, 0]);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 10);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2500>::from_ebu_smpte_time_and_control(&[0, 0, 10, 0]);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 10);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::<FrameRate2500>::from_ebu_smpte_time_and_control(&[0, 0, 0, 10]);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 10);
}
<|endoftext|>