<commit_before>//! Power Management Unit (PMU)
//!
//! The Power Management Unit (PMU) controls the chip's power states and clock
//! power, as well as allows the chip to interface with peripherals at different
//! voltage levels.
//!
//! There are three types of power domains:
//!
//!   1. VDDIOMR:
//!
//!     * Always-on main I/O voltage supply domain necessary for the running the
//!       core.
//!     * Nominal 3.3V
//!
//!   2. VDDIOA & VDDIOB:
//!
//!     * I/O voltage supply domains for external peripherals.
//!
//!     * Can be shut down at any moment (not critical for core functions).
//!
//!     * Designed for 1.8-3.6V
//!
//!   3. VDDIOF:
//!
//!     * I/O voltage supply domain for flash memory.
//!
//!     * Designed for 1.8-3.6V
//!

use common::volatile_cell::VolatileCell;
use core::mem::transmute;

/// Registers for the Power Management Unit (PMU)
// Non-public fields prefixed with "_" mark unused registers
#[repr(C, packed)]
pub struct PMURegisters {
    _reset: VolatileCell<u32>,
    _set_reset: VolatileCell<u32>,

    /// Clear register for the reset source
    pub clear_reset: VolatileCell<u32>,

    /// Status for source of last reset event
    ///
    /// Bits 0-7 correspond to:
    ///
    /// | bit | Description                                       |
    /// | --- | :------------------------------------------------ |
    /// | 0   | Power on reset                                    |
    /// | 1   | Low power exit                                    |
    /// | 2   | Watchdog reset                                    |
    /// | 3   | Lockup reset                                      |
    /// | 4   | SYSRESET                                          |
    /// | 5   | Software initiated reset through PMU_GLOBAL_RESET |
    /// | 6   | Fast burnout circuit                              |
    /// | 7   | Security breach reset                             |
    ///
    pub reset_source: VolatileCell<u32>,

    /// Global chip reset
    ///
    /// Initiates a reset of the system similar to toggling the external reset
    /// pin. To initiate a reset, write the key 0x7041776 to this register.
    pub global_reset: VolatileCell<u32>,

    pub low_power_disable: VolatileCell<u32>,

    pub low_power_bypass: VolatileCell<u32>,

    pub low_power_bypass_value: VolatileCell<u32>,

    pub set_wakeup_interrupt_controller: VolatileCell<u32>,

    pub clear_wakeup_interrupt_controller: VolatileCell<u32>,

    /// Value of the system vector table offset
    pub sysvtor: VolatileCell<u32>,

    /// Enable PMU to gate some clocks when processor is sleeping
    pub nap_enable: VolatileCell<u32>,

    _pmu_sw_pdb: VolatileCell<u32>,
    _pmu_vref: VolatileCell<u32>,
    _xtl_osc_bypass: VolatileCell<u32>,
    _flash_tm0_test_en_bypass: VolatileCell<u32>,

    /// Battery level indicator
    ///
    /// When non-zero, the voltage level is higher than specified in the vref
    /// register's BATMON field.
    pub battery_level_ok: VolatileCell<u32>,

    _b_reg_dig_ctrl: VolatileCell<u32>,
    _exitpd_mask: VolatileCell<u32>,
    _exitpd_src: VolatileCell<u32>,
    _exitpd_mon: VolatileCell<u32>,
    _osc_ctrl: VolatileCell<u32>,

    /// Turn on clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_set: VolatileCell<u32>,

    /// Turn off clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_clear: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_disable: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_disable: VolatileCell<u32>,
}

const PMU_BASE : isize = 0x40000000;

static mut PMU : *mut PMURegisters = PMU_BASE as *mut PMURegisters;

#[derive(Clone,Copy)]
pub enum PeripheralClock0 {
    Camo0,
    Crpyto0,
    Dma0,
    Flash0,
    Fuse0,
    GlobalSec,
    GlobalSecTimer,
    GlobalSecHs,
    Gpio0,
    Gpio1,
    I2C0,
    I2C1,
    I2CS0,
    KeyMgr0,
    PeriAPB0,
    PeriAPB1,
    PeriAPB2,
    PeriAPB2Timer,
    PeriAPB3,
    PeriAPB3Timer,
    PeriAPB3HS,
    PinMux,
    Pmu,
    RBox0,
    Rdd0,
    Rtc0,
    Rtc0Timer,
    Spi0Hs,
    Spi1Hs,
    Sps0,
    Sps0TimerHs,
    Swdp0,
    Temp0
}

#[derive(Clone,Copy)]
pub enum PeripheralClock1 {
    TimeHs0Timer,
    TimeHs1Timer,
    TimeLs0,
    TimeUs0Timer,
    Trng0,
    Uart0Timer,
    Uart1Timer,
    Uart2Timer,
    Usb0,
    Usb0TimerHs,
    Volt0,
    Watchdog0,
    Xo0,
    Xo0Timer,
    PeripheralMasterMatrix,
    PeripheralMatrix
}

#[derive(Clone,Copy)]
pub enum PeripheralClock {
    Bank0(PeripheralClock0),
    Bank1(PeripheralClock1)
}

/// Wrapper struct around `PeripheralClock` that can only be created by.
/// trusted code.
#[derive(Clone,Copy)]
pub struct Clock {
    // It's important that this field is private!
    clock: PeripheralClock
}

impl Clock {
    pub unsafe fn new(clock: PeripheralClock) -> Clock {
        Clock { clock: clock }
    }

    pub fn enable(&self) {
        let pmu : &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_enable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_enable.set(1 << (clock as u32));
            }
        }
    }

    pub fn disable(&self) {
        let pmu : &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_disable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_disable.set(1 << (clock as u32));
            }
        }
    }
}

<commit_msg>Formatting nits<commit_after>//! Power Management Unit (PMU)
//!
//! The Power Management Unit (PMU) controls the chip's power states and clock
//! power, as well as allows the chip to interface with peripherals at different
//! voltage levels.
//!
//! There are three types of power domains:
//!
//!   1. VDDIOMR:
//!
//!     * Always-on main I/O voltage supply domain necessary for the running the
//!       core.
//!     * Nominal 3.3V
//!
//!   2. VDDIOA & VDDIOB:
//!
//!     * I/O voltage supply domains for external peripherals.
//!
//!     * Can be shut down at any moment (not critical for core functions).
//!
//!     * Designed for 1.8-3.6V
//!
//!   3. VDDIOF:
//!
//!     * I/O voltage supply domain for flash memory.
//!
//!     * Designed for 1.8-3.6V
//!

use common::volatile_cell::VolatileCell;
use core::mem::transmute;

/// Registers for the Power Management Unit (PMU)
// Non-public fields prefixed with "_" mark unused registers
#[repr(C, packed)]
pub struct PMURegisters {
    _reset: VolatileCell<u32>,
    _set_reset: VolatileCell<u32>,

    /// Clear register for the reset source
    pub clear_reset: VolatileCell<u32>,

    /// Status for source of last reset event
    ///
    /// Bits 0-7 correspond to:
    ///
    /// | bit | Description                                       |
    /// | --- | :------------------------------------------------ |
    /// | 0   | Power on reset                                    |
    /// | 1   | Low power exit                                    |
    /// | 2   | Watchdog reset                                    |
    /// | 3   | Lockup reset                                      |
    /// | 4   | SYSRESET                                          |
    /// | 5   | Software initiated reset through PMU_GLOBAL_RESET |
    /// | 6   | Fast burnout circuit                              |
    /// | 7   | Security breach reset                             |
    ///
    pub reset_source: VolatileCell<u32>,

    /// Global chip reset
    ///
    /// Initiates a reset of the system similar to toggling the external reset
    /// pin. To initiate a reset, write the key 0x7041776 to this register.
    pub global_reset: VolatileCell<u32>,

    pub low_power_disable: VolatileCell<u32>,

    pub low_power_bypass: VolatileCell<u32>,

    pub low_power_bypass_value: VolatileCell<u32>,

    pub set_wakeup_interrupt_controller: VolatileCell<u32>,

    pub clear_wakeup_interrupt_controller: VolatileCell<u32>,

    /// Value of the system vector table offset
    pub sysvtor: VolatileCell<u32>,

    /// Enable PMU to gate some clocks when processor is sleeping
    pub nap_enable: VolatileCell<u32>,

    _pmu_sw_pdb: VolatileCell<u32>,
    _pmu_vref: VolatileCell<u32>,
    _xtl_osc_bypass: VolatileCell<u32>,
    _flash_tm0_test_en_bypass: VolatileCell<u32>,

    /// Battery level indicator
    ///
    /// When non-zero, the voltage level is higher than specified in the vref
    /// register's BATMON field.
    pub battery_level_ok: VolatileCell<u32>,

    _b_reg_dig_ctrl: VolatileCell<u32>,
    _exitpd_mask: VolatileCell<u32>,
    _exitpd_src: VolatileCell<u32>,
    _exitpd_mon: VolatileCell<u32>,
    _osc_ctrl: VolatileCell<u32>,

    /// Turn on clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_set: VolatileCell<u32>,

