<commit_before>//! Target information

use super::prelude::*;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    // Disassembler?

    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeSystemZDisassembler();

    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeHexagonAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeHexagonDisassembler();

    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeCppBackendTargetInfo();
    pub fn LLVMInitializeCppBackendTarget();
    pub fn LLVMInitializeCppBackendTargetMC();
    // AsmPrinter?
    // AsmParser?

    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeMSP430AsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeXCoreAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeXCoreDisassembler();

    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeMipsDisassembler();

    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeAArch64Disassembler();

    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializeARMDisassembler();

    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializePowerPCDisassembler();

    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeSparcDisassembler();

    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeX86Disassembler();

    pub fn LLVMInitializeBPFTargetInfo();
    pub fn LLVMInitializeBPFTarget();
    pub fn LLVMInitializeBPFTargetMC();
    pub fn LLVMInitializeBPFAsmPrinter();
    // No AsmParser
    pub fn LLVMInitializeBPFDisassembler();

    pub fn LLVMInitializeLanaiTargetInfo();
    pub fn LLVMInitializeLanaiTarget();
    pub fn LLVMInitializeLanaiTargetMC();
    pub fn LLVMInitializeLanaiAsmPrinter();
    pub fn LLVMInitializeLanaiAsmParser();
    pub fn LLVMInitializeLanaiDisassembler();

    pub fn LLVMInitializeRISCVTargetInfo();
    pub fn LLVMInitializeRISCVTarget();
    pub fn LLVMInitializeRISCVTargetMC();
    // No AsmPrinter
    // No AsmParser
    // No Disassembler

    pub fn LLVMInitializeWebAssemblyTargetInfo();
    pub fn LLVMInitializeWebAssemblyTarget();
    pub fn LLVMInitializeWebAssemblyTargetMC();
    pub fn LLVMInitializeWebAssemblyAsmPrinter();
    pub fn LLVMInitializeWebAssemblyAsmParser();
    pub fn LLVMInitializeWebAssemblyDisassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<commit_msg>Remove Cpp backend.<commit_after>//! Target information

use super::prelude::*;

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LLVMByteOrdering {
    LLVMBigEndian = 0,
    LLVMLittleEndian = 1,
}

pub enum LLVMOpaqueTargetData {}
pub type LLVMTargetDataRef = *mut LLVMOpaqueTargetData;

pub enum LLVMOpaqueTargetLibraryInfotData {}
pub type LLVMTargetLibraryInfoRef = *mut LLVMOpaqueTargetLibraryInfotData;

extern "C" {
    pub fn LLVMInitializeAMDGPUTargetInfo();
    pub fn LLVMInitializeAMDGPUTarget();
    pub fn LLVMInitializeAMDGPUTargetMC();
    pub fn LLVMInitializeAMDGPUAsmPrinter();
    pub fn LLVMInitializeAMDGPUAsmParser();
    // Disassembler?

    pub fn LLVMInitializeSystemZTargetInfo();
    pub fn LLVMInitializeSystemZTarget();
    pub fn LLVMInitializeSystemZTargetMC();
    pub fn LLVMInitializeSystemZAsmPrinter();
    pub fn LLVMInitializeSystemZAsmParser();
    pub fn LLVMInitializeSystemZDisassembler();

    pub fn LLVMInitializeHexagonTargetInfo();
    pub fn LLVMInitializeHexagonTarget();
    pub fn LLVMInitializeHexagonTargetMC();
    pub fn LLVMInitializeHexagonAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeHexagonDisassembler();

    pub fn LLVMInitializeNVPTXTargetInfo();
    pub fn LLVMInitializeNVPTXTarget();
    pub fn LLVMInitializeNVPTXTargetMC();
    pub fn LLVMInitializeNVPTXAsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeMSP430TargetInfo();
    pub fn LLVMInitializeMSP430Target();
    pub fn LLVMInitializeMSP430TargetMC();
    pub fn LLVMInitializeMSP430AsmPrinter();
    // AsmParser?

    pub fn LLVMInitializeXCoreTargetInfo();
    pub fn LLVMInitializeXCoreTarget();
    pub fn LLVMInitializeXCoreTargetMC();
    pub fn LLVMInitializeXCoreAsmPrinter();
    // AsmParser?
    pub fn LLVMInitializeXCoreDisassembler();

    pub fn LLVMInitializeMipsTargetInfo();
    pub fn LLVMInitializeMipsTarget();
    pub fn LLVMInitializeMipsTargetMC();
    pub fn LLVMInitializeMipsAsmPrinter();
    pub fn LLVMInitializeMipsAsmParser();
    pub fn LLVMInitializeMipsDisassembler();

    pub fn LLVMInitializeAArch64TargetInfo();
    pub fn LLVMInitializeAArch64Target();
    pub fn LLVMInitializeAArch64TargetMC();
    pub fn LLVMInitializeAArch64AsmPrinter();
    pub fn LLVMInitializeAArch64AsmParser();
    pub fn LLVMInitializeAArch64Disassembler();

    pub fn LLVMInitializeARMTargetInfo();
    pub fn LLVMInitializeARMTarget();
    pub fn LLVMInitializeARMTargetMC();
    pub fn LLVMInitializeARMAsmPrinter();
    pub fn LLVMInitializeARMAsmParser();
    pub fn LLVMInitializeARMDisassembler();

    pub fn LLVMInitializePowerPCTargetInfo();
    pub fn LLVMInitializePowerPCTarget();
    pub fn LLVMInitializePowerPCTargetMC();
    pub fn LLVMInitializePowerPCAsmPrinter();
    pub fn LLVMInitializePowerPCAsmParser();
    pub fn LLVMInitializePowerPCDisassembler();

    pub fn LLVMInitializeSparcTargetInfo();
    pub fn LLVMInitializeSparcTarget();
    pub fn LLVMInitializeSparcTargetMC();
    pub fn LLVMInitializeSparcAsmPrinter();
    pub fn LLVMInitializeSparcAsmParser();
    pub fn LLVMInitializeSparcDisassembler();

    pub fn LLVMInitializeX86TargetInfo();
    pub fn LLVMInitializeX86Target();
    pub fn LLVMInitializeX86TargetMC();
    pub fn LLVMInitializeX86AsmPrinter();
    pub fn LLVMInitializeX86AsmParser();
    pub fn LLVMInitializeX86Disassembler();

    pub fn LLVMInitializeBPFTargetInfo();
    pub fn LLVMInitializeBPFTarget();
    pub fn LLVMInitializeBPFTargetMC();
    pub fn LLVMInitializeBPFAsmPrinter();
    // No AsmParser
    pub fn LLVMInitializeBPFDisassembler();

    pub fn LLVMInitializeLanaiTargetInfo();
    pub fn LLVMInitializeLanaiTarget();
    pub fn LLVMInitializeLanaiTargetMC();
    pub fn LLVMInitializeLanaiAsmPrinter();
    pub fn LLVMInitializeLanaiAsmParser();
    pub fn LLVMInitializeLanaiDisassembler();

    pub fn LLVMInitializeRISCVTargetInfo();
    pub fn LLVMInitializeRISCVTarget();
    pub fn LLVMInitializeRISCVTargetMC();
    // No AsmPrinter
    // No AsmParser
    // No Disassembler

    pub fn LLVMInitializeWebAssemblyTargetInfo();
    pub fn LLVMInitializeWebAssemblyTarget();
    pub fn LLVMInitializeWebAssemblyTargetMC();
    pub fn LLVMInitializeWebAssemblyAsmPrinter();
    pub fn LLVMInitializeWebAssemblyAsmParser();
    pub fn LLVMInitializeWebAssemblyDisassembler();
}