    /// Turn off clocks for memory
    ///
    /// Bits 0-6 correspond to memory banks 0-6, respectively.
    pub memory_clk_clear: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 0).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks0_disable: VolatileCell<u32>,

    /// Enable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_enable: VolatileCell<u32>,

    /// Disable peripheral clocks (bank 1).
    ///
    /// Each bit corresponds to a different peripheral clock.
    pub peripheral_clocks1_disable: VolatileCell<u32>,
}

const PMU_BASE: isize = 0x40000000;

static mut PMU: *mut PMURegisters = PMU_BASE as *mut PMURegisters;

#[derive(Clone,Copy)]
pub enum PeripheralClock0 {
    Camo0,
    Crpyto0,
    Dma0,
    Flash0,
    Fuse0,
    GlobalSec,
    GlobalSecTimer,
    GlobalSecHs,
    Gpio0,
    Gpio1,
    I2C0,
    I2C1,
    I2CS0,
    KeyMgr0,
    PeriAPB0,
    PeriAPB1,
    PeriAPB2,
    PeriAPB2Timer,
    PeriAPB3,
    PeriAPB3Timer,
    PeriAPB3HS,
    PinMux,
    Pmu,
    RBox0,
    Rdd0,
    Rtc0,
    Rtc0Timer,
    Spi0Hs,
    Spi1Hs,
    Sps0,
    Sps0TimerHs,
    Swdp0,
    Temp0
}

#[derive(Clone,Copy)]
pub enum PeripheralClock1 {
    TimeHs0Timer,
    TimeHs1Timer,
    TimeLs0,
    TimeUs0Timer,
    Trng0,
    Uart0Timer,
    Uart1Timer,
    Uart2Timer,
    Usb0,
    Usb0TimerHs,
    Volt0,
    Watchdog0,
    Xo0,
    Xo0Timer,
    PeripheralMasterMatrix,
    PeripheralMatrix
}

#[derive(Clone,Copy)]
pub enum PeripheralClock {
    Bank0(PeripheralClock0),
    Bank1(PeripheralClock1)
}

/// Wrapper struct around `PeripheralClock` that can only be created by.
/// trusted code.
#[derive(Clone,Copy)]
pub struct Clock {
    // It's important that this field is private!
    clock: PeripheralClock
}

impl Clock {
    pub unsafe fn new(clock: PeripheralClock) -> Clock {
        Clock { clock: clock }
    }

    pub fn enable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_enable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_enable.set(1 << (clock as u32));
            }
        }
    }

    pub fn disable(&self) {
        let pmu: &mut PMURegisters = unsafe { transmute(PMU) };
        match self.clock {
            PeripheralClock::Bank0(clock) => {
                pmu.peripheral_clocks0_disable.set(1 << (clock as u32));
            },
            PeripheralClock::Bank1(clock) => {
                pmu.peripheral_clocks1_disable.set(1 << (clock as u32));
            }
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>Update rpc event handling.<commit_after><|endoftext|>


<commit_before>//! Types for the Global Descriptor Table and segment selectors.

use bit_field::BitField;
use core::fmt;
use structures::tss::TaskStateSegment;
use PrivilegeLevel;

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct SegmentSelector(pub u16);

impl SegmentSelector {
    /// Creates a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index`: index in GDT or LDT array (not the offset)
    ///  * `rpl`: the requested privilege level
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector(index << 3 | (rpl as u16))
    }

    /// Returns the GDT index.
    pub fn index(&self) -> u16 {
        self.0 >> 3
    }

    /// Returns the requested privilege level.
    pub fn rpl(&self) -> PrivilegeLevel {
        PrivilegeLevel::from_u16(self.0.get_bits(0..2))
    }
}

impl fmt::Debug for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s = f.debug_struct("SegmentSelector");
        s.field("index", &self.index());
        s.field("rpl", &self.rpl());
        s.finish()
    }
}

pub struct GlobalDescriptorTable {
    table: [u64; 8],
    next_free: usize,
}

impl GlobalDescriptorTable {
    pub fn new() -> GlobalDescriptorTable {
        GlobalDescriptorTable {
            table: [0; 8],
            next_free: 1,
        }
    }

    pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector {
        let index = match entry {
            Descriptor::UserSegment(value) => self.push(value),
            Descriptor::SystemSegment(value_low, value_high) => {
                let index = self.push(value_low);
                self.push(value_high);
                index
            }
        };
        SegmentSelector::new(index as u16, PrivilegeLevel::Ring0)
    }

    pub fn load(&'static self) {
        use core::mem::size_of;
        use instructions::tables::{lgdt, DescriptorTablePointer};

        let ptr = DescriptorTablePointer {
            base: self.table.as_ptr() as u64,
            limit: (self.table.len() * size_of::<u64>() - 1) as u16,
        };

        unsafe { lgdt(&ptr) };
    }

    fn push(&mut self, value: u64) -> usize {
        if self.next_free < self.table.len() {
            let index = self.next_free;
            self.table[index] = value;
            self.next_free += 1;
            index
        } else {
            panic!("GDT full");
        }
    }
}

pub enum Descriptor {
    UserSegment(u64),
    SystemSegment(u64, u64),
}

bitflags! {
    pub struct DescriptorFlags: u64 {
        const CONFORMING        = 1 << 42;
        const EXECUTABLE        = 1 << 43;
        const USER_SEGMENT      = 1 << 44;
        const PRESENT           = 1 << 47;
        const LONG_MODE         = 1 << 53;
    }
}

impl Descriptor {
    pub fn kernel_code_segment() -> Descriptor {
        use self::DescriptorFlags as Flags;

        let flags = Flags::USER_SEGMENT | Flags::PRESENT | Flags::EXECUTABLE | Flags::LONG_MODE;
        Descriptor::UserSegment(flags.bits())
    }

    pub fn tss_segment(tss: &'static TaskStateSegment) -> Descriptor {
        use self::DescriptorFlags as Flags;
        use bit_field::BitField;
        use core::mem::size_of;

        let ptr = tss as *const _ as u64;

        let mut low = Flags::PRESENT.bits();
        // base
        low.set_bits(16..40, ptr.get_bits(0..24));
        low.set_bits(56..64, ptr.get_bits(24..32));
        // limit (the `-1` in needed since the bound is inclusive)
        low.set_bits(0..16, (size_of::<TaskStateSegment>() - 1) as u64);
        // type (0b1001 = available 64-bit tss)
        low.set_bits(40..44, 0b1001);

        let mut high = 0;
        high.set_bits(0..32, ptr.get_bits(32..64));

        Descriptor::SystemSegment(low, high)
    }
}
<commit_msg>Add documentation for the GDT types and methods<commit_after>//! Types for the Global Descriptor Table and segment selectors.

use bit_field::BitField;
use core::fmt;
use structures::tss::TaskStateSegment;
use PrivilegeLevel;

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct SegmentSelector(pub u16);

impl SegmentSelector {
    /// Creates a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index`: index in GDT or LDT array (not the offset)
    ///  * `rpl`: the requested privilege level
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector(index << 3 | (rpl as u16))
    }

    /// Returns the GDT index.
    pub fn index(&self) -> u16 {
        self.0 >> 3
    }

    /// Returns the requested privilege level.
    pub fn rpl(&self) -> PrivilegeLevel {
        PrivilegeLevel::from_u16(self.0.get_bits(0..2))
    }
}

impl fmt::Debug for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s = f.debug_struct("SegmentSelector");
        s.field("index", &self.index());
        s.field("rpl", &self.rpl());
        s.finish()
    }
}

/// A 64-bit mode global descriptor table (GDT).
///
/// In 64-bit mode, segmentation is not supported. The GDT is used nonetheless, for example for
/// switching between user and kernel mode or for loading a TSS.
///
/// The GDT has a fixed size of 8 entries, trying to add more entries will panic.
pub struct GlobalDescriptorTable {
    table: [u64; 8],
    next_free: usize,
}

impl GlobalDescriptorTable {
    /// Creates an empty GDT.
    pub fn new() -> GlobalDescriptorTable {
        GlobalDescriptorTable {
            table: [0; 8],
            next_free: 1,
        }
    }

    /// Adds the given segment descriptor to the GDT, returning the segment selector.
    ///
    /// Panics if the GDT has no free entries left.
    pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector {
        let index = match entry {
            Descriptor::UserSegment(value) => self.push(value),
            Descriptor::SystemSegment(value_low, value_high) => {
                let index = self.push(value_low);
                self.push(value_high);
                index
            }
        };
        SegmentSelector::new(index as u16, PrivilegeLevel::Ring0)
    }

    /// Loads the GDT in the CPU using the `lgdt` instruction.
    pub fn load(&'static self) {
        use core::mem::size_of;
        use instructions::tables::{lgdt, DescriptorTablePointer};

        let ptr = DescriptorTablePointer {
            base: self.table.as_ptr() as u64,
            limit: (self.table.len() * size_of::<u64>() - 1) as u16,
        };

        unsafe { lgdt(&ptr) };
    }

    fn push(&mut self, value: u64) -> usize {
        if self.next_free < self.table.len() {
            let index = self.next_free;
            self.table[index] = value;
            self.next_free += 1;
            index
        } else {
            panic!("GDT full");
        }
    }
}

/// A 64-bit mode segment descriptor.
///
/// Segmentation is no longer supported in 64-bit mode, so most of the descriptor
/// contents are ignored.
pub enum Descriptor {
    /// Descriptor for a code or data segment.
    ///
    /// Since segmentation is no longer supported in 64-bit mode, almost all of
    /// code and data descriptors is ignored. Only some flags are still used.
    UserSegment(u64),
    /// A system segment descriptor such as a LDT or TSS descriptor.
    SystemSegment(u64, u64),
}

bitflags! {
    /// Flags for a GDT descriptor. Not all flags are valid for all descriptor types.
    pub struct DescriptorFlags: u64 {
        /// Marks a code segment as “conforming”. This influences the privilege checks that
        /// occur on control transfers.
        const CONFORMING        = 1 << 42;
        /// This flag must be set for code segments.
        const EXECUTABLE        = 1 << 43;
        /// This flag must be set for user segments (in contrast to system segments).
        const USER_SEGMENT      = 1 << 44;
        /// Must be set for any segment, causes a segment not present exception if not set.
        const PRESENT           = 1 << 47;
        /// Must be set for long mode code segments.
        const LONG_MODE         = 1 << 53;
    }
}

impl Descriptor {
    /// Creates a segment descriptor for a long mode kernel code segment.
    pub fn kernel_code_segment() -> Descriptor {
        use self::DescriptorFlags as Flags;

        let flags = Flags::USER_SEGMENT | Flags::PRESENT | Flags::EXECUTABLE | Flags::LONG_MODE;
        Descriptor::UserSegment(flags.bits())
    }

    /// Creates a TSS system descriptor for the given TSS.
    pub fn tss_segment(tss: &'static TaskStateSegment) -> Descriptor {
        use self::DescriptorFlags as Flags;
        use bit_field::BitField;
        use core::mem::size_of;

        let ptr = tss as *const _ as u64;

        let mut low = Flags::PRESENT.bits();
        // base
        low.set_bits(16..40, ptr.get_bits(0..24));
        low.set_bits(56..64, ptr.get_bits(24..32));
        // limit (the `-1` in needed since the bound is inclusive)
        low.set_bits(0..16, (size_of::<TaskStateSegment>() - 1) as u64);
        // type (0b1001 = available 64-bit tss)
        low.set_bits(40..44, 0b1001);

        let mut high = 0;
        high.set_bits(0..32, ptr.get_bits(32..64));

        Descriptor::SystemSegment(low, high)
    }
}
<|endoftext|>


<commit_before>use crate::constants::*;
use crate::tokenizer;
use diffus::{
    edit::{self, collection},
    Diffable,
};

/// If more than this part of either adds or moves is highlighted,
/// we consider it to be a replacement rather than a move, and skip
/// highlighting it.
const MAX_HIGHLIGHT_PERCENTAGE: usize = 30;

/// This constant is mostly made up. The Ruby version of riff had its
/// limit set to 15_000, and this is more than that because blue.
const MAX_HIGHLIGHT_LENGTH: usize = 25_000;

pub struct Refiner<'a> {
    adds: &'a str,
    removes: &'a str,
}

impl<'a> Refiner<'a> {
    pub fn create(adds: &'a String, removes: &'a String) -> Self {
        return Refiner { adds, removes };
    }

    /// Format add and remove lines in ADD and REMOVE colors.
    ///
    /// No intra-line refinement.
    #[must_use]
    fn simple_format(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();

        for remove_line in self.removes.lines() {
            lines.push(format!("{}-{}{}", REMOVE, remove_line, NORMAL));
        }
        if (!self.removes.is_empty()) && self.removes.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        for add_line in self.adds.lines() {
            lines.push(format!("{}+{}{}", ADD, add_line, NORMAL))
        }
        if (!self.adds.is_empty()) && self.adds.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        return lines;
    }

    /// Returns a vector of ANSI highlighted lines
    #[must_use]
    pub fn format(self) -> Vec<String> {
        if self.adds.is_empty() {
            return self.simple_format();
        }

        if self.removes.is_empty() {
            return self.simple_format();
        }

        if self.adds.len() + self.removes.len() > MAX_HIGHLIGHT_LENGTH {
            return self.simple_format();
        }

        // Find diffs between adds and removals
        let mut highlighted_adds = String::new();
        let mut highlighted_removes = String::new();
        let mut adds_is_inverse = false;
        let mut removes_is_inverse = false;
        let mut adds_highlight_count = 0;
        let mut removes_highlight_count = 0;

        // Tokenize adds and removes before diffing them
        let tokenized_adds = tokenizer::tokenize(self.adds);
        let tokenized_removes = tokenizer::tokenize(self.removes);

        let diff = tokenized_removes.diff(&tokenized_adds);
        match diff {
            edit::Edit::Copy(unchanged) => {
                for token in unchanged {
                    highlighted_adds.push_str(token);
                    highlighted_removes.push_str(token);
                }
            }
            edit::Edit::Change(diff) => {
                diff.into_iter()
                    .map(|edit| {
                        match edit {
                            collection::Edit::Copy(elem) => {
                                if adds_is_inverse {
                                    highlighted_adds.push_str(NOT_INVERSE_VIDEO);
                                }
                                adds_is_inverse = false;

                                if removes_is_inverse {
                                    highlighted_removes.push_str(NOT_INVERSE_VIDEO);
                                }
                                removes_is_inverse = false;

                                highlighted_adds.push_str(elem);
                                highlighted_removes.push_str(elem);
                            }
                            collection::Edit::Insert(elem) => {
                                adds_highlight_count += 1;
                                if !adds_is_inverse {
                                    highlighted_adds.push_str(INVERSE_VIDEO);
                                }
                                adds_is_inverse = true;

                                if elem == &"\n" {
                                    // Make sure the highlighted linefeed is visible
                                    highlighted_adds.push('⏎');

                                    // This will be reset by the linefeed, so we need to re-inverse on the next line
                                    adds_is_inverse = false;
                                }
                                highlighted_adds.push_str(elem);
                            }
                            collection::Edit::Remove(elem) => {
                                removes_highlight_count += 1;
                                if !removes_is_inverse {
                                    highlighted_removes.push_str(INVERSE_VIDEO);
                                }
                                removes_is_inverse = true;

                                if elem == &"\n" {
                                    // Make sure the highlighted linefeed is visible
                                    highlighted_removes.push('⏎');

                                    // This will be reset by the linefeed, so we need to re-inverse on the next line
                                    removes_is_inverse = false;
                                }
                                highlighted_removes.push_str(elem);
                            }
                            collection::Edit::Change(_) => panic!("Not implemented, help!"),
                        };
                    })
                    .for_each(drop);
            }
        }

        if (100 * adds_highlight_count) / self.adds.len() > MAX_HIGHLIGHT_PERCENTAGE {
            return self.simple_format();
        }
        if (100 * removes_highlight_count) / self.removes.len() > MAX_HIGHLIGHT_PERCENTAGE {
            return self.simple_format();
        }

        let mut lines: Vec<String> = Vec::new();
        for highlighted_remove in highlighted_removes.lines() {
            lines.push(format!("{}-{}{}", REMOVE, highlighted_remove, NORMAL));
        }
        if (!self.removes.is_empty()) && self.removes.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        for highlighted_add in highlighted_adds.lines() {
            lines.push(format!("{}+{}{}", ADD, highlighted_add, NORMAL));
        }
        if (!self.adds.is_empty()) && self.adds.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        return lines;
    }
}

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

    #[cfg(test)]
    use pretty_assertions::assert_eq;

    #[test]
    fn test_simple_format_adds_and_removes() {
        let empty: Vec<String> = Vec::new();
        assert_eq!(
            Refiner::create(&"".to_string(), &"".to_string()).simple_format(),
            empty
        );

        // Test adds-only
        assert_eq!(
            Refiner::create(&"a\n".to_string(), &"".to_string()).simple_format(),
            ["".to_string() + ADD + "+a" + NORMAL]
        );
        assert_eq!(
            Refiner::create(&"a\nb\n".to_string(), &"".to_string()).simple_format(),
            [
                "".to_string() + ADD + "+a" + NORMAL,
                "".to_string() + ADD + "+b" + NORMAL,
            ]
        );

        // Test removes-only
        assert_eq!(
            Refiner::create(&"".to_string(), &"a\n".to_string()).simple_format(),
            ["".to_string() + REMOVE + "-a" + NORMAL]
        );
        assert_eq!(
            Refiner::create(&"".to_string(), &"a\nb\n".to_string()).simple_format(),
            [
                "".to_string() + REMOVE + "-a" + NORMAL,
                "".to_string() + REMOVE + "-b" + NORMAL,
            ]
        );
    }

    #[test]
    fn test_quote_change() {
        assert_eq!(
            Refiner::create(&"[quotes]\n".to_string(), &"<quotes>\n".to_string()).format(),
            [
                format!(
                    "{}-{}<{}quotes{}>{}{}",
                    REMOVE,
                    INVERSE_VIDEO,
                    NOT_INVERSE_VIDEO,
                    INVERSE_VIDEO,
                    NOT_INVERSE_VIDEO,
                    NORMAL
                ),
                format!(
                    "{}+{}[{}quotes{}]{}{}",
                    ADD, INVERSE_VIDEO, NOT_INVERSE_VIDEO, INVERSE_VIDEO, NOT_INVERSE_VIDEO, NORMAL
                ),
            ]
        )
    }
}
<commit_msg>Fix broken maths<commit_after>use crate::constants::*;
use crate::tokenizer;
use diffus::{
    edit::{self, collection},
    Diffable,
};