extern "C" {
    /// Get the data layout for a module.
    pub fn LLVMGetModuleDataLayout(M: LLVMModuleRef) -> LLVMTargetDataRef;
    /// Set the data layout for a module.
    pub fn LLVMSetModuleDataLayout(M: LLVMModuleRef, R: LLVMTargetDataRef);
    /// Create target data from a target layout string.
    pub fn LLVMCreateTargetData(StringRep: *const ::libc::c_char) -> LLVMTargetDataRef;
    pub fn LLVMAddTargetLibraryInfo(TLI: LLVMTargetLibraryInfoRef, PM: LLVMPassManagerRef);
    pub fn LLVMCopyStringRepOfTargetData(TD: LLVMTargetDataRef) -> *mut ::libc::c_char;
    pub fn LLVMByteOrder(TD: LLVMTargetDataRef) -> LLVMByteOrdering;
    pub fn LLVMPointerSize(TD: LLVMTargetDataRef) -> ::libc::c_uint;
    pub fn LLVMPointerSizeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> ::libc::c_uint;
    pub fn LLVMIntPtrType(TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForAS(TD: LLVMTargetDataRef, AS: ::libc::c_uint) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeInContext(C: LLVMContextRef, TD: LLVMTargetDataRef) -> LLVMTypeRef;
    pub fn LLVMIntPtrTypeForASInContext(C: LLVMContextRef,
                                        TD: LLVMTargetDataRef,
                                        AS: ::libc::c_uint)
                                        -> LLVMTypeRef;
    pub fn LLVMSizeOfTypeInBits(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMStoreSizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABISizeOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_ulonglong;
    pub fn LLVMABIAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMCallFrameAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfType(TD: LLVMTargetDataRef, Ty: LLVMTypeRef) -> ::libc::c_uint;
    pub fn LLVMPreferredAlignmentOfGlobal(TD: LLVMTargetDataRef,
                                          GlobalVar: LLVMValueRef)
                                          -> ::libc::c_uint;
    pub fn LLVMElementAtOffset(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Offset: ::libc::c_ulonglong)
                               -> ::libc::c_uint;
    pub fn LLVMOffsetOfElement(TD: LLVMTargetDataRef,
                               StructTy: LLVMTypeRef,
                               Element: ::libc::c_uint)
                               -> ::libc::c_ulonglong;
    pub fn LLVMDisposeTargetData(TD: LLVMTargetDataRef);
}

// Functions from our target wrappers, since the C interface defines them with
// macros (wrappers/target.c).
extern "C" {
    pub fn LLVM_InitializeAllTargetInfos();
    pub fn LLVM_InitializeAllTargets();
    pub fn LLVM_InitializeAllTargetMCs();
    pub fn LLVM_InitializeAllAsmPrinters();
    pub fn LLVM_InitializeAllAsmParsers();
    pub fn LLVM_InitializeAllDisassemblers();

    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeTarget() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmParser() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeAsmPrinter() -> LLVMBool;
    /// Returns 1 on failure.
    pub fn LLVM_InitializeNativeDisassembler() -> LLVMBool;
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::collections::btree_map::Iter;
use std::path::{PathBuf, Path};
use std::fmt::{Display, Formatter, Result};
use std::ops::Add;
use std::cmp::{Ord, Ordering};

/// Used to track the state of logical conditions
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct LogicState {
    /// Whether the condition has been observed as true
    pub been_true: bool,
    /// Whether the condition has been observed as false
    pub been_false: bool,
}

impl<'a> Add for &'a LogicState {
    type Output = LogicState;

    fn add(self, other: &'a LogicState) -> LogicState {
        LogicState {
            been_true: self.been_true | other.been_true,
            been_false: self.been_false | other.been_false,
        }
    }
}

/// Shows what type of coverage data is being collected by a given trace
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub enum CoverageStat {
    /// Line coverage data (whether line has been hit)
    Line(u64),
    /// Branch coverage data (whether branch has been true and false
    Branch(LogicState),
    /// Condition coverage data (each boolean subcondition true and false)
    Condition(Vec<LogicState>),
}

impl Add for CoverageStat {
    type Output = CoverageStat;

    fn add(self, other: CoverageStat) -> CoverageStat {
        match (self, other) {
            (CoverageStat::Line(ref l), CoverageStat::Line(ref r)) => {
                CoverageStat::Line(l+r)
            },
            (CoverageStat::Branch(ref l), CoverageStat::Branch(ref r)) => {
                CoverageStat::Branch(l + r)
            },
            t @ _ => t.0,
        }
    }
}

impl Display for CoverageStat {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self {
            &CoverageStat::Line(x) => {
                write!(f, "hits: {}", x)
            },
            _ => write!(f, ""),
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    /// Line the trace is on in the file
    pub line: u64,
    /// Optional address showing location in the test artefact
    pub address: Option<u64>,
    /// Length of the instruction (useful to get entire condition/branch)
    pub length: usize,
    /// Coverage stats
    pub stats: CoverageStat,
}

/// Implemented to allow Traces to be sorted by line number
impl Ord for Trace {
    fn cmp(&self, other: &Trace) -> Ordering {
        self.line.cmp(&other.line)
    }
    fn max(self, other: Trace) -> Trace {
        if self.line > other.line {
            self
        } else {
            other
        }
    }
    fn min(self, other: Trace) -> Trace {
        if self.line < other.line {
            self
        } else {
            other
        }
    }
}

/// Stores all the program traces mapped to files and provides an interface to
/// add, query and change traces.
#[derive(Debug)]
pub struct TraceMap {
    /// Traces in the program mapped to the given file
    traces: BTreeMap<PathBuf, Vec<Trace>>,
}

impl TraceMap {
    /// Create a new TraceMap
    pub fn new() -> TraceMap {
        TraceMap {
            traces: BTreeMap::new(),
        }
    }

    /// Returns true if there are no traces
    pub fn is_empty(&self) -> bool {
        self.traces.is_empty()
    }

    /// Provides an interator to the underlying map of PathBufs to Vec<Trace>
    pub fn iter(&self) -> Iter<PathBuf, Vec<Trace>> {
        self.traces.iter()
    }

    /// Merges the results of one tracemap into the current one.
    /// This adds records which are missing and adds the statistics gathered to
    /// existing records
    pub fn merge(&mut self, other: &TraceMap) {
        for (k,  values) in other.iter() {
            if !self.traces.contains_key(k) {
                self.traces.insert(k.to_path_buf(), values.to_vec());
            } else {
                let mut existing = self.traces.get_mut(k).unwrap();
                for ref v in values.iter() {
                    let mut added = false;
                    if let Some(ref mut t) = existing.iter_mut()
                                                     .find(|ref x| x.line == v.line && x.address == v.address) {
                        t.stats = t.stats.clone() + v.stats.clone();
                        added = true;
                    }
                    if !added {
                        existing.push((*v).clone());
                        existing.sort_unstable();
                    }
                }
            }
        }
    }

    /// This will collapse duplicate Traces into a single trace. Warning this
    /// will lose the addresses of the duplicate traces but increment the results
    /// should be called only if you don't need those addresses from then on
    /// TODO possibly not the cleanest solution
    pub fn dedup(&mut self) {
        for (_, values) in self.traces.iter_mut() {
            // Map of lines and stats, merge duplicated stats here
            let mut lines: HashMap<u64, CoverageStat> = HashMap::new();
            // Duplicated traces need cleaning up. Maintain a list of them!
            let mut dirty: Vec<u64> = Vec::new();
            for v in values.iter() {
                if lines.contains_key(&v.line) {
                    dirty.push(v.line);
                    let s = lines.get(&v.line).unwrap().clone() + v.stats.clone();
                    lines.insert(v.line, s);
                } else {
                    lines.insert(v.line, v.stats.clone());
                }
            }
            for d in dirty.iter() {
                let mut first = true;
                values.retain(|x| {
                    let res = x.line != *d;
                    if !res {
                        first = false;
                        true
                    } else {
                        res
                    }
                });
                if let Some(new_stat) = lines.remove(&d) {
                    if let Some(ref mut t) = values.iter_mut().find(|x| x.line==*d) {
                        t.stats = new_stat;
                    }
                }
            }
        }
    }

    /// Add a trace to the tracemap for the given file
    pub fn add_trace(&mut self, file: &Path, trace: Trace) {
        if self.traces.contains_key(file) {
            if let Some(trace_vec) = self.traces.get_mut(file) {
                trace_vec.push(trace);
                trace_vec.sort_unstable();
            }
        } else {
            self.traces.insert(file.to_path_buf(), vec![trace]);
        }
    }

    /// Gets an immutable reference to a trace from an address. Returns None if
    /// there is no trace at that address
    pub fn get_trace(&self, address: u64) -> Option<&Trace> {
        self.all_traces()
            .iter()
            .find(|x| x.address == Some(address))
            .map(|x| *x)
    }

    /// Gets a mutable reference to a trace at a given address
    /// Returns None if there is no trace at that address
    pub fn get_trace_mut(&mut self, address: u64) -> Option<&mut Trace> {
        for val in self.all_traces_mut() {
            if val.address == Some(address) {
                return Some(val);
            }
        }
        None
    }

    /// Returns true if the location described by file and line number is present
    /// in the tracemap
    pub fn contains_location(&self, file: &Path, line: u64) -> bool {
        match self.traces.get(file) {
            Some(traces) => traces.iter().any(|x| x.line == line),
            None => false,
        }
    }

    /// Gets all traces below a certain path
    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }

    /// Gets all traces
    pub fn all_traces(&self) -> Vec<&Trace> {
        self.traces.values().flat_map(|ref x| x.iter()).collect()
    }

    /// Gets a vector of all the traces to mutate
    fn all_traces_mut(&mut self) -> Vec<&mut Trace> {
        self.traces.values_mut().flat_map(|x| x.iter_mut()).collect()
    }

    pub fn files(&self) -> Vec<&PathBuf> {
        self.traces.keys().collect()
    }

    pub fn coverable_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    pub fn covered_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Give the total amount of coverable points in the code. This will vary
    /// based on the statistics available for line coverage it will be total
    /// line whereas for condition or decision it will count the number of
    /// conditions available
    pub fn total_coverable(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    /// From all the coverable data return the amount covered
    pub fn total_covered(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Returns coverage percentage ranging from 0.0-1.0
    pub fn coverage_percentage(&self) -> f64 {
        (self.total_covered() as f64) / (self.total_coverable() as f64)
    }

}

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

    #[test]
    fn stat_addition() {
        let x = CoverageStat::Line(0);
        let y = CoverageStat::Line(5);
        let z = CoverageStat::Line(7);
        let xy = x.clone() + y.clone();
        let yx = y.clone() + x.clone();
        let yy = y.clone() + y.clone();
        let zy = z.clone() + y.clone();
        assert_eq!(&xy, &CoverageStat::Line(5));
        assert_eq!(&yx, &xy);
        assert_eq!(&yy, &CoverageStat::Line(10));
        assert_eq!(&zy, &CoverageStat::Line(12));

        let tf = LogicState{been_true:true, been_false:true};
        let t = LogicState{been_true:true, been_false:false};
        let f = LogicState{been_true:false, been_false:true};
        let n = LogicState{been_true:false, been_false:false};

        assert_eq!(&t+&f, tf);
        assert_eq!(&t+&t, t);
        assert_eq!(&tf+&f, tf);
        assert_eq!(&tf+&t, tf);
        assert_eq!(&t+&n, t);
        assert_eq!(&n+&f, f);
        assert_eq!(&n+&n,n);
    }
}
<commit_msg>Added tests and fixed issue<commit_after>use std::collections::{BTreeMap, HashMap};
use std::collections::btree_map::Iter;
use std::path::{PathBuf, Path};
use std::fmt::{Display, Formatter, Result};
use std::ops::Add;
use std::cmp::{Ord, Ordering};

/// Used to track the state of logical conditions
#[derive(Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct LogicState {
    /// Whether the condition has been observed as true
    pub been_true: bool,
    /// Whether the condition has been observed as false
    pub been_false: bool,
}

impl<'a> Add for &'a LogicState {
    type Output = LogicState;

    fn add(self, other: &'a LogicState) -> LogicState {
        LogicState {
            been_true: self.been_true | other.been_true,
            been_false: self.been_false | other.been_false,
        }
    }
}

/// Shows what type of coverage data is being collected by a given trace
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub enum CoverageStat {
    /// Line coverage data (whether line has been hit)
    Line(u64),
    /// Branch coverage data (whether branch has been true and false
    Branch(LogicState),
    /// Condition coverage data (each boolean subcondition true and false)
    Condition(Vec<LogicState>),
}

impl Add for CoverageStat {
    type Output = CoverageStat;

    fn add(self, other: CoverageStat) -> CoverageStat {
        match (self, other) {
            (CoverageStat::Line(ref l), CoverageStat::Line(ref r)) => {
                CoverageStat::Line(l+r)
            },
            (CoverageStat::Branch(ref l), CoverageStat::Branch(ref r)) => {
                CoverageStat::Branch(l + r)
            },
            t @ _ => t.0,
        }
    }
}

impl Display for CoverageStat {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self {
            &CoverageStat::Line(x) => {
                write!(f, "hits: {}", x)
            },
            _ => write!(f, ""),
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    /// Line the trace is on in the file
    pub line: u64,
    /// Optional address showing location in the test artefact
    pub address: Option<u64>,
    /// Length of the instruction (useful to get entire condition/branch)
    pub length: usize,
    /// Coverage stats
    pub stats: CoverageStat,
}

/// Implemented to allow Traces to be sorted by line number
impl Ord for Trace {
    fn cmp(&self, other: &Trace) -> Ordering {
        self.line.cmp(&other.line)
    }
    fn max(self, other: Trace) -> Trace {
        if self.line > other.line {
            self
        } else {
            other
        }
    }
    fn min(self, other: Trace) -> Trace {
        if self.line < other.line {
            self
        } else {
            other
        }
    }
}

/// Stores all the program traces mapped to files and provides an interface to
/// add, query and change traces.
#[derive(Debug)]
pub struct TraceMap {
    /// Traces in the program mapped to the given file
    traces: BTreeMap<PathBuf, Vec<Trace>>,
}

impl TraceMap {
    /// Create a new TraceMap
    pub fn new() -> TraceMap {
        TraceMap {
            traces: BTreeMap::new(),
        }
    }

    /// Returns true if there are no traces
    pub fn is_empty(&self) -> bool {
        self.traces.is_empty()
    }

    /// Provides an interator to the underlying map of PathBufs to Vec<Trace>
    pub fn iter(&self) -> Iter<PathBuf, Vec<Trace>> {
        self.traces.iter()
    }

    /// Merges the results of one tracemap into the current one.
    /// This adds records which are missing and adds the statistics gathered to
    /// existing records
    pub fn merge(&mut self, other: &TraceMap) {
        for (k,  values) in other.iter() {
            if !self.traces.contains_key(k) {
                self.traces.insert(k.to_path_buf(), values.to_vec());
            } else {
                let mut existing = self.traces.get_mut(k).unwrap();
                for ref v in values.iter() {
                    let mut added = false;
                    if let Some(ref mut t) = existing.iter_mut()
                                                     .find(|ref x| x.line == v.line && x.address == v.address) {
                        t.stats = t.stats.clone() + v.stats.clone();
                        added = true;
                    }
                    if !added {
                        existing.push((*v).clone());
                        existing.sort_unstable();
                    }
                }
            }
        }
    }

    /// This will collapse duplicate Traces into a single trace. Warning this
    /// will lose the addresses of the duplicate traces but increment the results
    /// should be called only if you don't need those addresses from then on
    /// TODO possibly not the cleanest solution
    pub fn dedup(&mut self) {
        for (_, values) in self.traces.iter_mut() {
            // Map of lines and stats, merge duplicated stats here
            let mut lines: HashMap<u64, CoverageStat> = HashMap::new();
            // Duplicated traces need cleaning up. Maintain a list of them!
            let mut dirty: Vec<u64> = Vec::new();
            for v in values.iter() {
                if lines.contains_key(&v.line) {
                    dirty.push(v.line);
                    let s = lines.get(&v.line).unwrap().clone() + v.stats.clone();
                    lines.insert(v.line, s);
                } else {
                    lines.insert(v.line, v.stats.clone());
                }
            }
            for d in dirty.iter() {
                let mut first = true;
                values.retain(|x| {
                    let res = x.line != *d;
                    if !res {
                        if first {
                            first = false;
                            true
                        }else {
                            false
                        }
                    } else {
                        res
                    }
                });
                if let Some(new_stat) = lines.remove(&d) {
                    if let Some(ref mut t) = values.iter_mut().find(|x| x.line==*d) {
                        t.stats = new_stat;
                    }
                }
            }
        }
    }

    /// Add a trace to the tracemap for the given file
    pub fn add_trace(&mut self, file: &Path, trace: Trace) {
        if self.traces.contains_key(file) {
            if let Some(trace_vec) = self.traces.get_mut(file) {
                trace_vec.push(trace);
                trace_vec.sort_unstable();
            }
        } else {
            self.traces.insert(file.to_path_buf(), vec![trace]);
        }
    }

    /// Gets an immutable reference to a trace from an address. Returns None if
    /// there is no trace at that address
    pub fn get_trace(&self, address: u64) -> Option<&Trace> {
        self.all_traces()
            .iter()
            .find(|x| x.address == Some(address))
            .map(|x| *x)
    }

    /// Gets a mutable reference to a trace at a given address
    /// Returns None if there is no trace at that address
    pub fn get_trace_mut(&mut self, address: u64) -> Option<&mut Trace> {
        for val in self.all_traces_mut() {
            if val.address == Some(address) {
                return Some(val);
            }
        }
        None
    }

    /// Returns true if the location described by file and line number is present
    /// in the tracemap
    pub fn contains_location(&self, file: &Path, line: u64) -> bool {
        match self.traces.get(file) {
            Some(traces) => traces.iter().any(|x| x.line == line),
            None => false,
        }
    }

    /// Gets all traces below a certain path
    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }

    /// Gets all traces
    pub fn all_traces(&self) -> Vec<&Trace> {
        self.traces.values().flat_map(|ref x| x.iter()).collect()
    }

    /// Gets a vector of all the traces to mutate
    fn all_traces_mut(&mut self) -> Vec<&mut Trace> {
        self.traces.values_mut().flat_map(|x| x.iter_mut()).collect()
    }

    pub fn files(&self) -> Vec<&PathBuf> {
        self.traces.keys().collect()
    }

    pub fn coverable_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    pub fn covered_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Give the total amount of coverable points in the code. This will vary
    /// based on the statistics available for line coverage it will be total
    /// line whereas for condition or decision it will count the number of
    /// conditions available
    pub fn total_coverable(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    /// From all the coverable data return the amount covered
    pub fn total_covered(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Returns coverage percentage ranging from 0.0-1.0
    pub fn coverage_percentage(&self) -> f64 {
        (self.total_covered() as f64) / (self.total_coverable() as f64)
    }

}

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

    #[test]
    fn stat_addition() {
        let x = CoverageStat::Line(0);
        let y = CoverageStat::Line(5);
        let z = CoverageStat::Line(7);
        let xy = x.clone() + y.clone();
        let yx = y.clone() + x.clone();
        let yy = y.clone() + y.clone();
        let zy = z.clone() + y.clone();
        assert_eq!(&xy, &CoverageStat::Line(5));
        assert_eq!(&yx, &xy);
        assert_eq!(&yy, &CoverageStat::Line(10));
        assert_eq!(&zy, &CoverageStat::Line(12));

        let tf = LogicState{been_true:true, been_false:true};
        let t = LogicState{been_true:true, been_false:false};
        let f = LogicState{been_true:false, been_false:true};
        let n = LogicState{been_true:false, been_false:false};

        assert_eq!(&t+&f, tf);
        assert_eq!(&t+&t, t);
        assert_eq!(&tf+&f, tf);
        assert_eq!(&tf+&t, tf);
        assert_eq!(&t+&n, t);
        assert_eq!(&n+&f, f);
        assert_eq!(&n+&n,n);
    }

    #[test]
    fn merge_address_mismatch_and_dedup() {
        let mut t1 = TraceMap::new();
        let mut t2 = TraceMap::new();

        let a_trace = Trace {
            line: 1,
            address: Some(5),
            length: 0,
            stats: CoverageStat::Line(1)
        };
        t1.add_trace(Path::new("file.rs"), a_trace.clone());
        t2.add_trace(Path::new("file.rs"), Trace {
            line: 1,
            address: None,
            length: 0,
            stats: CoverageStat::Line(2)
        });

        t1.merge(&t2);
        assert_eq!(t1.all_traces().len(), 2);
        assert_eq!(t1.get_trace(5), Some(&a_trace));
        t1.dedup();
        let all = t1.all_traces();
        assert_eq!(all.len(), 1);
        assert_eq!(all[0].stats, CoverageStat::Line(3));
    }

    #[test]
    fn no_merge_dedup_needed() {
        let mut t1 = TraceMap::new();
        let mut t2 = TraceMap::new();

        let a_trace = Trace {
            line: 1,
            address: Some(5),
            length: 0,
            stats: CoverageStat::Line(1)
        };
        t1.add_trace(Path::new("file.rs"), a_trace.clone());
        t2.add_trace(Path::new("file.rs"), Trace {
            line: 2,
            address: None,
            length: 0,
            stats: CoverageStat::Line(2)
        });

        t1.merge(&t2);
        assert_eq!(t1.all_traces().len(), 2);
        assert_eq!(t1.get_trace(5), Some(&a_trace));
        t1.dedup();
        let all = t1.all_traces();
        assert_eq!(all.len(), 2);
    }
}
<|endoftext|>


<commit_before>//! This module provides useful traits that were deprecated in rust

// Note copied from the stdlib under MIT license

use num_traits::{Bounded, Num, NumCast};
use std::ops::{AddAssign};

use crate::color::{ColorType, Luma, LumaA, Rgb, Rgba};

/// Types which are safe to treat as an immutable byte slice in a pixel layout
/// for image encoding.
pub trait EncodableLayout: seals::EncodableLayout {
    /// Get the bytes of this value.
    fn as_bytes(&self) -> &[u8];
}

impl EncodableLayout for [u8] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

impl EncodableLayout for [u16] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

impl EncodableLayout for [f32] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

/// The type of each channel in a pixel. For example, this can be `u8`, `u16`, `f32`.
// TODO rename to `PixelComponent`
pub trait Primitive: Copy + NumCast + Num + PartialOrd<Self> + Clone + Bounded + 'static {

    /// The maximum value for this type of primitive within the context of color.
    /// For floats, the maximum is `1.0`, whereas the integer types inherit their usual maximum values.
    const DEFAULT_MAX_VALUE: Self;

    /// The minimum value for this type of primitive within the context of color.
    /// For floats, the minimum is `0.0`, whereas the integer types inherit their usual minimum values.
    const DEFAULT_MIN_VALUE: Self;
}

macro_rules! declare_primitive {
    ($base:ty: ($from:expr)..$to:expr) => {
        impl Primitive for $base {
            const DEFAULT_MAX_VALUE: Self = $to;
            const DEFAULT_MIN_VALUE: Self = $from;
        }
    }
}

declare_primitive!(usize: (0)..Self::MAX);
declare_primitive!(u8: (0)..Self::MAX);
declare_primitive!(u16: (0)..Self::MAX);
declare_primitive!(u32: (0)..Self::MAX);
declare_primitive!(u64: (0)..Self::MAX);

declare_primitive!(isize: (Self::MIN)..Self::MAX);
declare_primitive!(i8: (Self::MIN)..Self::MAX);
declare_primitive!(i16: (Self::MIN)..Self::MAX);
declare_primitive!(i32: (Self::MIN)..Self::MAX);
declare_primitive!(i64: (Self::MIN)..Self::MAX);
declare_primitive!(f32: (0.0)..1.0);
declare_primitive!(f64: (0.0)..1.0);

/// An Enlargable::Larger value should be enough to calculate
/// the sum (average) of a few hundred or thousand Enlargeable values.
pub trait Enlargeable: Sized + Bounded + NumCast {
    type Larger: Primitive + AddAssign + 'static;

    fn clamp_from(n: Self::Larger) -> Self {
        // Note: Only unsigned value types supported.
        if n > NumCast::from(Self::max_value()).unwrap() {
            Self::max_value()
        } else {
            NumCast::from(n).unwrap()
        }
    }
}

impl Enlargeable for u8 {
    type Larger = u32;
}
impl Enlargeable for u16 {
    type Larger = u32;
}
impl Enlargeable for u32 {
    type Larger = u64;
}
impl Enlargeable for f32 {
    type Larger = f64;
}

/// Linear interpolation without involving floating numbers.
pub trait Lerp: Bounded + NumCast {
    type Ratio: Primitive;

    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
        let a = <Self::Ratio as NumCast>::from(a).unwrap();
        let b = <Self::Ratio as NumCast>::from(b).unwrap();

        let res = a + (b - a) * ratio;

        if res > NumCast::from(Self::max_value()).unwrap() {
            Self::max_value()
        } else if res < NumCast::from(0).unwrap() {
            NumCast::from(0).unwrap()
        } else {
            NumCast::from(res).unwrap()
        }
    }
}

impl Lerp for u8 {
    type Ratio = f32;
}

impl Lerp for u16 {
    type Ratio = f32;
}

impl Lerp for u32 {
    type Ratio = f64;
}

impl Lerp for f32 {
    type Ratio = f32;

    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
        a + (b - a) * ratio
    }
}

/// The pixel with an associated color type.
pub trait PixelWithColorType: Pixel + self::private::SealedPixelWithColorType {

    /// A string that can help to interpret the meaning each channel
    /// See [gimp babl](http://gegl.org/babl/).
    const COLOR_TYPE: ColorType;
}

impl PixelWithColorType for Rgb<u8> { const COLOR_TYPE: ColorType = ColorType::Rgb8; }
impl PixelWithColorType for Rgb<u16> { const COLOR_TYPE: ColorType = ColorType::Rgb16; }
impl PixelWithColorType for Rgb<f32> { const COLOR_TYPE: ColorType = ColorType::Rgb32F; }

impl PixelWithColorType for Rgba<u8> { const COLOR_TYPE: ColorType = ColorType::Rgba8; }
impl PixelWithColorType for Rgba<u16> { const COLOR_TYPE: ColorType = ColorType::Rgba8; }
impl PixelWithColorType for Rgba<f32> { const COLOR_TYPE: ColorType = ColorType::Rgba32F; }

impl PixelWithColorType for Luma<u8> { const COLOR_TYPE: ColorType = ColorType::L8; }
impl PixelWithColorType for Luma<u16> { const COLOR_TYPE: ColorType = ColorType::L16; }

impl PixelWithColorType for LumaA<u8> { const COLOR_TYPE: ColorType = ColorType::La8; }
impl PixelWithColorType for LumaA<u16> { const COLOR_TYPE: ColorType = ColorType::La16; }

/// Prevents down-stream users from implementing the `PixelComponent` trait
mod private {
    use crate::color::*;

    pub trait SealedPixelWithColorType {}
    impl SealedPixelWithColorType for Rgb<u8> {}
    impl SealedPixelWithColorType for Rgb<u16> {}
    impl SealedPixelWithColorType for Rgb<f32> {}

    impl SealedPixelWithColorType for Rgba<u8> {}
    impl SealedPixelWithColorType for Rgba<u16> {}
    impl SealedPixelWithColorType for Rgba<f32> {}

    impl SealedPixelWithColorType for Luma<u8> {}
    impl SealedPixelWithColorType for LumaA<u8> {}

    impl SealedPixelWithColorType for Luma<u16> {}
    impl SealedPixelWithColorType for LumaA<u16> {}
}

/// A generalized pixel.
///
/// A pixel object is usually not used standalone but as a view into an image buffer.
pub trait Pixel: Copy + Clone {

    /// The scalar type that is used to store each channel in this pixel.
    type Subpixel: Primitive;

    /// The number of channels of this pixel type.
    const CHANNEL_COUNT: u8;

    /// Returns the components as a slice.
    fn channels(&self) -> &[Self::Subpixel];

    /// Returns the components as a mutable slice
    fn channels_mut(&mut self) -> &mut [Self::Subpixel];

    /// Returns the channels of this pixel as a 4 tuple. If the pixel
    /// has less than 4 channels the remainder is filled with the maximum value
    #[deprecated(since="0.24.0", note="Use `channels()` or `channels_mut()`")]
    fn channels4(
        &self,
    ) -> (
        Self::Subpixel,
        Self::Subpixel,
        Self::Subpixel,
        Self::Subpixel,
    );

    /// Construct a pixel from the 4 channels a, b, c and d.
    /// If the pixel does not contain 4 channels the extra are ignored.
    #[deprecated(since="0.24.0", note="Use the constructor of the pixel, for example `Rgba::new(r,g,b,a)` or `Pixel::from_slice`")]
    fn from_channels(
        a: Self::Subpixel,
        b: Self::Subpixel,
        c: Self::Subpixel,
        d: Self::Subpixel,
    ) -> Self;

    /// Returns a view into a slice.
    ///
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
    /// that the slice is long enough to prevent panics if the pixel is used later on.
    fn from_slice(slice: &[Self::Subpixel]) -> &Self;

    /// Returns mutable view into a mutable slice.
    ///
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
    /// that the slice is long enough to prevent panics if the pixel is used later on.
    fn from_slice_mut(slice: &mut [Self::Subpixel]) -> &mut Self;

    /// Convert this pixel to RGB
    fn to_rgb(&self) -> Rgb<Self::Subpixel>;

    /// Convert this pixel to RGB with an alpha channel
    fn to_rgba(&self) -> Rgba<Self::Subpixel>;

    /// Convert this pixel to luma
    fn to_luma(&self) -> Luma<Self::Subpixel>;

    /// Convert this pixel to luma with an alpha channel
    fn to_luma_alpha(&self) -> LumaA<Self::Subpixel>;

    /// Apply the function ```f``` to each channel of this pixel.
    fn map<F>(&self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel of this pixel.
    fn apply<F>(&mut self, f: F)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Apply the function ```g``` to the alpha channel.
    fn map_with_alpha<F, G>(&self, f: F, g: G) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
        G: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Apply the function ```g``` to the alpha channel. Works in-place.
    fn apply_with_alpha<F, G>(&mut self, f: F, g: G)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
        G: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    fn map_without_alpha<F>(&self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
    {
        let mut this = *self;
        this.apply_with_alpha(f, |x| x);
        this
    }

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Works in place.
    fn apply_without_alpha<F>(&mut self, f: F)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
    {
        self.apply_with_alpha(f, |x| x);
    }

    /// Apply the function ```f``` to each channel of this pixel and
    /// ```other``` pairwise.
    fn map2<F>(&self, other: &Self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel of this pixel and
    /// ```other``` pairwise. Works in-place.
    fn apply2<F>(&mut self, other: &Self, f: F)
    where
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;

    /// Invert this pixel
    fn invert(&mut self);

    /// Blend the color of a given pixel into ourself, taking into account alpha channels
    fn blend(&mut self, other: &Self);
}

/// Private module for supertraits of sealed traits.
mod seals {
    pub trait EncodableLayout {}

    impl EncodableLayout for [u8] {}
    impl EncodableLayout for [u16] {}
    impl EncodableLayout for [f32] {}
}
<commit_msg>fix documentation<commit_after>//! This module provides useful traits that were deprecated in rust

// Note copied from the stdlib under MIT license

use num_traits::{Bounded, Num, NumCast};
use std::ops::{AddAssign};

use crate::color::{ColorType, Luma, LumaA, Rgb, Rgba};

/// Types which are safe to treat as an immutable byte slice in a pixel layout
/// for image encoding.
pub trait EncodableLayout: seals::EncodableLayout {
    /// Get the bytes of this value.
    fn as_bytes(&self) -> &[u8];
}

impl EncodableLayout for [u8] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

impl EncodableLayout for [u16] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

impl EncodableLayout for [f32] {
    fn as_bytes(&self) -> &[u8] {
        bytemuck::cast_slice(self)
    }
}

/// The type of each channel in a pixel. For example, this can be `u8`, `u16`, `f32`.
// TODO rename to `PixelComponent`? Split up into separate traits? Seal?
pub trait Primitive: Copy + NumCast + Num + PartialOrd<Self> + Clone + Bounded + 'static {

    /// The maximum value for this type of primitive within the context of color.
    /// For floats, the maximum is `1.0`, whereas the integer types inherit their usual maximum values.
    const DEFAULT_MAX_VALUE: Self;

    /// The minimum value for this type of primitive within the context of color.
    /// For floats, the minimum is `0.0`, whereas the integer types inherit their usual minimum values.
    const DEFAULT_MIN_VALUE: Self;
}

macro_rules! declare_primitive {
    ($base:ty: ($from:expr)..$to:expr) => {
        impl Primitive for $base {
            const DEFAULT_MAX_VALUE: Self = $to;
            const DEFAULT_MIN_VALUE: Self = $from;
        }
    }
}

declare_primitive!(usize: (0)..Self::MAX);
declare_primitive!(u8: (0)..Self::MAX);
declare_primitive!(u16: (0)..Self::MAX);
declare_primitive!(u32: (0)..Self::MAX);
declare_primitive!(u64: (0)..Self::MAX);

declare_primitive!(isize: (Self::MIN)..Self::MAX);
declare_primitive!(i8: (Self::MIN)..Self::MAX);
declare_primitive!(i16: (Self::MIN)..Self::MAX);
declare_primitive!(i32: (Self::MIN)..Self::MAX);
declare_primitive!(i64: (Self::MIN)..Self::MAX);
declare_primitive!(f32: (0.0)..1.0);
declare_primitive!(f64: (0.0)..1.0);

/// An Enlargable::Larger value should be enough to calculate
/// the sum (average) of a few hundred or thousand Enlargeable values.
pub trait Enlargeable: Sized + Bounded + NumCast {
    type Larger: Primitive + AddAssign + 'static;

    fn clamp_from(n: Self::Larger) -> Self {
        // Note: Only unsigned value types supported.
        if n > NumCast::from(Self::max_value()).unwrap() {
            Self::max_value()
        } else {
            NumCast::from(n).unwrap()
        }
    }
}

impl Enlargeable for u8 {
    type Larger = u32;
}
impl Enlargeable for u16 {
    type Larger = u32;
}
impl Enlargeable for u32 {
    type Larger = u64;
}
impl Enlargeable for f32 {
    type Larger = f64;
}

/// Linear interpolation without involving floating numbers.
pub trait Lerp: Bounded + NumCast {
    type Ratio: Primitive;

    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
        let a = <Self::Ratio as NumCast>::from(a).unwrap();
        let b = <Self::Ratio as NumCast>::from(b).unwrap();

        let res = a + (b - a) * ratio;

        if res > NumCast::from(Self::max_value()).unwrap() {
            Self::max_value()
        } else if res < NumCast::from(0).unwrap() {
            NumCast::from(0).unwrap()
        } else {
            NumCast::from(res).unwrap()
        }
    }
}

impl Lerp for u8 {
    type Ratio = f32;
}

impl Lerp for u16 {
    type Ratio = f32;
}

impl Lerp for u32 {
    type Ratio = f64;
}

impl Lerp for f32 {
    type Ratio = f32;

    fn lerp(a: Self, b: Self, ratio: Self::Ratio) -> Self {
        a + (b - a) * ratio
    }
}

/// The pixel with an associated `ColorType`.
/// Not all possible pixels represent one of the predefined `ColorType`s.
pub trait PixelWithColorType: Pixel + self::private::SealedPixelWithColorType {

    /// This pixel has the format of one of the predefined `ColorType`s,
    /// such as `Rgb8`, `La16` or `Rgba32F`.
    /// This is needed for automatically detecting
    /// a color format when saving an image as a file.
    const COLOR_TYPE: ColorType;
}

impl PixelWithColorType for Rgb<u8> { const COLOR_TYPE: ColorType = ColorType::Rgb8; }
impl PixelWithColorType for Rgb<u16> { const COLOR_TYPE: ColorType = ColorType::Rgb16; }
impl PixelWithColorType for Rgb<f32> { const COLOR_TYPE: ColorType = ColorType::Rgb32F; }

impl PixelWithColorType for Rgba<u8> { const COLOR_TYPE: ColorType = ColorType::Rgba8; }
impl PixelWithColorType for Rgba<u16> { const COLOR_TYPE: ColorType = ColorType::Rgba8; }
impl PixelWithColorType for Rgba<f32> { const COLOR_TYPE: ColorType = ColorType::Rgba32F; }

impl PixelWithColorType for Luma<u8> { const COLOR_TYPE: ColorType = ColorType::L8; }
impl PixelWithColorType for Luma<u16> { const COLOR_TYPE: ColorType = ColorType::L16; }

impl PixelWithColorType for LumaA<u8> { const COLOR_TYPE: ColorType = ColorType::La8; }
impl PixelWithColorType for LumaA<u16> { const COLOR_TYPE: ColorType = ColorType::La16; }

/// Prevents down-stream users from implementing the `Primitive` trait
mod private {
    use crate::color::*;

    pub trait SealedPixelWithColorType {}
    impl SealedPixelWithColorType for Rgb<u8> {}
    impl SealedPixelWithColorType for Rgb<u16> {}
    impl SealedPixelWithColorType for Rgb<f32> {}

    impl SealedPixelWithColorType for Rgba<u8> {}
    impl SealedPixelWithColorType for Rgba<u16> {}
    impl SealedPixelWithColorType for Rgba<f32> {}

    impl SealedPixelWithColorType for Luma<u8> {}
    impl SealedPixelWithColorType for LumaA<u8> {}

    impl SealedPixelWithColorType for Luma<u16> {}
    impl SealedPixelWithColorType for LumaA<u16> {}
}

/// A generalized pixel.
///
/// A pixel object is usually not used standalone but as a view into an image buffer.
pub trait Pixel: Copy + Clone {

    /// The scalar type that is used to store each channel in this pixel.
    type Subpixel: Primitive;

    /// The number of channels of this pixel type.
    const CHANNEL_COUNT: u8;

    /// Returns the components as a slice.
    fn channels(&self) -> &[Self::Subpixel];

    /// Returns the components as a mutable slice
    fn channels_mut(&mut self) -> &mut [Self::Subpixel];

    /// Returns the channels of this pixel as a 4 tuple. If the pixel
    /// has less than 4 channels the remainder is filled with the maximum value
    #[deprecated(since="0.24.0", note="Use `channels()` or `channels_mut()`")]
    fn channels4(
        &self,
    ) -> (
        Self::Subpixel,
        Self::Subpixel,
        Self::Subpixel,
        Self::Subpixel,
    );

    /// Construct a pixel from the 4 channels a, b, c and d.
    /// If the pixel does not contain 4 channels the extra are ignored.
    #[deprecated(since="0.24.0", note="Use the constructor of the pixel, for example `Rgba::new(r,g,b,a)` or `Pixel::from_slice`")]
    fn from_channels(
        a: Self::Subpixel,
        b: Self::Subpixel,
        c: Self::Subpixel,
        d: Self::Subpixel,
    ) -> Self;

    /// Returns a view into a slice.
    ///
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
    /// that the slice is long enough to prevent panics if the pixel is used later on.
    fn from_slice(slice: &[Self::Subpixel]) -> &Self;

    /// Returns mutable view into a mutable slice.
    ///
    /// Note: The slice length is not checked on creation. Thus the caller has to ensure
    /// that the slice is long enough to prevent panics if the pixel is used later on.
    fn from_slice_mut(slice: &mut [Self::Subpixel]) -> &mut Self;

    /// Convert this pixel to RGB
    fn to_rgb(&self) -> Rgb<Self::Subpixel>;

    /// Convert this pixel to RGB with an alpha channel
    fn to_rgba(&self) -> Rgba<Self::Subpixel>;

    /// Convert this pixel to luma
    fn to_luma(&self) -> Luma<Self::Subpixel>;

    /// Convert this pixel to luma with an alpha channel
    fn to_luma_alpha(&self) -> LumaA<Self::Subpixel>;

    /// Apply the function ```f``` to each channel of this pixel.
    fn map<F>(&self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel of this pixel.
    fn apply<F>(&mut self, f: F)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Apply the function ```g``` to the alpha channel.
    fn map_with_alpha<F, G>(&self, f: F, g: G) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
        G: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Apply the function ```g``` to the alpha channel. Works in-place.
    fn apply_with_alpha<F, G>(&mut self, f: F, g: G)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
        G: FnMut(Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel except the alpha channel.
    fn map_without_alpha<F>(&self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
    {
        let mut this = *self;
        this.apply_with_alpha(f, |x| x);
        this
    }

    /// Apply the function ```f``` to each channel except the alpha channel.
    /// Works in place.
    fn apply_without_alpha<F>(&mut self, f: F)
    where
        F: FnMut(Self::Subpixel) -> Self::Subpixel,
    {
        self.apply_with_alpha(f, |x| x);
    }

    /// Apply the function ```f``` to each channel of this pixel and
    /// ```other``` pairwise.
    fn map2<F>(&self, other: &Self, f: F) -> Self
    where
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;

    /// Apply the function ```f``` to each channel of this pixel and
    /// ```other``` pairwise. Works in-place.
    fn apply2<F>(&mut self, other: &Self, f: F)
    where
        F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;

    /// Invert this pixel
    fn invert(&mut self);

    /// Blend the color of a given pixel into ourself, taking into account alpha channels
    fn blend(&mut self, other: &Self);
}

/// Private module for supertraits of sealed traits.
mod seals {
    pub trait EncodableLayout {}

    impl EncodableLayout for [u8] {}
    impl EncodableLayout for [u16] {}
    impl EncodableLayout for [f32] {}
}
<|endoftext|>


<commit_before>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // Execute PATH with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execv.3.html
        pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // Execute FILE, searching in the `PATH' environment variable if it contains
        // no slashes, with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execvp.3.html
        pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/sethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/chroot.2.html
        pub fn chroot(path: *const c_char) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        ffi::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        ffi::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<commit_msg>Add support for fsync, fdatasync<commit_after>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // Execute PATH with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execv.3.html
        pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // Execute FILE, searching in the `PATH' environment variable if it contains
        // no slashes, with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execvp.3.html
        pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/sethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/chroot.2.html
        pub fn chroot(path: *const c_char) -> c_int;

        // synchronize a file's in-core state with storage device
        // doc: http://man7.org/linux/man-pages/man2/fsync.2.html
        pub fn fsync(fd: c_int) -> c_int;
        pub fn fdatasync(fd: c_int) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        ffi::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        ffi::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fsync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fdatasync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<|endoftext|>


<commit_before>mod stack;
mod pc;
mod memory;
mod params;
mod account;
mod cost;
mod run;

pub use self::opcode::Opcode;
pub use self::memory::{Memory, VectorMemory};
pub use self::stack::{Stack, VectorStack};
pub use self::pc::{PC, VectorPC};
pub use self::machine::{Machine, VectorMachine, FakeVectorMachine};

#[derive(Debug)]
pub enum ExecutionError {
    EmptyGas,
    StackUnderflow,
    StackOverflow,
    InvalidOpcode,
    PCOverflow,
    PCBadJumpDest,
    PCTooLarge, // The current implementation only support code size with usize::maximum.
    MemoryTooLarge,
    DataTooLarge,
    CodeTooLarge,
    RequireAccount(Address),
    RequireAccountCode(Address),
    Stopped
}

#[derive(Debug)]
pub enum CommitError {
    AlreadyCommitted,
    StateChanged
}

pub type ExecutionResult<T> = ::std::result::Result<T, ExecutionError>;

pub struct Machine<M, S> {
    pc: PC,
    memory: M,
    stack: Stack,
    transaction: Transaction,
    block: Block,
    cost_aggregrator: CostAggregrator,
    return_values: Vec<u8>,
    accounts: Map<Address, Account>,
    valid_pc: bool,

    homestead: bool,
    eip150: bool,
    eip160: bool,
}

impl<M: Memory + Default, S: Storage> Machine<M, S> {
    pub fn new(transaction: Transaction, block: Block) -> Self {
        Self {
            pc: PC,
            memory: M::default(),
            stack: Stack::default(),
            transaction: transaction,
            block: block,
            cost_aggregrator: CostAggregrator::default(),
            return_values: Vec::new(),
            accounts: Vec::new(),
            valid_pc: false,

            homestead: false,
            eip150: false,
            eip160: false,
        }
    }
}

impl<M: Memory, S: Storage> Machine<M, S> {
    pub fn pc(&self) -> ExecutionResult<&PC> {
        &self.pc
    }

    pub fn memory(&self) -> &M {
        &self.memory
    }

    pub fn stack(&self) -> &Stack {
        &self.stack
    }

    pub fn transaction(&self) -> &Transaction {
        &self.transaction
    }

    pub fn block(&self) -> &Block {
        &self.block
    }

    pub fn accounts(&self) -> Iter<Address, Account> {

    }

    pub fn return_values(&self) -> &[u8] {

    }

    pub fn active_memory_len(&self) -> M256 {
        self.cost_aggregrator.active_memoty_len()
    }

    pub fn owner(&self) -> Address {

    }

    pub fn homestead(&self) -> bool {
        self.homestead
    }

    pub fn set_homestead(&mut self, val: bool) {
        self.homestead = val;
    }

    pub fn eip150(&self) -> bool {
        self.eip150
    }

    pub fn set_eip150(&mut self, val: bool) {
        self.eip150 = val;
    }

    pub fn eip160(&self) -> bool {
        self.eip160
    }

    pub fn set_eip160(&mut self, val: bool) {
        self.eip160 = val;
    }

    pub fn commit(&mut self, commitment: Commitment<S>) -> Result<(), CommitError> {
        let account: Account<S> = commitment.into();
        let address = account.address();
        if self.accounts.contains_key(&address) {
            return Err(CommitError::AlreadyCommitted);
        }

        if address == self.owner() {
            match account {
                Account::Full {
                    address: _,
                    code: ref code,
                    balance: _,
                    storage: _,
                    appending_logs: _,
                } => {
                    self.pc = PC::new(code.as_slice());
                    self.valid_pc = true;
                }
            }
        }

        self.accounts.insert(address, account);
        Ok(())
    }

    fn account_log(&mut self, address: Address, data: &[u8], topics: &[M256]) -> ExecutionResult<()> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                address: _,
                balance: _,
                storage: _,
                code: _,
                appending_logs: ref appending_logs,
            }) => {
                appending_logs.push(Log {
                    data: data.into(),
                    topics: topics.into(),
                });
                Ok(())
            },
            _ => {
                Err(ExecutionResult::RequireAccount(address))
            }
        }
    }

    fn account_code(&self, address: Address) -> ExecutionResult<&[u8]> {
        match self.accounts_get(&address) {
            Some(&Account::Full {
                address: _,
                balance: _,
                storage: _,
                code: ref code,
                appending_logs: _,
            }) => {
                Ok(code.as_ref().unwrap().as_slice())
            },
            Some(&Account::Code {
                code: ref code,
            }) => {
                Ok(code.as_ref().unwrap().as_slice())
            },
            _ => {
                Err(ExecutionResult::RequireAccountCode(address))
            }
        }
    }

    fn account_balance(&self, address: Address) -> ExecutionResult<M256> {
        match self.accounts_get(&address) {
            Some(&Account::Full {
                address: _,
                balance: balance,
                storage: _,
                code: _,
                appending_logs: _,
            }) => {
                Ok(balance)
            },
            _ => {
                Err(ExecutionResult::RequireAccount(address))
            }
        }
    }

    pub fn peek_cost(&self) -> ExecutionResult<Gas> {
        if !self.valid_pc {
            return Err(Error::RequireAccount(self.owner()));
        }

        let opcode = self.pc.peek_opcode()?;
        let aggregrator = self.cost_aggregrator;
        let (gas, agg) = gas_cost(opcode, &self, aggregrator);
        Ok(gas)
    }

    pub fn step(&mut self) -> Result<()> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        begin_rescuable!(self, &mut Self, __);
        if self.pc.stopped() {
            trr!(Err(Error::Stopped), __);
        }

        let position = self.pc.position();
        on_rescue!(|machine| {
            machine.pc.jump_unchecked(position);
        }, __);

        let opcode = trr!(self.pc.read_opcode(), __);
        let available_gas = self.available_gas();
        let cost_aggregrator = self.state.cost_aggregrator();
        let (gas, agg) = trr!(gas_cost(opcode, &mut self.state,
                                       available_gas, cost_aggregrator), __);
        let refunded = trr!(gas_refund(opcode, &mut self.state), __);

        if gas > self.available_gas() {
            trr!(Err(ExecutionError::EmptyGas), __);
        }

        trr!(opcode.run(&mut self.state, available_gas - gas), __);

        self.cost_aggregrator = agg;
        self.used_gas = self.used_gas + gas;
        self.refunded_gas = self.refunded_gas + refunded;

        end_rescuable!(__);
        Ok(())
    }

    pub fn fire(&mut self) -> Result<()> {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {
                    ExecutionError::Stopped => return Ok(()),
                    err => return Err(err),
                }
            }
        }
    }
}
<commit_msg>Problem: the program won't compile Solution: WIP<commit_after>mod stack;
mod pc;
mod memory;
mod params;
mod account;
mod cost;
mod run;