/// If more than this part of either adds or moves is highlighted,
/// we consider it to be a replacement rather than a move, and skip
/// highlighting it.
///
// FIXME: Turn this condition into a test case
/// If tuning this, please check that the `Inspired by` part of `git show
/// 77c8f77 -- bin/riff` is highlighted as an upside down L.
const MAX_HIGHLIGHT_PERCENTAGE: usize = 30;

/// If it's only this few highlights, we'll just highligh anyway without
/// checking the `MAX_HIGHLIGHT_PERCENTAGE`.
///
// FIXME: Turn this condition into a test case
/// If tuning this, please check that the `Inspired by` part of `git show
/// 77c8f77 -- bin/riff` is highlighted as an upside down L.
const OK_HIGHLIGHT_COUNT: usize = 5;

/// This constant is mostly made up. The Ruby version of riff had its
/// limit set to 15_000, and this is more than that because blue.
const MAX_HIGHLIGHT_LENGTH: usize = 25_000;

pub struct Refiner<'a> {
    adds: &'a str,
    removes: &'a str,
}

impl<'a> Refiner<'a> {
    pub fn create(adds: &'a String, removes: &'a String) -> Self {
        return Refiner { adds, removes };
    }

    /// Format add and remove lines in ADD and REMOVE colors.
    ///
    /// No intra-line refinement.
    #[must_use]
    fn simple_format(&self) -> Vec<String> {
        let mut lines: Vec<String> = Vec::new();

        for remove_line in self.removes.lines() {
            lines.push(format!("{}-{}{}", REMOVE, remove_line, NORMAL));
        }
        if (!self.removes.is_empty()) && self.removes.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        for add_line in self.adds.lines() {
            lines.push(format!("{}+{}{}", ADD, add_line, NORMAL))
        }
        if (!self.adds.is_empty()) && self.adds.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        return lines;
    }

    /// Returns a vector of ANSI highlighted lines
    #[must_use]
    pub fn format(self) -> Vec<String> {
        if self.adds.is_empty() {
            return self.simple_format();
        }

        if self.removes.is_empty() {
            return self.simple_format();
        }

        if self.adds.len() + self.removes.len() > MAX_HIGHLIGHT_LENGTH {
            return self.simple_format();
        }

        // Find diffs between adds and removals
        let mut highlighted_adds = String::new();
        let mut highlighted_removes = String::new();
        let mut adds_is_inverse = false;
        let mut removes_is_inverse = false;
        let mut adds_highlight_count = 0;
        let mut removes_highlight_count = 0;

        // Tokenize adds and removes before diffing them
        let tokenized_adds = tokenizer::tokenize(self.adds);
        let tokenized_removes = tokenizer::tokenize(self.removes);

        let diff = tokenized_removes.diff(&tokenized_adds);
        match diff {
            edit::Edit::Copy(unchanged) => {
                for token in unchanged {
                    highlighted_adds.push_str(token);
                    highlighted_removes.push_str(token);
                }
            }
            edit::Edit::Change(diff) => {
                diff.into_iter()
                    .map(|edit| {
                        match edit {
                            collection::Edit::Copy(elem) => {
                                if adds_is_inverse {
                                    highlighted_adds.push_str(NOT_INVERSE_VIDEO);
                                }
                                adds_is_inverse = false;

                                if removes_is_inverse {
                                    highlighted_removes.push_str(NOT_INVERSE_VIDEO);
                                }
                                removes_is_inverse = false;

                                highlighted_adds.push_str(elem);
                                highlighted_removes.push_str(elem);
                            }
                            collection::Edit::Insert(elem) => {
                                adds_highlight_count += 1;
                                if !adds_is_inverse {
                                    highlighted_adds.push_str(INVERSE_VIDEO);
                                }
                                adds_is_inverse = true;

                                if elem == &"\n" {
                                    // Make sure the highlighted linefeed is visible
                                    highlighted_adds.push('⏎');

                                    // This will be reset by the linefeed, so we need to re-inverse on the next line
                                    adds_is_inverse = false;
                                }
                                highlighted_adds.push_str(elem);
                            }
                            collection::Edit::Remove(elem) => {
                                removes_highlight_count += 1;
                                if !removes_is_inverse {
                                    highlighted_removes.push_str(INVERSE_VIDEO);
                                }
                                removes_is_inverse = true;

                                if elem == &"\n" {
                                    // Make sure the highlighted linefeed is visible
                                    highlighted_removes.push('⏎');

                                    // This will be reset by the linefeed, so we need to re-inverse on the next line
                                    removes_is_inverse = false;
                                }
                                highlighted_removes.push_str(elem);
                            }
                            collection::Edit::Change(_) => panic!("Not implemented, help!"),
                        };
                    })
                    .for_each(drop);
            }
        }

        let highlight_count = adds_highlight_count + removes_highlight_count;
        let token_count = tokenized_adds.len() + tokenized_removes.len();

        // FIXME: Maybe for this check count how many runs of characters were
        // highlighted rather than how many tokens? Heuristics are difficult...
        if highlight_count <= OK_HIGHLIGHT_COUNT {
            // Few enough highlights, Just do it (tm)
        } else if (100 * highlight_count) / token_count > MAX_HIGHLIGHT_PERCENTAGE {
            return self.simple_format();
        }

        let mut lines: Vec<String> = Vec::new();
        for highlighted_remove in highlighted_removes.lines() {
            lines.push(format!("{}-{}{}", REMOVE, highlighted_remove, NORMAL));
        }
        if (!self.removes.is_empty()) && self.removes.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        for highlighted_add in highlighted_adds.lines() {
            lines.push(format!("{}+{}{}", ADD, highlighted_add, NORMAL));
        }
        if (!self.adds.is_empty()) && self.adds.chars().last().unwrap() != '\n' {
            lines.push(format!(
                "{}{}{}",
                NO_EOF_NEWLINE_COLOR, NO_EOF_NEWLINE_MARKER, NORMAL
            ));
        }

        return lines;
    }
}

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

    #[cfg(test)]
    use pretty_assertions::assert_eq;

    #[test]
    fn test_simple_format_adds_and_removes() {
        let empty: Vec<String> = Vec::new();
        assert_eq!(
            Refiner::create(&"".to_string(), &"".to_string()).simple_format(),
            empty
        );

        // Test adds-only
        assert_eq!(
            Refiner::create(&"a\n".to_string(), &"".to_string()).simple_format(),
            ["".to_string() + ADD + "+a" + NORMAL]
        );
        assert_eq!(
            Refiner::create(&"a\nb\n".to_string(), &"".to_string()).simple_format(),
            [
                "".to_string() + ADD + "+a" + NORMAL,
                "".to_string() + ADD + "+b" + NORMAL,
            ]
        );

        // Test removes-only
        assert_eq!(
            Refiner::create(&"".to_string(), &"a\n".to_string()).simple_format(),
            ["".to_string() + REMOVE + "-a" + NORMAL]
        );
        assert_eq!(
            Refiner::create(&"".to_string(), &"a\nb\n".to_string()).simple_format(),
            [
                "".to_string() + REMOVE + "-a" + NORMAL,
                "".to_string() + REMOVE + "-b" + NORMAL,
            ]
        );
    }

    #[test]
    fn test_quote_change() {
        assert_eq!(
            Refiner::create(&"[quotes]\n".to_string(), &"<quotes>\n".to_string()).format(),
            [
                format!(
                    "{}-{}<{}quotes{}>{}{}",
                    REMOVE,
                    INVERSE_VIDEO,
                    NOT_INVERSE_VIDEO,
                    INVERSE_VIDEO,
                    NOT_INVERSE_VIDEO,
                    NORMAL
                ),
                format!(
                    "{}+{}[{}quotes{}]{}{}",
                    ADD, INVERSE_VIDEO, NOT_INVERSE_VIDEO, INVERSE_VIDEO, NOT_INVERSE_VIDEO, NORMAL
                ),
            ]
        )
    }
}
<|endoftext|>


<commit_before>use gen::GenError;

pub trait SerializeFn<I>: Fn(I) -> Result<I, GenError> {}

impl<I, F:  Fn(I) ->Result<I, GenError>> SerializeFn<I> for F {}

pub fn slice<'a, S: 'a + AsRef<[u8]>>(data: S) -> impl SerializeFn<&'a mut [u8]> {
    let len = data.as_ref().len();

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref());
            Ok(&mut out[len..])
        }
    }
}

pub fn string<'a, S: 'a+AsRef<str>>(data: S) -> impl SerializeFn<&'a mut [u8]> {

    let len = data.as_ref().len();
    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref().as_bytes());
            Ok(&mut out[len..])
        }
    }
}

use std::io::{Cursor, Write};
use std::fmt;
pub fn hex<'a, S: 'a + fmt::UpperHex>(data: S) -> impl SerializeFn<&'a mut [u8]> {

  move |out: &'a mut [u8]| {
    let mut c = Cursor::new(out);
    match write!(&mut c, "{:X}", data) {
      Err(_) => Err(GenError::CustomError(42)),
      Ok(_) => {
        let pos = c.position() as usize;
        let out = c.into_inner();
        Ok(&mut out[pos..])
      }
    }
  }
}

pub fn skip<'a>(len: usize) -> impl SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            Ok(&mut out[len..])
        }
    }
}

pub fn position<'a, F>(f: F) -> impl Fn(&'a mut [u8]) -> Result<(&'a mut [u8], &'a mut [u8]), GenError>
  where F: SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        unsafe {
            let ptr = out.as_mut_ptr();
            let out = f(out)?;
            let len = out.as_ptr() as usize - ptr as usize;

            Ok((std::slice::from_raw_parts_mut(ptr, len), out))
        }
    }
}

fn pair<F, G, I>(first: F, second: G) -> impl SerializeFn<I>
where F: SerializeFn<I>,
      G: SerializeFn<I> {

  move |out: I| {
    let out = first(out)?;
    second(out)
  }
}

fn cond<F, G, I>(condition: bool, f: F) -> impl SerializeFn<I>
where F: SerializeFn<I>, {

  move |out: I| {
    if condition {
      f(out)
    } else {
      Ok(out)
    }
  }
}

pub fn _all<'a, 'b, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(values: Arg) -> impl SerializeFn<I> + 'a
  where G: SerializeFn<I> + 'b {

  move |mut out: I| {
    let it = values.clone().into_iter();

    for v in it {
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn separated_list<'a, 'b, 'c, F, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(sep: F, values: Arg) -> impl SerializeFn<I> + 'a
  where F: SerializeFn<I> + 'b + 'a,
        G: SerializeFn<I> + 'c {

  move |mut out: I| {
    let mut it = values.clone().into_iter();
    match it.next() {
      None => return Ok(out),
      Some(first) => {
        out = first(out)?;
      }
    }

    for v in it {
      out = sep(out)?;
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn be_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 8) & 0xff) as u8;
            out[1] = (i        & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 24) & 0xff) as u8;
            out[1] = ((i >> 16) & 0xff) as u8;
            out[2] = ((i >> 8)  & 0xff) as u8;
            out[3] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 56) & 0xff) as u8;
            out[1] = ((i >> 48) & 0xff) as u8;
            out[2] = ((i >> 40) & 0xff) as u8;
            out[3] = ((i >> 32) & 0xff) as u8;
            out[4] = ((i >> 24) & 0xff) as u8;
            out[5] = ((i >> 16) & 0xff) as u8;
            out[6] = ((i >> 8)  & 0xff) as u8;
            out[7] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i        & 0xff) as u8;
            out[1] = ((i >> 8) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            out[4] = ((i >> 32) & 0xff) as u8;
            out[5] = ((i >> 40) & 0xff) as u8;
            out[6] = ((i >> 48) & 0xff) as u8;
            out[7] = ((i >> 56) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}
//missing combinators:
//or
//empty
//then
//stream
//length_value
//text print
//text upperhex
//text lowerhex
<commit_msg>add missing signed int combinators<commit_after>use gen::GenError;

pub trait SerializeFn<I>: Fn(I) -> Result<I, GenError> {}

impl<I, F:  Fn(I) ->Result<I, GenError>> SerializeFn<I> for F {}

pub fn slice<'a, S: 'a + AsRef<[u8]>>(data: S) -> impl SerializeFn<&'a mut [u8]> {
    let len = data.as_ref().len();

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref());
            Ok(&mut out[len..])
        }
    }
}

pub fn string<'a, S: 'a+AsRef<str>>(data: S) -> impl SerializeFn<&'a mut [u8]> {

    let len = data.as_ref().len();
    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref().as_bytes());
            Ok(&mut out[len..])
        }
    }
}

use std::io::{Cursor, Write};
use std::fmt;
pub fn hex<'a, S: 'a + fmt::UpperHex>(data: S) -> impl SerializeFn<&'a mut [u8]> {

  move |out: &'a mut [u8]| {
    let mut c = Cursor::new(out);
    match write!(&mut c, "{:X}", data) {
      Err(_) => Err(GenError::CustomError(42)),
      Ok(_) => {
        let pos = c.position() as usize;
        let out = c.into_inner();
        Ok(&mut out[pos..])
      }
    }
  }
}

pub fn skip<'a>(len: usize) -> impl SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            Ok(&mut out[len..])
        }
    }
}

pub fn position<'a, F>(f: F) -> impl Fn(&'a mut [u8]) -> Result<(&'a mut [u8], &'a mut [u8]), GenError>
  where F: SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        unsafe {
            let ptr = out.as_mut_ptr();
            let out = f(out)?;
            let len = out.as_ptr() as usize - ptr as usize;

            Ok((std::slice::from_raw_parts_mut(ptr, len), out))
        }
    }
}

fn pair<F, G, I>(first: F, second: G) -> impl SerializeFn<I>
where F: SerializeFn<I>,
      G: SerializeFn<I> {

  move |out: I| {
    let out = first(out)?;
    second(out)
  }
}

fn cond<F, G, I>(condition: bool, f: F) -> impl SerializeFn<I>
where F: SerializeFn<I>, {

  move |out: I| {
    if condition {
      f(out)
    } else {
      Ok(out)
    }
  }
}

pub fn _all<'a, 'b, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(values: Arg) -> impl SerializeFn<I> + 'a
  where G: SerializeFn<I> + 'b {

  move |mut out: I| {
    let it = values.clone().into_iter();

    for v in it {
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn separated_list<'a, 'b, 'c, F, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(sep: F, values: Arg) -> impl SerializeFn<I> + 'a
  where F: SerializeFn<I> + 'b + 'a,
        G: SerializeFn<I> + 'c {

  move |mut out: I| {
    let mut it = values.clone().into_iter();
    match it.next() {
      None => return Ok(out),
      Some(first) => {
        out = first(out)?;
      }
    }

    for v in it {
      out = sep(out)?;
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn be_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 8) & 0xff) as u8;
            out[1] = (i        & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 24) & 0xff) as u8;
            out[1] = ((i >> 16) & 0xff) as u8;
            out[2] = ((i >> 8)  & 0xff) as u8;
            out[3] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 56) & 0xff) as u8;
            out[1] = ((i >> 48) & 0xff) as u8;
            out[2] = ((i >> 40) & 0xff) as u8;
            out[3] = ((i >> 32) & 0xff) as u8;
            out[4] = ((i >> 24) & 0xff) as u8;
            out[5] = ((i >> 16) & 0xff) as u8;
            out[6] = ((i >> 8)  & 0xff) as u8;
            out[7] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_i8<'a>(i: i8) -> impl SerializeFn<&'a mut [u8]> {
    be_u8(i as u8)
}

pub fn be_i16<'a>(i: i16) -> impl SerializeFn<&'a mut [u8]> {
    be_u16(i as u16)
}

pub fn be_i32<'a>(i: i32) -> impl SerializeFn<&'a mut [u8]> {
    be_u32(i as u32)
}

pub fn be_i64<'a>(i: i64) -> impl SerializeFn<&'a mut [u8]> {
    be_u64(i as u64)
}