pub use self::opcode::Opcode;
pub use self::memory::{Memory, SeqMemory};
pub use self::stack::Stack;
pub use self::pc::PC;
pub use self::params::{Block, Transaction};
pub use self::account::{Commitment, Account, Storage, MapStorage, Log};

use self::cost::{gas_cost, gas_refund, CostAggregrator};
use std::collections::hash_map;
use utils::gas::Gas;
use utils::address::Address;
use utils::bigint::{M256, U256};

#[derive(Debug)]
pub enum ExecutionError {
    EmptyGas,
    StackUnderflow,
    StackOverflow,
    InvalidOpcode,
    PCOverflow,
    PCBadJumpDest,
    PCTooLarge, // The current implementation only support code size with usize::maximum.
    MemoryTooLarge,
    DataTooLarge,
    CodeTooLarge,
    RequireAccount(Address),
    RequireAccountCode(Address),
    Stopped
}

#[derive(Debug)]
pub enum CommitError {
    AlreadyCommitted,
    StateChanged
}

pub type ExecutionResult<T> = ::std::result::Result<T, ExecutionError>;

pub struct Machine<M, S> {
    pc: PC,
    memory: M,
    stack: Stack,
    transaction: Transaction,
    block: Block,
    cost_aggregrator: CostAggregrator,
    return_values: Vec<u8>,
    accounts: hash_map::HashMap<Address, Account>,
    valid_pc: bool,