pub fn le_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i        & 0xff) as u8;
            out[1] = ((i >> 8) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            out[4] = ((i >> 32) & 0xff) as u8;
            out[5] = ((i >> 40) & 0xff) as u8;
            out[6] = ((i >> 48) & 0xff) as u8;
            out[7] = ((i >> 56) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_i8<'a>(i: i8) -> impl SerializeFn<&'a mut [u8]> {
    le_u8(i as u8)
}

pub fn le_i16<'a>(i: i16) -> impl SerializeFn<&'a mut [u8]> {
    le_u16(i as u16)
}

pub fn le_i32<'a>(i: i32) -> impl SerializeFn<&'a mut [u8]> {
    le_u32(i as u32)
}

pub fn le_i64<'a>(i: i64) -> impl SerializeFn<&'a mut [u8]> {
    le_u64(i as u64)
}

//missing combinators:
//or
//empty
//then
//stream
//length_value
//text print
//text upperhex
//text lowerhex
<|endoftext|>


<commit_before>//use serde;
// use serde::de::Deserialize;
// #![feature(custom_derive, plugin)]
// #![plugin(serde_macros)]

extern crate serde_json;
extern crate serde;

use serde_json::Value;

use std::collections;
use std::collections::BTreeMap;
use std::fmt::Debug;

// --------------------------------------------------------
// root obj.  contains controls.
// --------------------------------------------------------

// root is not itself a Control!  although maybe it should be?
#[derive(Debug)]
pub struct Root {
  pub title: String,
  pub rootControl: Box<Control>,
}

pub fn deserializeRoot(data: &Value) -> Option<Box<Root>>
{
  let obj = data.as_object().unwrap();
  let title = obj.get("title").unwrap().as_string().unwrap();

  let rc = obj.get("rootControl").unwrap();

  let rootcontrol = deserializeControl(Vec::new(), rc).unwrap();

  Some(Box::new(Root { title: String::new() + title, rootControl: rootcontrol }))
}

// --------------------------------------------------------
// controls.
// --------------------------------------------------------

pub trait Control : Debug {
  fn controlType(&self) -> &'static str;
  fn controlId(&self) -> &Vec<i32>;
  fn cloneTrol(&self) -> Box<Control>;
  fn subControls(&self) -> Option<&Vec<Box<Control>>>;
}

#[derive(Debug)]
pub struct Slider {
  controlId: Vec<i32>,
  name: String,
  pressed: bool,
  location: f32,
}

impl Control for Slider {
  fn controlType(&self) -> &'static str { "slider" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  // fn cloneTrol(&self) -> Box<Control> { Box::new( Slider { *self } ) }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Slider { controlId: self.controlId.clone(),
              name: self.name.clone(),
              pressed: self.pressed.clone(),
              location: self.location.clone() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { None }
}

#[derive(Debug)]
pub struct Button {
  controlId: Vec<i32>,
  name: String,
  pressed: bool,
}

impl Control for Button {
  fn controlType(&self) -> &'static str { "button" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Button { controlId: self.controlId.clone(),
              name: self.name.clone(),
              pressed: self.pressed.clone() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { None }
}

//#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Sizer {
  controlId: Vec<i32>,
  controls: Vec<Box<Control>>,
}

impl Control for Sizer {
  fn controlType(&self) -> &'static str { "sizer" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Sizer { controlId: self.controlId.clone(),
              controls: Vec::new() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { None }
}

fn deserializeControl(aVId: Vec<i32>, data: &Value) -> Option<Box<Control>>
{
  // what's the type?
  let obj = data.as_object().unwrap();
  let objtype =
    obj.get("type").unwrap().as_string().unwrap();

  match objtype {
    "slider" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      Some(Box::new(Slider { controlId: aVId.clone(), name: String::new() + name, pressed: false, location: 0.5 }))
      },
    "button" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      Some(Box::new(Button { controlId: aVId.clone(), name: String::new() + name, pressed: false }))
      },
    "sizer" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      let controls = obj.get("controls").unwrap().as_array().unwrap();

      let mut controlv = Vec::new();

      for (i, v) in controls.into_iter().enumerate() {
          let mut id = aVId.clone();
          id.push(i as i32);
          let c = deserializeControl(id, v).unwrap();
          controlv.push(c);
          }
      // loop through controls, makin controls.
      Some(Box::new(Sizer { controlId: aVId.clone(), controls: controlv }))
      },
    _ => None,
    }
}

// --------------------------------------------------------
// control state map.  copies all the controls.
// --------------------------------------------------------

pub fn makeControlMap (control: &Control) -> BTreeMap<Vec<i32>,Box<Control>> {
  //.let mut btm = BTreeMap<Vec<i32>,Box<Control>>::new();
  let mut btm = BTreeMap::new();

  makeControlMap_impl(control, btm)
}

fn makeControlMap_impl (control: &Control, mut map: BTreeMap<Vec<i32>,Box<Control>>) -> BTreeMap<Vec<i32>,Box<Control>> {

  map.insert(control.controlId().clone(), control.cloneTrol());

  match control.subControls() {
    Some(trols) => {
      let mut item = trols.into_iter();

      loop {
          match item.next() {
            Some(x) => {
              map = makeControlMap_impl(&**x, map)
              },
            None => { break },
          }
        }
      }
    None => {}
    }

  map
}
<commit_msg>fix controlmap build<commit_after>//use serde;
// use serde::de::Deserialize;
// #![feature(custom_derive, plugin)]
// #![plugin(serde_macros)]

extern crate serde_json;
extern crate serde;

use serde_json::Value;

use std::collections;
use std::collections::BTreeMap;
use std::fmt::Debug;

// --------------------------------------------------------
// root obj.  contains controls.
// --------------------------------------------------------

// root is not itself a Control!  although maybe it should be?
#[derive(Debug)]
pub struct Root {
  pub title: String,
  pub rootControl: Box<Control>,
}

pub fn deserializeRoot(data: &Value) -> Option<Box<Root>>
{
  let obj = data.as_object().unwrap();
  let title = obj.get("title").unwrap().as_string().unwrap();

  let rc = obj.get("rootControl").unwrap();

  let rootcontrol = deserializeControl(Vec::new(), rc).unwrap();

  Some(Box::new(Root { title: String::new() + title, rootControl: rootcontrol }))
}

// --------------------------------------------------------
// controls.
// --------------------------------------------------------

pub trait Control : Debug {
  fn controlType(&self) -> &'static str;
  fn controlId(&self) -> &Vec<i32>;
  fn cloneTrol(&self) -> Box<Control>;
  fn subControls(&self) -> Option<&Vec<Box<Control>>>;
}

#[derive(Debug)]
pub struct Slider {
  controlId: Vec<i32>,
  name: String,
  pressed: bool,
  location: f32,
}

impl Control for Slider {
  fn controlType(&self) -> &'static str { "slider" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  // fn cloneTrol(&self) -> Box<Control> { Box::new( Slider { *self } ) }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Slider { controlId: self.controlId.clone(),
              name: self.name.clone(),
              pressed: self.pressed.clone(),
              location: self.location.clone() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { None }
}

#[derive(Debug)]
pub struct Button {
  controlId: Vec<i32>,
  name: String,
  pressed: bool,
}

impl Control for Button {
  fn controlType(&self) -> &'static str { "button" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Button { controlId: self.controlId.clone(),
              name: self.name.clone(),
              pressed: self.pressed.clone() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { None }
}

//#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Sizer {
  controlId: Vec<i32>,
  controls: Vec<Box<Control>>,
}

impl Control for Sizer {
  fn controlType(&self) -> &'static str { "sizer" }
  fn controlId(&self) -> &Vec<i32> { &self.controlId }
  fn cloneTrol(&self) -> Box<Control> {
    Box::new(
      Sizer { controlId: self.controlId.clone(),
              controls: Vec::new() } ) }
  fn subControls(&self) -> Option<&Vec<Box<Control>>> { Some(&self.controls) }
}

fn deserializeControl(aVId: Vec<i32>, data: &Value) -> Option<Box<Control>>
{
  // what's the type?
  let obj = data.as_object().unwrap();
  let objtype =
    obj.get("type").unwrap().as_string().unwrap();

  match objtype {
    "slider" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      Some(Box::new(Slider { controlId: aVId.clone(), name: String::new() + name, pressed: false, location: 0.5 }))
      },
    "button" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      Some(Box::new(Button { controlId: aVId.clone(), name: String::new() + name, pressed: false }))
      },
    "sizer" => {
      let name = obj.get("name").unwrap().as_string().unwrap();
      let controls = obj.get("controls").unwrap().as_array().unwrap();

      let mut controlv = Vec::new();

      for (i, v) in controls.into_iter().enumerate() {
          let mut id = aVId.clone();
          id.push(i as i32);
          let c = deserializeControl(id, v).unwrap();
          controlv.push(c);
          }
      // loop through controls, makin controls.
      Some(Box::new(Sizer { controlId: aVId.clone(), controls: controlv }))
      },
    _ => None,
    }
}

// --------------------------------------------------------
// control state map.  copies all the controls.
// --------------------------------------------------------

pub fn makeControlMap (control: &Control) -> BTreeMap<Vec<i32>,Box<Control>> {
  //.let mut btm = BTreeMap<Vec<i32>,Box<Control>>::new();
  let mut btm = BTreeMap::new();

  makeControlMap_impl(control, btm)
}

fn makeControlMap_impl (control: &Control, mut map: BTreeMap<Vec<i32>,Box<Control>>) -> BTreeMap<Vec<i32>,Box<Control>> {

  map.insert(control.controlId().clone(), control.cloneTrol());

  match control.subControls() {
    Some(trols) => {
      let mut item = trols.into_iter();

      loop {
          match item.next() {
            Some(x) => {
              map = makeControlMap_impl(&**x, map)
              },
            None => { break },
          }
        }
      }
    None => {}
    }

  map
}
<|endoftext|>


<commit_before>import std::vec;
import std::str;
import std::int;
import std::option;
import std::option::none;
import std::option::some;
import middle::ty;
import middle::ty::*;
import metadata::encoder;
import syntax::print::pp;
import syntax::print::pprust;
import syntax::print::pprust::path_to_str;
import syntax::print::pprust::constr_args_to_str;
import syntax::print::pprust::proto_to_str;
import pp::word;
import pp::eof;
import pp::zerobreak;
import pp::hardbreak;
import ast::ty_mach_to_str;
import syntax::ast;
import middle::ast_map;
import metadata::csearch;

fn mode_str(m: &ty::mode) -> str {
    alt m {
      mo_val. { "" }
      mo_alias(false) { "&" }
      mo_alias(true) { "&mutable " }
    }
}