    homestead: bool,
    eip150: bool,
    eip160: bool,
}

impl<M: Memory + Default, S: Storage> Machine<M, S> {
    pub fn new(transaction: Transaction, block: Block) -> Self {
        Self {
            pc: PC::default(),
            memory: M::default(),
            stack: Stack::default(),
            transaction: transaction,
            block: block,
            cost_aggregrator: CostAggregrator::default(),
            return_values: Vec::new(),
            accounts: hash_map::HashMap::new(),
            valid_pc: false,

            homestead: false,
            eip150: false,
            eip160: false,
        }
    }
}

impl<M: Memory, S: Storage> Machine<M, S> {
    pub fn pc(&self) -> ExecutionResult<&PC> {
        &self.pc
    }

    pub fn memory(&self) -> &M {
        &self.memory
    }

    pub fn stack(&self) -> &Stack {
        &self.stack
    }

    pub fn transaction(&self) -> &Transaction {
        &self.transaction
    }

    pub fn block(&self) -> &Block {
        &self.block
    }

    pub fn accounts(&self) -> hash_map::Iter<Address, Account> {

    }

    pub fn return_values(&self) -> &[u8] {

    }

    pub fn active_memory_len(&self) -> M256 {
        self.cost_aggregrator.active_memoty_len()
    }

    pub fn owner(&self) -> Address {

    }

    pub fn homestead(&self) -> bool {
        self.homestead
    }

    pub fn set_homestead(&mut self, val: bool) {
        self.homestead = val;
    }

    pub fn eip150(&self) -> bool {
        self.eip150
    }

    pub fn set_eip150(&mut self, val: bool) {
        self.eip150 = val;
    }

    pub fn eip160(&self) -> bool {
        self.eip160
    }

    pub fn set_eip160(&mut self, val: bool) {
        self.eip160 = val;
    }

    pub fn commit(&mut self, commitment: Commitment<S>) -> Result<(), CommitError> {
        let account: Account<S> = commitment.into();
        let address = account.address();
        if self.accounts.contains_key(&address) {
            return Err(CommitError::AlreadyCommitted);
        }

        if address == self.owner() {
            match account {
                Account::Full {
                    address: _,
                    code: ref code,
                    balance: _,
                    storage: _,
                    appending_logs: _,
                } => {
                    self.pc = PC::new(code.as_slice());
                    self.valid_pc = true;
                }
            }
        }

        self.accounts.insert(address, account);
        Ok(())
    }

    fn account_log(&mut self, address: Address, data: &[u8], topics: &[M256]) -> ExecutionResult<()> {
        match self.accounts.get(&address) {
            Some(&Account::Full {
                address: _,
                balance: _,
                storage: _,
                code: _,
                appending_logs: ref appending_logs,
            }) => {
                appending_logs.push(Log {
                    data: data.into(),
                    topics: topics.into(),
                });
                Ok(())
            },
            _ => {
                Err(ExecutionResult::RequireAccount(address))
            }
        }
    }