fn mode_str_1(m: &ty::mode) -> str {
    alt m { mo_val. { "val" } _ { mode_str(m) } }
}

fn fn_ident_to_string(id: ast::node_id, i: &ast::fn_ident) -> str {
    ret alt i { none. { "anon" + int::str(id) } some(s) { s } };
}

fn get_id_ident(cx: &ctxt, id: ast::def_id) -> str {
    if (id.crate != ast::local_crate) {
        str::connect(cx.ext_map.get(id), "::")
    } else {
        alt cx.items.find(id.node) {
          some(ast_map::node_item(it)) { it.ident }
          _ { fail "get_id_ident: can't find item in ast_map" }
        }
    }
}

fn ty_to_str(cx: &ctxt, typ: &t) -> str {
    fn fn_input_to_str(cx: &ctxt, input: &{mode: middle::ty::mode, ty: t}) ->
       str {
        let s = mode_str(input.mode);
        ret s + ty_to_str(cx, input.ty);
    }
    fn fn_to_str(cx: &ctxt, proto: ast::proto, ident: option::t<ast::ident>,
                 inputs: &[arg], output: t, cf: ast::controlflow,
                 constrs: &[@constr]) -> str {
        let s = proto_to_str(proto);
        alt ident { some(i) { s += " "; s += i; } _ { } }
        s += "(";
        let strs = ~[];
        for a: arg in inputs { strs += ~[fn_input_to_str(cx, a)]; }
        s += str::connect(strs, ", ");
        s += ")";
        if struct(cx, output) != ty_nil {
            alt cf {
              ast::noreturn. { s += " -> !"; }
              ast::return. { s += " -> " + ty_to_str(cx, output); }
            }
        }
        s += constrs_str(constrs);
        ret s;
    }
    fn method_to_str(cx: &ctxt, m: &method) -> str {
        ret fn_to_str(cx, m.proto, some::<ast::ident>(m.ident), m.inputs,
                      m.output, m.cf, m.constrs) + ";";
    }
    fn field_to_str(cx: &ctxt, f: &field) -> str {
        ret f.ident + ": " + mt_to_str(cx, f.mt);
    }
    fn mt_to_str(cx: &ctxt, m: &mt) -> str {
        let mstr;
        alt m.mut {
          ast::mut. { mstr = "mutable "; }
          ast::imm. { mstr = ""; }
          ast::maybe_mut. { mstr = "mutable? "; }
        }
        ret mstr + ty_to_str(cx, m.ty);
    }
    alt cname(cx, typ) { some(cs) { ret cs; } _ { } }
    let s = "";
    alt struct(cx, typ) {
      ty_native(_) { s += "native"; }
      ty_nil. { s += "()"; }
      ty_bot. { s += "_|_"; }
      ty_bool. { s += "bool"; }
      ty_int. { s += "int"; }
      ty_float. { s += "float"; }
      ty_uint. { s += "uint"; }
      ty_machine(tm) { s += ty_mach_to_str(tm); }
      ty_char. { s += "char"; }
      ty_str. { s += "str"; }
      ty_istr. { s += "istr"; }
      ty_box(tm) { s += "@" + mt_to_str(cx, tm); }
      ty_uniq(t) { s += "~" + ty_to_str(cx, t); }
      ty_vec(tm) { s += "[" + mt_to_str(cx, tm) + "]"; }
      ty_type. { s += "type"; }
      ty_rec(elems) {
        let strs: [str] = ~[];
        for fld: field in elems { strs += ~[field_to_str(cx, fld)]; }
        s += "{" + str::connect(strs, ",") + "}";
      }
      ty_tup(elems) {
        let strs = ~[];
        for elem in elems { strs += ~[ty_to_str(cx, elem)]; }
        s += "(" + str::connect(strs, ",") + ")";
      }
      ty_tag(id, tps) {
        s += get_id_ident(cx, id);
        if vec::len::<t>(tps) > 0u {
            let strs: [str] = ~[];
            for typ: t in tps { strs += ~[ty_to_str(cx, typ)]; }
            s += "[" + str::connect(strs, ",") + "]";
        }
      }
      ty_fn(proto, inputs, output, cf, constrs) {
        s += fn_to_str(cx, proto, none, inputs, output, cf, constrs);
      }
      ty_native_fn(_, inputs, output) {
        s +=
            fn_to_str(cx, ast::proto_fn, none, inputs, output, ast::return,
                      ~[]);
      }
      ty_obj(meths) {
        let strs = ~[];
        for m: method in meths { strs += ~[method_to_str(cx, m)]; }
        s += "obj {\n\t" + str::connect(strs, "\n\t") + "\n}";
      }
      ty_res(id, _, _) {
        s += get_id_ident(cx, id);
      }
      ty_var(v) { s += "<T" + int::str(v) + ">"; }
      ty_param(id,_) {
        s += "'" + str::unsafe_from_bytes(~[('a' as u8) + (id as u8)]);
      }
      _ { s += ty_to_short_str(cx, typ); }
    }
    ret s;
}

fn ty_to_short_str(cx: &ctxt, typ: t) -> str {
    let s = encoder::encoded_ty(cx, typ);
    if str::byte_len(s) >= 32u { s = str::substr(s, 0u, 32u); }
    ret s;
}

fn constr_to_str(c: &@constr) -> str {
    ret path_to_str(c.node.path) +
            pprust::constr_args_to_str(pprust::uint_to_str, c.node.args);
}

fn constrs_str(constrs: &[@constr]) -> str {
    let s = "";
    let colon = true;
    for c: @constr in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
        s += constr_to_str(c);
    }
    ret s;
}