    fn account_code(&self, address: Address) -> ExecutionResult<&[u8]> {
        match self.accounts_get(&address) {
            Some(&Account::Full {
                address: _,
                balance: _,
                storage: _,
                code: ref code,
                appending_logs: _,
            }) => {
                Ok(code.as_ref().unwrap().as_slice())
            },
            Some(&Account::Code {
                code: ref code,
            }) => {
                Ok(code.as_ref().unwrap().as_slice())
            },
            _ => {
                Err(ExecutionResult::RequireAccountCode(address))
            }
        }
    }

    fn account_balance(&self, address: Address) -> ExecutionResult<M256> {
        match self.accounts_get(&address) {
            Some(&Account::Full {
                address: _,
                balance: balance,
                storage: _,
                code: _,
                appending_logs: _,
            }) => {
                Ok(balance)
            },
            _ => {
                Err(ExecutionResult::RequireAccount(address))
            }
        }
    }

    pub fn peek_cost(&self) -> ExecutionResult<Gas> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        let opcode = self.pc.peek_opcode()?;
        let aggregrator = self.cost_aggregrator;
        let (gas, agg) = gas_cost(opcode, &self, aggregrator);
        Ok(gas)
    }

    pub fn step(&mut self) -> Result<()> {
        if !self.valid_pc {
            return Err(ExecutionError::RequireAccount(self.owner()));
        }

        begin_rescuable!(self, &mut Self, __);
        if self.pc.stopped() {
            trr!(Err(ExecutionError::Stopped), __);
        }

        let position = self.pc.position();
        on_rescue!(|machine| {
            machine.pc.jump_unchecked(position);
        }, __);

        let opcode = trr!(self.pc.read_opcode(), __);
        let available_gas = self.available_gas();
        let cost_aggregrator = self.state.cost_aggregrator();
        let (gas, agg) = trr!(gas_cost(opcode, &mut self.state,
                                       available_gas, cost_aggregrator), __);
        let refunded = trr!(gas_refund(opcode, &mut self.state), __);

        if gas > self.available_gas() {
            trr!(Err(ExecutionError::EmptyGas), __);
        }

        trr!(opcode.run(&mut self.state, available_gas - gas), __);

        self.cost_aggregrator = agg;
        self.used_gas = self.used_gas + gas;
        self.refunded_gas = self.refunded_gas + refunded;

        end_rescuable!(__);
        Ok(())
    }

    pub fn fire(&mut self) -> Result<()> {
        loop {
            let result = self.step();

            if result.is_err() {
                match result.err().unwrap() {
                    ExecutionError::Stopped => return Ok(()),
                    err => return Err(err),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>
pub struct Window
{
    max_x : u32,
    max_y : u32
}

<commit_msg>remove old windows.rs<commit_after><|endoftext|>