fn ty_constr_to_str<Q>(c: &@ast::spanned<ast::constr_general_<ast::path, Q>>)
   -> str {
    ret path_to_str(c.node.path) +
            constr_args_to_str::<ast::path>(path_to_str, c.node.args);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Some cleanup in ty_to_str.<commit_after>import std::vec;
import std::str;
import std::int;
import std::option;
import std::option::none;
import std::option::some;
import middle::ty;
import middle::ty::*;
import metadata::encoder;
import syntax::print::pp;
import syntax::print::pprust;
import syntax::print::pprust::path_to_str;
import syntax::print::pprust::constr_args_to_str;
import syntax::print::pprust::proto_to_str;
import pp::word;
import pp::eof;
import pp::zerobreak;
import pp::hardbreak;
import ast::ty_mach_to_str;
import syntax::ast;
import middle::ast_map;
import metadata::csearch;

fn mode_str(m: &ty::mode) -> str {
    alt m {
      mo_val. { "" }
      mo_alias(false) { "&" }
      mo_alias(true) { "&mutable " }
    }
}

fn mode_str_1(m: &ty::mode) -> str {
    alt m { mo_val. { "val" } _ { mode_str(m) } }
}

fn fn_ident_to_string(id: ast::node_id, i: &ast::fn_ident) -> str {
    ret alt i { none. { "anon" + int::str(id) } some(s) { s } };
}

fn get_id_ident(cx: &ctxt, id: ast::def_id) -> str {
    if (id.crate != ast::local_crate) {
        str::connect(cx.ext_map.get(id), "::")
    } else {
        alt cx.items.find(id.node) {
          some(ast_map::node_item(it)) { it.ident }
          _ { fail "get_id_ident: can't find item in ast_map" }
        }
    }
}

fn ty_to_str(cx: &ctxt, typ: &t) -> str {
    fn fn_input_to_str(cx: &ctxt, input: &{mode: middle::ty::mode, ty: t}) ->
       str {
        let s = mode_str(input.mode);
        ret s + ty_to_str(cx, input.ty);
    }
    fn fn_to_str(cx: &ctxt, proto: ast::proto, ident: option::t<ast::ident>,
                 inputs: &[arg], output: t, cf: ast::controlflow,
                 constrs: &[@constr]) -> str {
        let s = proto_to_str(proto);
        alt ident { some(i) { s += " "; s += i; } _ { } }
        s += "(";
        let strs = ~[];
        for a: arg in inputs { strs += ~[fn_input_to_str(cx, a)]; }
        s += str::connect(strs, ", ");
        s += ")";
        if struct(cx, output) != ty_nil {
            alt cf {
              ast::noreturn. { s += " -> !"; }
              ast::return. { s += " -> " + ty_to_str(cx, output); }
            }
        }
        s += constrs_str(constrs);
        ret s;
    }
    fn method_to_str(cx: &ctxt, m: &method) -> str {
        ret fn_to_str(cx, m.proto, some::<ast::ident>(m.ident), m.inputs,
                      m.output, m.cf, m.constrs) + ";";
    }
    fn field_to_str(cx: &ctxt, f: &field) -> str {
        ret f.ident + ": " + mt_to_str(cx, f.mt);
    }
    fn mt_to_str(cx: &ctxt, m: &mt) -> str {
        let mstr;
        alt m.mut {
          ast::mut. { mstr = "mutable "; }
          ast::imm. { mstr = ""; }
          ast::maybe_mut. { mstr = "mutable? "; }
        }
        ret mstr + ty_to_str(cx, m.ty);
    }
    alt cname(cx, typ) { some(cs) { ret cs; } _ { } }
    ret alt struct(cx, typ) {
      ty_native(_) { "native" }
      ty_nil. { "()" }
      ty_bot. { "_|_" }
      ty_bool. { "bool" }
      ty_int. { "int" }
      ty_float. { "float" }
      ty_uint. { "uint" }
      ty_machine(tm) { ty_mach_to_str(tm) }
      ty_char. { "char" }
      ty_str. { "str" }
      ty_istr. { "istr" }
      ty_box(tm) { "@" + mt_to_str(cx, tm) }
      ty_uniq(t) { "~" + ty_to_str(cx, t) }
      ty_vec(tm) { "[" + mt_to_str(cx, tm) + "]" }
      ty_type. { "type" }
      ty_rec(elems) {
        let strs: [str] = ~[];
        for fld: field in elems { strs += ~[field_to_str(cx, fld)]; }
        "{" + str::connect(strs, ",") + "}"
      }
      ty_tup(elems) {
        let strs = ~[];
        for elem in elems { strs += ~[ty_to_str(cx, elem)]; }
        "(" + str::connect(strs, ",") + ")"
      }
      ty_tag(id, tps) {
        let s = get_id_ident(cx, id);
        if vec::len::<t>(tps) > 0u {
            let strs: [str] = ~[];
            for typ: t in tps { strs += ~[ty_to_str(cx, typ)]; }
            s += "[" + str::connect(strs, ",") + "]";
        }
        s
      }
      ty_fn(proto, inputs, output, cf, constrs) {
        fn_to_str(cx, proto, none, inputs, output, cf, constrs)
      }
      ty_native_fn(_, inputs, output) {
        fn_to_str(cx, ast::proto_fn, none, inputs, output, ast::return, ~[])
      }
      ty_obj(meths) {
        let strs = ~[];
        for m: method in meths { strs += ~[method_to_str(cx, m)]; }
        "obj {\n\t" + str::connect(strs, "\n\t") + "\n}"
      }
      ty_res(id, _, _) {
        get_id_ident(cx, id)
      }
      ty_var(v) { "<T" + int::str(v) + ">" }
      ty_param(id,_) {
        "'" + str::unsafe_from_bytes(~[('a' as u8) + (id as u8)])
      }
      _ { ty_to_short_str(cx, typ) }
    }
}

fn ty_to_short_str(cx: &ctxt, typ: t) -> str {
    let s = encoder::encoded_ty(cx, typ);
    if str::byte_len(s) >= 32u { s = str::substr(s, 0u, 32u); }
    ret s;
}

fn constr_to_str(c: &@constr) -> str {
    ret path_to_str(c.node.path) +
            pprust::constr_args_to_str(pprust::uint_to_str, c.node.args);
}

fn constrs_str(constrs: &[@constr]) -> str {
    let s = "";
    let colon = true;
    for c: @constr in constrs {
        if colon { s += " : "; colon = false; } else { s += ", "; }
        s += constr_to_str(c);
    }
    ret s;
}

fn ty_constr_to_str<Q>(c: &@ast::spanned<ast::constr_general_<ast::path, Q>>)
   -> str {
    ret path_to_str(c.node.path) +
            constr_args_to_str::<ast::path>(path_to_str, c.node.args);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use ::log::{LogRecord, LogMetadata};

///The Logger used by Netherrack
///
///For now, it simply logs to standard output. In future versions, it will be extended
pub struct NetherrackLogger;

impl ::log::Log for NetherrackLogger {

    ///Checks to see if a LogRecord can be accepted based on LogMetadata
    #[allow(unused_variables)]
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        true //Before 0.1, change dynamically based on if we're a prerelease version
    }

    ///Attempts to log a LogRecord
    fn log(&self, record: &LogRecord) {
        //First, check to see if logging is enabled for the metadata
        if self.enabled(record.metadata()) {
            println!("[{}] {}: {}", record.level(), record.target(), record.args());
        }
    }
}<commit_msg>Add a newline at the end of logger.rs<commit_after>use ::log::{LogRecord, LogMetadata};

///The Logger used by Netherrack
///
///For now, it simply logs to standard output. In future versions, it will be extended
pub struct NetherrackLogger;

impl ::log::Log for NetherrackLogger {

    ///Checks to see if a LogRecord can be accepted based on LogMetadata
    #[allow(unused_variables)]
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        true //Before 0.1, change dynamically based on if we're a prerelease version
    }

    ///Attempts to log a LogRecord
    fn log(&self, record: &LogRecord) {
        //First, check to see if logging is enabled for the metadata
        if self.enabled(record.metadata()) {
            println!("[{}] {}: {}", record.level(), record.target(), record.args());
        }
    }
}
<|endoftext|>


<commit_before>use core::codepointinfo::CodepointInfo;

// the screen is composed of lines
#[derive(Debug)]
pub struct Screen {
    pub line: Vec<Line>,
    pub used: usize,
    pub width: usize,
    pub height: usize,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line: line,
            used: 0,
            width: width,
            height: height,
        }
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.used == self.height {
            return (false, self.used);
        }
        if self.line[self.used].used >= self.line[self.used].width {
            self.used += 1;
        }
        if self.used >= self.height {
            return (false, self.used);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.used];
        let (ok, _) = line.push(cpi);

        if ok == true {
            if cp == '\n' || cp == '\r' {
                self.used += 1;
            }
        }
        (ok, self.used)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.used = 0;
    }

    pub fn get_mut_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.height {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_line(&self, index: usize) -> Option<&Line> {
        if index < self.height {
            Some(&self.line[index])
        } else {
            None
        }
    }
}

// a line is composed of codepoints
#[derive(Debug)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub used: usize,
    pub width: usize,
}

impl Line {
    fn new(columns: usize) -> Line {

        let mut chars = Vec::with_capacity(columns);
        for _ in 0..columns {
            chars.push(CodepointInfo {
                           cp: ' ',
                           displayed_cp: ' ',
                           offset: 0,
                           is_selected: false,
                       });
        }

        Line {
            chars: chars,
            used: 0,
            width: columns,
        }
    }

    fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.used < self.width {
            self.chars[self.used] = cpi;
            self.used += 1;
            (true, self.used)
        } else {
            (false, self.used)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w].cp = ' ';
            self.chars[w].displayed_cp = ' ';
            self.chars[w].offset = 0;
        }
        self.used = 0;
    }

    pub fn get_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.width {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_mut_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.width {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }
}
<commit_msg>add fn Screen::resize(usize, usize)<commit_after>use core::codepointinfo::CodepointInfo;

// the screen is composed of lines
#[derive(Debug, Clone)]
pub struct Screen {
    pub line: Vec<Line>,
    pub used: usize,
    pub width: usize,
    pub height: usize,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line: line,
            used: 0,
            width: width,
            height: height,
        }
    }

    pub fn resize(&mut self, width: usize, height: usize) {

        self.line.resize(height, Line::new(width));
        for i in 0..height {
            self.line[i].chars.resize(width, CodepointInfo::new());
            self.line[i].width = width;
            self.line[i].used = 0;
        }
        self.width = width;
        self.height = height;
        self.used = 0;
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.used == self.height {
            return (false, self.used);
        }
        if self.line[self.used].used >= self.line[self.used].width {
            self.used += 1;
        }
        if self.used >= self.height {
            return (false, self.used);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.used];
        let (ok, _) = line.push(cpi);

        if ok == true {
            if cp == '\n' || cp == '\r' {
                self.used += 1;
            }
        }
        (ok, self.used)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.used = 0;
    }

    pub fn get_mut_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.height {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_line(&self, index: usize) -> Option<&Line> {
        if index < self.height {
            Some(&self.line[index])
        } else {
            None
        }
    }
}

// a line is composed of codepoints
#[derive(Debug, Clone)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub used: usize,
    pub width: usize,
}

impl Line {
    fn new(columns: usize) -> Line {

        let mut chars = Vec::with_capacity(columns);
        for _ in 0..columns {
            chars.push(CodepointInfo::new());
        }

        Line {
            chars: chars,
            used: 0,
            width: columns,
        }
    }

    fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.used < self.width {
            self.chars[self.used] = cpi;
            self.used += 1;
            (true, self.used)
        } else {
            (false, self.used)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w].cp = ' ';
            self.chars[w].displayed_cp = ' ';
            self.chars[w].offset = 0;
        }
        self.used = 0;
    }

    pub fn get_cpi(&self, index: usize) -> Option<&CodepointInfo> {
        if index < self.width {
            Some(&self.chars[index])
        } else {
            None
        }
    }

    pub fn get_mut_cpi(&mut self, index: usize) -> Option<&mut CodepointInfo> {
        if index < self.width {
            Some(&mut self.chars[index])
        } else {
            None
        }
    }
}

#[test]
fn test_screen() {

    let mut scr = Screen::new(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].chars.len());

    scr.resize(800, 600);
    assert_eq!(800, scr.width);
    assert_eq!(600, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].chars.len());

    scr.resize(1024, 768);
    assert_eq!(1024, scr.width);
    assert_eq!(768, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].chars.len());

    scr.resize(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].chars.len());
}
<|endoftext|>