<commit_before>//! Target information

use super::prelude::*;

#[repr(C)]
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();
}

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>Add BPF target bindings.<commit_after>//! Target information

use super::prelude::*;

#[repr(C)]
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();
}

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>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(String),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(pub Duration);
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_ms : u64 = try!(u64::deserialize(deserializer));
        let as_sec = as_ms / 1000;
        let as_ns = (as_ms / 1_000_000) as u32;
        Ok(ValDuration(Duration::new(as_sec, as_ns)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<commit_msg>Actually, implemented ValDuration::new()<commit_after>//!
//! Values manipulated by services
//!
use std::cmp::{PartialOrd, Ordering};
use std::time::Duration;
use std::str::FromStr;

use serde_json;
use chrono;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,
    String,
    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Json(pub serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    Unit,
    Bool(bool),
    Duration(ValDuration),
    TimeStamp(TimeStamp),
    Temperature(Temperature),
    Color(Color),
    String(String),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl Value {
    pub fn get_type(&self) -> Type {
        match *self {
            Value::Unit => Type::Unit,
            Value::Bool(_) => Type::Bool,
            Value::String(_) => Type::String,
            Value::Duration(_) => Type::Duration,
            Value::TimeStamp(_) => Type::TimeStamp,
            Value::Temperature(_) => Type::Temperature,
            Value::Color(_) => Type::Color,
            Value::Json(_) => Type::Json,
            Value::Binary{..} => Type::Binary,
            Value::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::Value::*;
        use std::cmp::Ordering::*;
        match (self, other) {
            (&Unit, &Unit) => Some(Equal),
            (&Unit, _) => None,

            (&Bool(a), &Bool(b)) => a.partial_cmp(&b),
            (&Bool(_), _) => None,

            (&Duration(ref a), &Duration(ref b)) => a.partial_cmp(b),
            (&Duration(_), _) => None,

            (&TimeStamp(ref a), &TimeStamp(ref b)) => a.partial_cmp(b),
            (&TimeStamp(_), _) => None,

            (&Temperature(ref a), &Temperature(ref b)) => a.partial_cmp(b),
            (&Temperature(_), _) => None,

            (&Color(ref a), &Color(ref b)) => a.partial_cmp(b),
            (&Color(_), _) => None,

            (&ExtNumeric(ref a), &ExtNumeric(ref b)) => a.partial_cmp(b),
            (&ExtNumeric(_), _) => None,

            (&String(ref a), &String(ref b)) => a.partial_cmp(b),
            (&String(_), _) => None,

            (&Json(ref a), &Json(ref b)) => a.partial_cmp(b),
            (&Json(_), _) => None,

            (&Binary{mimetype: ref a_mimetype, data: ref a_data},
             &Binary{mimetype: ref b_mimetype, data: ref b_data}) if a_mimetype == b_mimetype => a_data.partial_cmp(b_data),
            (&Binary{..}, _) => None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct ValDuration(Duration);
impl ValDuration {
    pub fn new(duration: Duration) -> Self {
        ValDuration(duration)
    }
}
impl Serialize for ValDuration {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let as_ms : u64 = self.0.as_secs() * 1000
            + (self.0.subsec_nanos() as u64) / 1_000_000;
        as_ms.serialize(serializer)
    }
}
impl Deserialize for ValDuration {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let as_ms : u64 = try!(u64::deserialize(deserializer));
        let as_sec = as_ms / 1000;
        let as_ns = (as_ms / 1_000_000) as u32;
        Ok(ValDuration(Duration::new(as_sec, as_ns)))
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub struct TimeStamp(chrono::DateTime<chrono::Local>);
impl Serialize for TimeStamp {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        let str = self.0.to_rfc3339();
        str.serialize(serializer)
    }
}
impl Deserialize for TimeStamp {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let str = try!(String::deserialize(deserializer));
        match chrono::DateTime::<chrono::Local>::from_str(&str) {
            Ok(dt) => Ok(TimeStamp(dt)),
            Err(_) => Err(D::Error::syntax("Invalid date"))
        }
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger::Logger;
use program::{NAME, VERSION};
use env::Env;
use mounter::Mounter;
use executor::Executor;

pub fn main() {
    let logger = Logger::new(NAME);
    let name_ver = NAME.to_string() + "-" + VERSION;
    let start = name_ver.clone() + " starting!";
    logger.info(&start);

    let env = Env::new();
    env.load(&logger);

    let mnt = Mounter::new();
    mnt.mount(&logger, &env);

    let ex = Executor::new();
    ex.start(&logger, &env);

    let end = name_ver.clone() + " exiting!";
    logger.info(&end);
}
<commit_msg>fix worker::main<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use logger::Logger;
use program::{NAME, VERSION};
use env::Env;
use mounter::Mounter;
use executor::Executor;

pub fn main() {
    let logger = Logger::new(NAME);
    let name_ver = NAME.to_string() + "-" + VERSION;
    let start = name_ver.clone() + " starting!";
    logger.info(&start);

    let mut env = Env::new();
    env.load(&logger);

    let mnt = Mounter::new();
    mnt.mount(&logger, &env);

    let ex = Executor::new();
    ex.start(&logger, &env);

    let end = name_ver.clone() + " exiting!";
    logger.info(&end);
}
<|endoftext|>


<commit_before>use assembler::Assemble;
use disassembler::Disassemble;
use native::{Arch, Instruction};
//use definitions::{RegDefinition, SubRegDefinition, Definition, GenDefinition};

//use std::collections::HashMap;

#[allow(non_camel_case_types)]
pub struct X86_64;

impl X86_64 {
    fn get_opnd_width(opnd: &str) -> Option<u32> {
        let definition = Self::gen_definition();
        if definition.has_reg(opnd) {
            Some(definition.get_reg_width(opnd))
        } else {
            // Parse it, it's (probably?) a memory pointer
            if opnd.starts_with("dword ptr") {
                Some(32)
            } else if opnd.starts_with("qword ptr") {
                Some(64)
            } else if opnd.starts_with("byte ptr") {
                Some(8)
            } else {
                None
            }
        }
    }
}

impl Assemble for X86_64 {
    fn assemble(text: &str) -> Option<Vec<u8>> {
        Self::assemble_text(Arch::X86_64, text)
    }
}

impl Disassemble for X86_64 {
    // XXX_ this could be improved, making Instruction a better
    // representation of the operands in a generic way so it's parsed
    // once by `disassemble` instead of every time it's needed by some
    // other function.
    fn get_registers(ins: &Instruction) -> Vec<&'static str> {
        let mut res = Vec::new();
        let def = Self::gen_definition();
        for opnd in &ins.opnds {
            let t = opnd.text().to_uppercase();
            // Try to match Reg or SubReg
            for &reg_name in def.regs.keys().chain(def.sub_regs.keys()) {
                // XXX_ contains can match name parts (AX in EAX)
                // if t.contains(reg_name) {
                if t == reg_name {
                    res.push(reg_name);
                }
            }
        }
        res
    }

    fn disassemble(bytes: &[u8], address: u64) -> Option<Instruction> {
        let (mnemonic, op_str) =
            Self::disassemble_arch(Arch::X86_64, bytes, address).unwrap();

        let opnds: Vec<(&str, Option<u32>)> =
            if op_str.trim().is_empty() {
                Vec::new()
            } else {
                op_str.split(',')
                    .map(|s| s.trim())
                    .map(|s| (s, Self::get_opnd_width(s)))
                    .collect()
            };
        Some(Instruction::new(&mnemonic,
                              &opnds))

    }
}

include!("x86_64_gen.rs");

#[test]
fn test_disassemble() {
    let out = X86_64::disassemble(&[0xff, 0x25, 0x42, 0x7e, 0x21, 0x00], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x48, 0x89, 0xE0], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x89, 0xC0], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0xAA], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x48, 0xA3, 0x00, 0x90, 0x9A,
                                    0x93, 0xE6, 0x7F, 0x00, 0x00], 0x1000);
    debugln!("{:?}", out);

}

#[test]
fn test_assemble() {
    let out = X86_64::assemble("mov eax, 0x10");
    //debugln!("{:?}", out);
    assert_eq!(true, out.is_some());
    // Test the pre defined code
    let def = X86_64::gen_definition();
    // Epilogue
    let epilogue = def.epilogue;
    let parsed_epilogue = epilogue.replace("%0", "0x40ffff");
    let asm_epilogue = X86_64::assemble(&parsed_epilogue);
    //debugln!("{:?}", asm_epilogue);
    assert_eq!(true, asm_epilogue.is_some());
    // Prologue
    let prologue = def.prologue;
    let parsed_prologue = prologue.replace("%0", "0x40ffff");
    let asm_prologue = X86_64::assemble(&parsed_prologue);
    //debugln!("{:?}", asm_prologue);
    assert_eq!(true, asm_prologue.is_some());
}
<commit_msg>X86_64::disassemble now can return None in case it failed<commit_after>use assembler::Assemble;
use disassembler::Disassemble;
use native::{Arch, Instruction};
//use definitions::{RegDefinition, SubRegDefinition, Definition, GenDefinition};

//use std::collections::HashMap;

#[allow(non_camel_case_types)]
pub struct X86_64;

impl X86_64 {
    fn get_opnd_width(opnd: &str) -> Option<u32> {
        let definition = Self::gen_definition();
        if definition.has_reg(opnd) {
            Some(definition.get_reg_width(opnd))
        } else {
            // Parse it, it's (probably?) a memory pointer
            if opnd.starts_with("dword ptr") {
                Some(32)
            } else if opnd.starts_with("qword ptr") {
                Some(64)
            } else if opnd.starts_with("byte ptr") {
                Some(8)
            } else {
                None
            }
        }
    }
}

impl Assemble for X86_64 {
    fn assemble(text: &str) -> Option<Vec<u8>> {
        Self::assemble_text(Arch::X86_64, text)
    }
}

impl Disassemble for X86_64 {
    // XXX_ this could be improved, making Instruction a better
    // representation of the operands in a generic way so it's parsed
    // once by `disassemble` instead of every time it's needed by some
    // other function.
    fn get_registers(ins: &Instruction) -> Vec<&'static str> {
        let mut res = Vec::new();
        let def = Self::gen_definition();
        for opnd in &ins.opnds {
            let t = opnd.text().to_uppercase();
            // Try to match Reg or SubReg
            for &reg_name in def.regs.keys().chain(def.sub_regs.keys()) {
                // XXX_ contains can match name parts (AX in EAX)
                // if t.contains(reg_name) {
                if t == reg_name {
                    res.push(reg_name);
                }
            }
        }
        res
    }

    fn disassemble(bytes: &[u8], address: u64) -> Option<Instruction> {
        if let Some(disas) =
            Self::disassemble_arch(Arch::X86_64, bytes, address)
        {
            let (mnemonic, op_str) = disas;
            let opnds: Vec<(&str, Option<u32>)> =
                if op_str.trim().is_empty() {
                    Vec::new()
                } else {
                    op_str.split(',')
                        .map(|s| s.trim())
                        .map(|s| (s, Self::get_opnd_width(s)))
                        .collect()
                };
            Some(Instruction::new(&mnemonic,
                                  &opnds))

        } else {
            None
        }
    }
}

include!("x86_64_gen.rs");

#[test]
fn test_disassemble() {
    let out = X86_64::disassemble(&[0xff, 0x25, 0x42, 0x7e, 0x21, 0x00], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x48, 0x89, 0xE0], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x89, 0xC0], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0xAA], 0x1000);
    debugln!("{:?}", out);
    let out = X86_64::disassemble(&[0x48, 0xA3, 0x00, 0x90, 0x9A,
                                    0x93, 0xE6, 0x7F, 0x00, 0x00], 0x1000);
    debugln!("{:?}", out);

}

#[test]
fn test_assemble() {
    let out = X86_64::assemble("mov eax, 0x10");
    //debugln!("{:?}", out);
    assert_eq!(true, out.is_some());
    // Test the pre defined code
    let def = X86_64::gen_definition();
    // Epilogue
    let epilogue = def.epilogue;
    let parsed_epilogue = epilogue.replace("%0", "0x40ffff");
    let asm_epilogue = X86_64::assemble(&parsed_epilogue);
    //debugln!("{:?}", asm_epilogue);
    assert_eq!(true, asm_epilogue.is_some());
    // Prologue
    let prologue = def.prologue;
    let parsed_prologue = prologue.replace("%0", "0x40ffff");
    let asm_prologue = X86_64::assemble(&parsed_prologue);
    //debugln!("{:?}", asm_prologue);
    assert_eq!(true, asm_prologue.is_some());
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

extern crate device_tree_source;
extern crate walkdir;
extern crate mktemp;
extern crate test;

use std::env::args;
use std::process::Command;
use std::path::{PathBuf, Path};

use walkdir::WalkDir;
use mktemp::Temp;

use test::{test_main, TestDesc, TestDescAndFn, DynTestName, DynTestFn, ShouldPanic};

use device_tree_source::parser::{ParseResult, parse_dt};
use device_tree_source::include::{IncludeError, include_files};

fn main() {
    let args: Vec<_> = args().collect();

    let new_dir = PathBuf::from(::std::env::var("CARGO_MANIFEST_DIR").unwrap())
                         .join("tests/dts");
    ::std::env::set_current_dir(&new_dir)
        .expect("Could not change current directory. Does tests/dts exist?");

    let tests = WalkDir::new(".")
                       .follow_links(true)
                       .into_iter()
                       .filter_map(|e| e.ok())
                       .filter(|e| e.file_name().to_string_lossy().ends_with(".dts"))
                       .map(|d| d.path().to_owned())
                       .map(|p| {
                           TestDescAndFn {
                               desc: TestDesc {
                                   name: DynTestName(format!("{}", p.display())),
                                   ignore: true,
                                   should_panic: ShouldPanic::No,
                               },
                               testfn: DynTestFn(Box::new(move || try_parse(&p.clone()))),
                           }
                       })
                       .collect();
    test_main(&args, tests);
}

fn try_parse(file: &PathBuf) {
    let mut cpp_temp_out = Temp::new_file().expect("Could not create temp file");
    let mut include_dirs = Vec::new();

    let mut cpp_command = Command::new("gcc");
    cpp_command.args(&["-E", "-nostdinc"])
               .args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
               .args(&["-o", cpp_temp_out.as_ref().to_str().unwrap()])
               .arg(file.to_str().unwrap())
               .args(&["-I", "."]);
    include_dirs.push(PathBuf::from("."));

    if Path::new("include").is_dir() {
        cpp_command.args(&["-I", "include/"]);
        include_dirs.push(PathBuf::from("include/"));
    }

    if let Some(parent) = file.parent() {
        cpp_command.args(&["-I", &parent.to_string_lossy()]);
        include_dirs.push(parent.to_owned());

        let include = parent.join("include");
        if include.is_dir() {
            cpp_command.args(&["-I", &include.to_string_lossy()]);
            include_dirs.push(include);
        }
    } else {
        panic!("Could not get parent directory of file");
    }

    let include_output = cpp_command.output().expect("Failed to start CPP");

    if !include_output.status.success() {
        // Done to prevent a panic as the file will not have been written to
        cpp_temp_out.release();
        panic!("Failed to execute CPP.\n{:?}\n{}",
               cpp_command,
               String::from_utf8_lossy(&include_output.stderr));
    }

    let (buffer, bounds) = match include_files(&cpp_temp_out, &include_dirs) {
        Ok(x) => x,
        Err(e) => {
            match e {
                IncludeError::IOError(err, path) => {
                    if let Some(path) = path {
                        panic!("IO error: {} {}", err, path.display());
                    } else {
                        panic!("IO error: {}", err);
                    }
                }
                IncludeError::LinemarkerInDtsi(path) =>
                    panic!("Extraneous linemarker found in DT include: {}",
                           path.to_string_lossy()),
                IncludeError::ParseError(_) =>
                    panic!("Failed to convert line to byte offset for bounds tracking."),
                IncludeError::NoBoundReturned(path) =>
                    panic!("No bounds returned after parsing file: {}", path.to_string_lossy()),
            }
        }
    };

    // println!("{:#?}", bounds);

    match parse_dt(&buffer) {
        Ok(ParseResult::Complete(..)) => {},
        Ok(ParseResult::RemainingInput(dt_info, amends, rem)) => {
            // println!("DT Info:\n{:#?}", dt_info);
            // println!("Amends:\n{:#?}", amends);
            panic!("Input remaining after parsing:\n{}", String::from_utf8_lossy(rem));
        }
        Err(err) => {
            // println!("{:#?}", bounds);
            // println!("{}", String::from_utf8_lossy(&buffer));
            panic!("{:?}", err);
        }
    }
}
<commit_msg>Change iter_dts_files to first check for a DTS_DIR enviroment variable<commit_after>#![allow(unused_variables)]

extern crate device_tree_source;
extern crate walkdir;
extern crate mktemp;
extern crate test;

use std::env::args;
use std::process::Command;
use std::path::{PathBuf, Path};

use walkdir::WalkDir;
use mktemp::Temp;

use test::{test_main, TestDesc, TestDescAndFn, DynTestName, DynTestFn, ShouldPanic};

use device_tree_source::parser::{ParseResult, parse_dt};
use device_tree_source::include::{IncludeError, include_files};

fn main() {
    let args: Vec<_> = args().collect();

    let new_dir = ::std::env::var("DTS_DIR")
                            .map(|env| PathBuf::from(env))
                            .or_else(|_| ::std::env::var("CARGO_MANIFEST_DIR")
                                                  .map(|env| PathBuf::from(env).join("tests/dts")));
    match new_dir {
        Ok(new_dir) => {
            if let Err(_) = ::std::env::set_current_dir(&new_dir) {
                println!("\nCould not change current directory. Does tests/dts exist?\n");
                return
            }
        }
        Err(_) => {
            println!("Both DTS_DIR and CARGO_MANIFEST_DIR unset!");
            return
        }
    }

    let tests = WalkDir::new(".")
                       .follow_links(true)
                       .into_iter()
                       .filter_map(|e| e.ok())
                       .filter(|e| e.file_name().to_string_lossy().ends_with(".dts"))
                       .map(|d| d.path().to_owned())
                       .map(|p| {
                           TestDescAndFn {
                               desc: TestDesc {
                                   name: DynTestName(format!("{}", p.display())),
                                   ignore: true,
                                   should_panic: ShouldPanic::No,
                               },
                               testfn: DynTestFn(Box::new(move || try_parse(&p.clone()))),
                           }
                       })
                       .collect();
    test_main(&args, tests);
}

fn try_parse(file: &PathBuf) {
    let mut cpp_temp_out = Temp::new_file().expect("Could not create temp file");
    let mut include_dirs = Vec::new();

    let mut cpp_command = Command::new("gcc");
    cpp_command.args(&["-E", "-nostdinc"])
               .args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
               .args(&["-o", cpp_temp_out.as_ref().to_str().unwrap()])
               .arg(file.to_str().unwrap())
               .args(&["-I", "."]);
    include_dirs.push(PathBuf::from("."));

    if Path::new("include").is_dir() {
        cpp_command.args(&["-I", "include/"]);
        include_dirs.push(PathBuf::from("include/"));
    }

    if let Some(parent) = file.parent() {
        cpp_command.args(&["-I", &parent.to_string_lossy()]);
        include_dirs.push(parent.to_owned());

        let include = parent.join("include");
        if include.is_dir() {
            cpp_command.args(&["-I", &include.to_string_lossy()]);
            include_dirs.push(include);
        }
    } else {
        panic!("Could not get parent directory of file");
    }

    let include_output = cpp_command.output().expect("Failed to start CPP");

    if !include_output.status.success() {
        // Done to prevent a panic as the file will not have been written to
        cpp_temp_out.release();
        panic!("Failed to execute CPP.\n{:?}\n{}",
               cpp_command,
               String::from_utf8_lossy(&include_output.stderr));
    }

    let (buffer, bounds) = match include_files(&cpp_temp_out, &include_dirs) {
        Ok(x) => x,
        Err(e) => {
            match e {
                IncludeError::IOError(err, path) => {
                    if let Some(path) = path {
                        panic!("IO error: {} {}", err, path.display());
                    } else {
                        panic!("IO error: {}", err);
                    }
                }
                IncludeError::LinemarkerInDtsi(path) =>
                    panic!("Extraneous linemarker found in DT include: {}",
                           path.to_string_lossy()),
                IncludeError::ParseError(_) =>
                    panic!("Failed to convert line to byte offset for bounds tracking."),
                IncludeError::NoBoundReturned(path) =>
                    panic!("No bounds returned after parsing file: {}", path.to_string_lossy()),
            }
        }
    };

    // println!("{:#?}", bounds);

    match parse_dt(&buffer) {
        Ok(ParseResult::Complete(..)) => {},
        Ok(ParseResult::RemainingInput(dt_info, amends, rem)) => {
            // println!("DT Info:\n{:#?}", dt_info);
            // println!("Amends:\n{:#?}", amends);
            panic!("Input remaining after parsing:\n{}", String::from_utf8_lossy(rem));
        }
        Err(err) => {
            // println!("{:#?}", bounds);
            // println!("{}", String::from_utf8_lossy(&buffer));
            panic!("{:?}", err);
        }
    }
}
<|endoftext|>


<commit_before>struct Point { x: i32, y: i32, z: i32 }

fn main() {
    let mut point = Point { x: 0, y: 0, z: 0 };

    {
        let borrowed_point = &point;
        let another_borrow = &point;

        // 通过引用和原始所有者来访问数据
        println!("Point has coordinates: ({}, {}, {})",
                 borrowed_point.x, another_borrow.y, point.z);

        // 报错！不能借用 `point` 作为可变内容，因为目前已被借用成为
        // 不可变内容。
        //let mutable_borrow = &mut point;
        // 动手试一试 ^ 将此行注释去掉。

        // 不可变引用离开作用域
    }

    {
        let mutable_borrow = &mut point;

        // 通过可变引用来改变数据
        mutable_borrow.x = 5;
        mutable_borrow.y = 2;
        mutable_borrow.z = 1;

        // 报错！不能借用 `point` 作为不可变内容，因为目前它已被借用成为
        // 可变内容。
        //let y = &point.y;
        // 动手试一试 ^ 将此行注释去掉。

        // 报错！不能打印，因为 `println!` 接受了一个不可变引用。
        //println!("Point Z coordinate is {}", point.z);
        // 动手试一试 ^ 将此行注释去掉。

        // 可变引用离开作用域
    }

    // `point` 的不可变引用再次可用。
    println!("Point now has coordinates: ({}, {}, {})",
             point.x, point.y, point.z);
}
<commit_msg>Clarify single mutable reference vs mutliple references<commit_after>struct Point { x: i32, y: i32, z: i32 }

fn main() {
    let mut point = Point { x: 0, y: 0, z: 0 };

    {
        let borrowed_point = &point;
        let another_borrow = &point;

        // 通过引用和原始所有者来访问数据
        println!("Point has coordinates: ({}, {}, {})",
                 borrowed_point.x, another_borrow.y, point.z);

        // 报错！不能借用 `point` 作为可变内容，因为目前已被借用成为
        // 不可变内容。
        //let mutable_borrow = &mut point;
        // 动手试一试 ^ 将此行注释去掉。

        // 不可变引用离开作用域
    }

    {
        let mutable_borrow = &mut point;

        // 通过可变引用来改变数据
        mutable_borrow.x = 5;
        mutable_borrow.y = 2;
        mutable_borrow.z = 1;

        // 报错！不能借用 `point` 作为不可变内容，因为目前它已被借用成为
        // 可变内容。
        //let y = &point.y;
        // 动手试一试 ^ 将此行注释去掉。

        // 报错！不能打印，因为 `println!` 接受了一个不可变引用。
        //println!("Point Z coordinate is {}", point.z);
        // 动手试一试 ^ 将此行注释去掉。

        // 好！可变引用可以作为不可变的传给 `println!`。
        println!("Point has coordinates: ({}, {}, {})",
                 mutable_borrow.x, mutable_borrow.y, mutable_borrow.z);

        // 可变引用离开作用域
    }

    // `point` 的不可变引用再次可用。
    let borrow_point = &point;
    println!("Point now has coordinates: ({}, {}, {})",
             borrowed_point.x, borrowed_point.y, borrowed_point.z);
}
<|endoftext|>


<commit_before>use self::build_tables::build_tables;
use self::parse_grammar::parse_grammar;
use self::prepare_grammar::prepare_grammar;
use self::render::render_c_code;
use crate::error::{Error, Result};
use lazy_static::lazy_static;
use regex::{Regex, RegexBuilder};
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, Stdio};

mod build_tables;
mod grammars;
mod nfa;
mod npm_files;
mod parse_grammar;
mod prepare_grammar;
mod render;
mod rules;
mod tables;

lazy_static! {
    static ref JSON_COMMENT_REGEX: Regex = RegexBuilder::new("^\\s*//.*")
        .multi_line(true)
        .build()
        .unwrap();
}

pub fn generate_parser_in_directory(
    repo_path: &PathBuf,
    grammar_path: Option<&str>,
    minimize: bool,
    state_ids_to_log: Vec<usize>,
) -> Result<()> {
    let grammar_path = grammar_path.map_or(repo_path.join("grammar.js"), |s| s.into());
    let grammar_json = load_grammar_file(&grammar_path)?;
    let (language_name, c_code) =
        generate_parser_for_grammar_with_opts(&grammar_json, minimize, state_ids_to_log)?;
    let repo_src_path = repo_path.join("src");
    let repo_header_path = repo_src_path.join("tree_sitter");
    fs::create_dir_all(&repo_src_path)?;
    fs::create_dir_all(&repo_header_path)?;
    fs::write(&repo_src_path.join("parser.c"), c_code)
        .map_err(|e| format!("Failed to write parser.c: {}", e))?;
    ensure_file(&repo_src_path.join("binding.cc"), || {
        npm_files::binding_cc(&language_name)
    })?;
    ensure_file(&repo_path.join("binding.gyp"), || {
        npm_files::binding_gyp(&language_name)
    })?;
    ensure_file(&repo_path.join("index.js"), || {
        npm_files::index_js(&language_name)
    })?;
    ensure_file(&repo_header_path.join("parser.h"), || {
        tree_sitter::PARSER_HEADER
    })?;
    Ok(())
}

pub fn generate_parser_for_grammar(grammar_json: &str) -> Result<(String, String)> {
    let grammar_json = JSON_COMMENT_REGEX.replace_all(grammar_json, "\n");
    generate_parser_for_grammar_with_opts(&grammar_json, true, Vec::new())
}

fn generate_parser_for_grammar_with_opts(
    grammar_json: &str,
    minimize: bool,
    state_ids_to_log: Vec<usize>,
) -> Result<(String, String)> {
    let input_grammar = parse_grammar(grammar_json)?;
    let (syntax_grammar, lexical_grammar, inlines, simple_aliases) =
        prepare_grammar(&input_grammar)?;
    let (parse_table, main_lex_table, keyword_lex_table, keyword_capture_token) = build_tables(
        &syntax_grammar,
        &lexical_grammar,
        &simple_aliases,
        &inlines,
        minimize,
        state_ids_to_log,
    )?;
    let c_code = render_c_code(
        &input_grammar.name,
        parse_table,
        main_lex_table,
        keyword_lex_table,
        keyword_capture_token,
        syntax_grammar,
        lexical_grammar,
        simple_aliases,
    );
    Ok((input_grammar.name, c_code))
}

fn load_grammar_file(grammar_path: &PathBuf) -> Result<String> {
    match grammar_path.extension().and_then(|e| e.to_str()) {
        Some("js") => Ok(load_js_grammar_file(grammar_path)?),
        Some("json") => Ok(fs::read_to_string(grammar_path)?),
        _ => Err(Error(format!(
            "Unknown grammar file extension: {:?}",
            grammar_path
        ))),
    }
}

fn load_js_grammar_file(grammar_path: &PathBuf) -> Result<String> {
    let mut node_process = Command::new("node")
        .env("TREE_SITTER_GRAMMAR_PATH", grammar_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Failed to run `node`");

    let mut node_stdin = node_process
        .stdin
        .take()
        .expect("Failed to open stdin for node");
    let javascript_code = include_bytes!("./dsl.js");
    node_stdin
        .write(javascript_code)
        .expect("Failed to write to node's stdin");
    drop(node_stdin);
    let output = node_process
        .wait_with_output()
        .expect("Failed to read output from node");
    match output.status.code() {
        None => panic!("Node process was killed"),
        Some(0) => {}
        Some(code) => return Err(Error(format!("Node process exited with status {}", code))),
    }

    Ok(String::from_utf8(output.stdout).expect("Got invalid UTF8 from node"))
}

fn ensure_file<T: AsRef<[u8]>>(path: &PathBuf, f: impl Fn() -> T) -> Result<()> {
    if path.exists() {
        Ok(())
    } else {
        fs::write(path, f().as_ref())
            .map_err(|e| Error(format!("Failed to write file {:?}: {}", path, e)))
    }
}
<commit_msg>Write grammar.json file when generating based on grammar.js<commit_after>use self::build_tables::build_tables;
use self::parse_grammar::parse_grammar;
use self::prepare_grammar::prepare_grammar;
use self::render::render_c_code;
use crate::error::{Error, Result};
use lazy_static::lazy_static;
use regex::{Regex, RegexBuilder};
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

mod build_tables;
mod grammars;
mod nfa;
mod npm_files;
mod parse_grammar;
mod prepare_grammar;
mod render;
mod rules;
mod tables;

lazy_static! {
    static ref JSON_COMMENT_REGEX: Regex = RegexBuilder::new("^\\s*//.*")
        .multi_line(true)
        .build()
        .unwrap();
}

pub fn generate_parser_in_directory(
    repo_path: &PathBuf,
    grammar_path: Option<&str>,
    minimize: bool,
    state_ids_to_log: Vec<usize>,
) -> Result<()> {
    let repo_src_path = repo_path.join("src");

    let grammar_json;
    match grammar_path {
        Some(path) => {
            grammar_json = load_grammar_file(path.as_ref())?;
        }
        None => {
            let grammar_js_path = grammar_path.map_or(repo_path.join("grammar.js"), |s| s.into());
            grammar_json = load_grammar_file(&grammar_js_path)?;
            fs::write(&repo_src_path.join("grammar.json"), &grammar_json)?;
        }
    }

    let (language_name, c_code) =
        generate_parser_for_grammar_with_opts(&grammar_json, minimize, state_ids_to_log)?;
    let repo_header_path = repo_src_path.join("tree_sitter");
    fs::create_dir_all(&repo_src_path)?;
    fs::create_dir_all(&repo_header_path)?;
    fs::write(&repo_src_path.join("parser.c"), c_code)
        .map_err(|e| format!("Failed to write parser.c: {}", e))?;
    ensure_file(&repo_src_path.join("binding.cc"), || {
        npm_files::binding_cc(&language_name)
    })?;
    ensure_file(&repo_path.join("binding.gyp"), || {
        npm_files::binding_gyp(&language_name)
    })?;
    ensure_file(&repo_path.join("index.js"), || {
        npm_files::index_js(&language_name)
    })?;
    ensure_file(&repo_header_path.join("parser.h"), || {
        tree_sitter::PARSER_HEADER
    })?;
    Ok(())
}

pub fn generate_parser_for_grammar(grammar_json: &str) -> Result<(String, String)> {
    let grammar_json = JSON_COMMENT_REGEX.replace_all(grammar_json, "\n");
    generate_parser_for_grammar_with_opts(&grammar_json, true, Vec::new())
}

fn generate_parser_for_grammar_with_opts(
    grammar_json: &str,
    minimize: bool,
    state_ids_to_log: Vec<usize>,
) -> Result<(String, String)> {
    let input_grammar = parse_grammar(grammar_json)?;
    let (syntax_grammar, lexical_grammar, inlines, simple_aliases) =
        prepare_grammar(&input_grammar)?;
    let (parse_table, main_lex_table, keyword_lex_table, keyword_capture_token) = build_tables(
        &syntax_grammar,
        &lexical_grammar,
        &simple_aliases,
        &inlines,
        minimize,
        state_ids_to_log,
    )?;
    let c_code = render_c_code(
        &input_grammar.name,
        parse_table,
        main_lex_table,
        keyword_lex_table,
        keyword_capture_token,
        syntax_grammar,
        lexical_grammar,
        simple_aliases,
    );
    Ok((input_grammar.name, c_code))
}

fn load_grammar_file(grammar_path: &Path) -> Result<String> {
    match grammar_path.extension().and_then(|e| e.to_str()) {
        Some("js") => Ok(load_js_grammar_file(grammar_path)?),
        Some("json") => Ok(fs::read_to_string(grammar_path)?),
        _ => Err(Error(format!(
            "Unknown grammar file extension: {:?}",
            grammar_path
        ))),
    }
}

fn load_js_grammar_file(grammar_path: &Path) -> Result<String> {
    let mut node_process = Command::new("node")
        .env("TREE_SITTER_GRAMMAR_PATH", grammar_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Failed to run `node`");

    let mut node_stdin = node_process
        .stdin
        .take()
        .expect("Failed to open stdin for node");
    let javascript_code = include_bytes!("./dsl.js");
    node_stdin
        .write(javascript_code)
        .expect("Failed to write to node's stdin");
    drop(node_stdin);
    let output = node_process
        .wait_with_output()
        .expect("Failed to read output from node");
    match output.status.code() {
        None => panic!("Node process was killed"),
        Some(0) => {}
        Some(code) => return Err(Error(format!("Node process exited with status {}", code))),
    }

    Ok(String::from_utf8(output.stdout).expect("Got invalid UTF8 from node"))
}

fn ensure_file<T: AsRef<[u8]>>(path: &PathBuf, f: impl Fn() -> T) -> Result<()> {
    if path.exists() {
        Ok(())
    } else {
        fs::write(path, f().as_ref())
            .map_err(|e| Error(format!("Failed to write file {:?}: {}", path, e)))
    }
}
<|endoftext|>


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

use std::{io, os, str, run, task};
use extra::{tempfile, json};
use extra::json::ToJson;

use super::*;

fn write_whole_file(path: &Path, data: &str) {
    match io::file_writer(path, [io::Create]) {
        Ok(writer) => writer.write_str(data),
        Err(message) => fail!(message),
    }
}

fn almost_equals(a: &json::Json, b: &json::Json) -> bool {
    match (a, b) {
        (&json::Number(a), &json::Number(b)) => (a - b).abs() < 1e-6,
        (&json::String(ref a), &json::String(ref b)) => a == b,
        (&json::Boolean(a), &json::Boolean(b)) => a == b,
        (&json::List(ref a), &json::List(ref b))
            => a.iter().zip(b.iter()).all(|(ref a, ref b)| almost_equals(*a, *b)),
        (&json::Object(_), &json::Object(_)) => fail!(~"Not implemented"),
        (&json::Null, &json::Null) => true,
        _ => false,
    }
}

fn assert_json_eq(results: json::Json, expected: json::Json, message: ~str) {
    if !almost_equals(&results, &expected) {
        let temp = tempfile::mkdtemp(&os::tmpdir(), "rust-cssparser-tests").unwrap();
        let temp_ = temp.clone();
        let results = results.to_pretty_str() + "\n";
        let expected = expected.to_pretty_str() + "\n";
        do task::try {
            let result_path = temp.push("results.json");
            let expected_path = temp.push("expected.json");
            write_whole_file(&result_path, results);
            write_whole_file(&expected_path, expected);
            run::process_status("colordiff", [~"-u1000", result_path.to_str(),
                                              expected_path.to_str()]);
        };
        os::remove_dir_recursive(&temp_);

        fail!(message)
    }
}

fn run_json_tests<T: ToJson>(json_data: &str, parse: &fn (input: ~str) -> T) {
    let items = match json::from_str(json_data) {
        Ok(json::List(items)) => items,
        _ => fail!("Invalid JSON")
    };
    assert!(items.len() % 2 == 0);
    let mut input: Option<~str> = None;
    for item in items.move_iter() {
        match (&input, item) {
            (&None, json::String(string)) => input = Some(string),
            (&Some(_), expected) => {
                let input = input.take_unwrap();
                let result = parse(input.to_owned()).to_json();
                assert_json_eq(result, expected, input);
            },
            _ => fail!("Unexpected JSON")
        };
    }
}

#[test]
fn component_value_list() {
    do run_json_tests(include_str!("css-parsing-tests/component_value_list.json")) |input| {
        tokenize(input).map(|(c, _)| c).to_owned_vec()
    }
}

#[test]
fn one_component_value() {
    do run_json_tests(include_str!("css-parsing-tests/one_component_value.json")) |input| {
        parse_one_component_value(tokenize(input))
    }
}

#[test]
fn declaration_list() {
    do run_json_tests(include_str!("css-parsing-tests/declaration_list.json")) |input| {
        parse_declaration_list(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn one_declaration() {
    do run_json_tests(include_str!("css-parsing-tests/one_declaration.json")) |input| {
        parse_one_declaration(tokenize(input))
    }
}

#[test]
fn rule_list() {
    do run_json_tests(include_str!("css-parsing-tests/rule_list.json")) |input| {
        parse_rule_list(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn stylesheet() {
    do run_json_tests(include_str!("css-parsing-tests/stylesheet.json")) |input| {
        parse_stylesheet_rules(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn one_rule() {
    do run_json_tests(include_str!("css-parsing-tests/one_rule.json")) |input| {
        parse_one_rule(tokenize(input))
    }
}

fn run_color_tests(json_data: &str, to_json: &fn(result: Option<Color>) -> json::Json) {
    do run_json_tests(json_data) |input| {
        match parse_one_component_value(tokenize(input)) {
            Ok(component_value) => to_json(Color::parse(&component_value)),
            Err(_reason) => json::Null,
        }
    }
}

#[test]
fn color3() {
    run_color_tests(include_str!("css-parsing-tests/color3.json"), |c| c.to_json())
}

#[test]
fn color3_hsl() {
    run_color_tests(include_str!("css-parsing-tests/color3_hsl.json"), |c| c.to_json())
}

/// color3_keywords.json is different: R, G and B are in 0..255 rather than 0..1
#[test]
fn color3_keywords() {
    do run_color_tests(include_str!("css-parsing-tests/color3_keywords.json")) |c| {
        match c {
            Some(RGBA(RGBA { red: r, green: g, blue: b, alpha: a }))
            => (~[r * 255., g * 255., b * 255., a]).to_json(),
            Some(CurrentColor) => json::String(~"currentColor"),
            None => json::Null,
        }
    }
}

#[test]
fn nth() {
    do run_json_tests(include_str!("css-parsing-tests/An+B.json")) |input| {
        parse_nth(tokenize(input).map(|(c, _)| c).to_owned_vec())
    }
}

impl ToJson for Result<Rule, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<DeclarationListItem, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<Declaration, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<ComponentValue, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for SyntaxError {
    fn to_json(&self) -> json::Json {
        json::List(~[json::String(~"error"), json::String(match self.reason {
            ErrEmptyInput => ~"empty",
            ErrExtraInput => ~"extra-input",
            _ => ~"invalid",
        })])
    }
}

impl ToJson for Color {
    fn to_json(&self) -> json::Json {
        match *self {
            RGBA(RGBA { red: r, green: g, blue: b, alpha: a }) => (~[r, g, b, a]).to_json(),
            CurrentColor => json::String(~"currentColor"),
        }
    }
}

impl ToJson for Rule {
    fn to_json(&self) -> json::Json {
        match *self {
            QualifiedRule(ref rule) => rule.to_json(),
            AtRule(ref rule) => rule.to_json(),
        }
    }
}

impl ToJson for DeclarationListItem {
    fn to_json(&self) -> json::Json {
        match *self {
            Declaration(ref declaration) => declaration.to_json(),
            Decl_AtRule(ref at_rule) => at_rule.to_json(),
        }
    }
}

fn list_to_json(list: &~[(ComponentValue, SourceLocation)]) -> ~[json::Json] {
    list.map(|tuple| {
        match *tuple {
            (ref c, _) => c.to_json()
        }
    })
}

impl ToJson for AtRule {
    fn to_json(&self) -> json::Json {
        match *self {
            AtRule{name: ref name, prelude: ref prelude, block: ref block, _}
            => json::List(~[json::String(~"at-rule"), name.to_json(),
                            prelude.to_json(), block.map(list_to_json).to_json()])
        }
    }
}

impl ToJson for QualifiedRule {
    fn to_json(&self) -> json::Json {
        match *self {
            QualifiedRule{prelude: ref prelude, block: ref block, _}
            => json::List(~[json::String(~"qualified rule"),
                            prelude.to_json(), json::List(list_to_json(block))])
        }
    }
}

impl ToJson for Declaration {
    fn to_json(&self) -> json::Json {
        match *self {
            Declaration{name: ref name, value: ref value, important: ref important, _}
            =>  json::List(~[json::String(~"declaration"), name.to_json(),
                             value.to_json(), important.to_json()])
        }
    }
}

impl ToJson for ComponentValue {
    fn to_json(&self) -> json::Json {
        use JList = extra::json::List;
        use JString = extra::json::String;

        fn numeric(value: &NumericValue) -> ~[json::Json] {
            match *value {
                NumericValue{representation: ref r, value: ref v, int_value: ref i}
                => ~[r.to_json(), v.to_json(),
                     JString(match *i { Some(_) => ~"integer", _ => ~"number" })]
            }
        }

        match *self {
            Ident(ref value) => JList(~[JString(~"ident"), value.to_json()]),
            AtKeyword(ref value) => JList(~[JString(~"at-keyword"), value.to_json()]),
            Hash(ref value) => JList(~[JString(~"hash"), value.to_json(),
                                       JString(~"unrestricted")]),
            IDHash(ref value) => JList(~[JString(~"hash"), value.to_json(), JString(~"id")]),
            String(ref value) => JList(~[JString(~"string"), value.to_json()]),
            URL(ref value) => JList(~[JString(~"url"), value.to_json()]),
            Delim('\\') => JString(~"\\"),
            Delim(value) => JString(str::from_char(value)),

            Number(ref value) => JList(~[JString(~"number")] + numeric(value)),
            Percentage(ref value) => JList(~[JString(~"percentage")] + numeric(value)),
            Dimension(ref value, ref unit)
            => JList(~[JString(~"dimension")] + numeric(value) + ~[unit.to_json()]),

            UnicodeRange { start: s, end: e }
            => JList(~[JString(~"unicode-range"), s.to_json(), e.to_json()]),

            WhiteSpace => JString(~" "),
            Colon => JString(~":"),
            Semicolon => JString(~";"),
            Comma => JString(~","),
            IncludeMatch => JString(~"~="),
            DashMatch => JString(~"|="),
            PrefixMatch => JString(~"^="),
            SuffixMatch => JString(~"$="),
            SubstringMatch => JString(~"*="),
            Column => JString(~"||"),
            CDO => JString(~"<!--"),
            CDC => JString(~"-->"),

            Function(ref name, ref arguments)
            => JList(~[JString(~"function"), name.to_json()] + arguments.map(|a| a.to_json())),
            ParenthesisBlock(ref content)
            => JList(~[JString(~"()")] + content.map(|c| c.to_json())),
            SquareBracketBlock(ref content)
            => JList(~[JString(~"[]")] + content.map(|c| c.to_json())),
            CurlyBracketBlock(ref content)
            => JList(~[JString(~"{}")] + list_to_json(content)),

            BadURL => JList(~[JString(~"error"), JString(~"bad-url")]),
            BadString => JList(~[JString(~"error"), JString(~"bad-string")]),
            CloseParenthesis => JList(~[JString(~"error"), JString(~")")]),
            CloseSquareBracket => JList(~[JString(~"error"), JString(~"]")]),
            CloseCurlyBracket => JList(~[JString(~"error"), JString(~"}")]),
        }
    }
}
<commit_msg>Upgrade to latest Rust.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::{io, str, run, task};
use extra::{tempfile, json};
use extra::json::ToJson;

use super::*;

fn write_whole_file(path: &Path, data: &str) {
    match io::file_writer(path, [io::Create]) {
        Ok(writer) => writer.write_str(data),
        Err(message) => fail!(message),
    }
}

fn almost_equals(a: &json::Json, b: &json::Json) -> bool {
    match (a, b) {
        (&json::Number(a), &json::Number(b)) => (a - b).abs() < 1e-6,
        (&json::String(ref a), &json::String(ref b)) => a == b,
        (&json::Boolean(a), &json::Boolean(b)) => a == b,
        (&json::List(ref a), &json::List(ref b))
            => a.iter().zip(b.iter()).all(|(ref a, ref b)| almost_equals(*a, *b)),
        (&json::Object(_), &json::Object(_)) => fail!(~"Not implemented"),
        (&json::Null, &json::Null) => true,
        _ => false,
    }
}

fn assert_json_eq(results: json::Json, expected: json::Json, message: ~str) {
    if !almost_equals(&results, &expected) {
        let temp = tempfile::TempDir::new("rust-cssparser-tests").unwrap();
        let results = results.to_pretty_str() + "\n";
        let expected = expected.to_pretty_str() + "\n";
        do task::try {
            let mut result_path = temp.path().clone();
            result_path.push("results.json");
            let mut expected_path = temp.path().clone();
            expected_path.push("expected.json");
            write_whole_file(&result_path, results);
            write_whole_file(&expected_path, expected);
            run::process_status("colordiff", [~"-u1000", result_path.display().to_str(),
                                              expected_path.display().to_str()]);
        };

        fail!(message)
    }
}

fn run_json_tests<T: ToJson>(json_data: &str, parse: &fn (input: ~str) -> T) {
    let items = match json::from_str(json_data) {
        Ok(json::List(items)) => items,
        _ => fail!("Invalid JSON")
    };
    assert!(items.len() % 2 == 0);
    let mut input: Option<~str> = None;
    for item in items.move_iter() {
        match (&input, item) {
            (&None, json::String(string)) => input = Some(string),
            (&Some(_), expected) => {
                let input = input.take_unwrap();
                let result = parse(input.to_owned()).to_json();
                assert_json_eq(result, expected, input);
            },
            _ => fail!("Unexpected JSON")
        };
    }
}

#[test]
fn component_value_list() {
    do run_json_tests(include_str!("css-parsing-tests/component_value_list.json")) |input| {
        tokenize(input).map(|(c, _)| c).to_owned_vec()
    }
}

#[test]
fn one_component_value() {
    do run_json_tests(include_str!("css-parsing-tests/one_component_value.json")) |input| {
        parse_one_component_value(tokenize(input))
    }
}

#[test]
fn declaration_list() {
    do run_json_tests(include_str!("css-parsing-tests/declaration_list.json")) |input| {
        parse_declaration_list(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn one_declaration() {
    do run_json_tests(include_str!("css-parsing-tests/one_declaration.json")) |input| {
        parse_one_declaration(tokenize(input))
    }
}

#[test]
fn rule_list() {
    do run_json_tests(include_str!("css-parsing-tests/rule_list.json")) |input| {
        parse_rule_list(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn stylesheet() {
    do run_json_tests(include_str!("css-parsing-tests/stylesheet.json")) |input| {
        parse_stylesheet_rules(tokenize(input)).to_owned_vec()
    }
}

#[test]
fn one_rule() {
    do run_json_tests(include_str!("css-parsing-tests/one_rule.json")) |input| {
        parse_one_rule(tokenize(input))
    }
}

fn run_color_tests(json_data: &str, to_json: &fn(result: Option<Color>) -> json::Json) {
    do run_json_tests(json_data) |input| {
        match parse_one_component_value(tokenize(input)) {
            Ok(component_value) => to_json(Color::parse(&component_value)),
            Err(_reason) => json::Null,
        }
    }
}

#[test]
fn color3() {
    run_color_tests(include_str!("css-parsing-tests/color3.json"), |c| c.to_json())
}

#[test]
fn color3_hsl() {
    run_color_tests(include_str!("css-parsing-tests/color3_hsl.json"), |c| c.to_json())
}

/// color3_keywords.json is different: R, G and B are in 0..255 rather than 0..1
#[test]
fn color3_keywords() {
    do run_color_tests(include_str!("css-parsing-tests/color3_keywords.json")) |c| {
        match c {
            Some(RGBA(RGBA { red: r, green: g, blue: b, alpha: a }))
            => (~[r * 255., g * 255., b * 255., a]).to_json(),
            Some(CurrentColor) => json::String(~"currentColor"),
            None => json::Null,
        }
    }
}

#[test]
fn nth() {
    do run_json_tests(include_str!("css-parsing-tests/An+B.json")) |input| {
        parse_nth(tokenize(input).map(|(c, _)| c).to_owned_vec())
    }
}

impl ToJson for Result<Rule, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<DeclarationListItem, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<Declaration, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for Result<ComponentValue, SyntaxError> {
    fn to_json(&self) -> json::Json {
        match *self {
            Ok(ref a) => a.to_json(),
            Err(ref b) => b.to_json(),
        }
    }
}

impl ToJson for SyntaxError {
    fn to_json(&self) -> json::Json {
        json::List(~[json::String(~"error"), json::String(match self.reason {
            ErrEmptyInput => ~"empty",
            ErrExtraInput => ~"extra-input",
            _ => ~"invalid",
        })])
    }
}

impl ToJson for Color {
    fn to_json(&self) -> json::Json {
        match *self {
            RGBA(RGBA { red: r, green: g, blue: b, alpha: a }) => (~[r, g, b, a]).to_json(),
            CurrentColor => json::String(~"currentColor"),
        }
    }
}

impl ToJson for Rule {
    fn to_json(&self) -> json::Json {
        match *self {
            QualifiedRule(ref rule) => rule.to_json(),
            AtRule(ref rule) => rule.to_json(),
        }
    }
}

impl ToJson for DeclarationListItem {
    fn to_json(&self) -> json::Json {
        match *self {
            Declaration(ref declaration) => declaration.to_json(),
            Decl_AtRule(ref at_rule) => at_rule.to_json(),
        }
    }
}

fn list_to_json(list: &~[(ComponentValue, SourceLocation)]) -> ~[json::Json] {
    list.map(|tuple| {
        match *tuple {
            (ref c, _) => c.to_json()
        }
    })
}

impl ToJson for AtRule {
    fn to_json(&self) -> json::Json {
        match *self {
            AtRule{name: ref name, prelude: ref prelude, block: ref block, _}
            => json::List(~[json::String(~"at-rule"), name.to_json(),
                            prelude.to_json(), block.as_ref().map(list_to_json).to_json()])
        }
    }
}

impl ToJson for QualifiedRule {
    fn to_json(&self) -> json::Json {
        match *self {
            QualifiedRule{prelude: ref prelude, block: ref block, _}
            => json::List(~[json::String(~"qualified rule"),
                            prelude.to_json(), json::List(list_to_json(block))])
        }
    }
}

impl ToJson for Declaration {
    fn to_json(&self) -> json::Json {
        match *self {
            Declaration{name: ref name, value: ref value, important: ref important, _}
            =>  json::List(~[json::String(~"declaration"), name.to_json(),
                             value.to_json(), important.to_json()])
        }
    }
}

impl ToJson for ComponentValue {
    fn to_json(&self) -> json::Json {
        use JList = extra::json::List;
        use JString = extra::json::String;

        fn numeric(value: &NumericValue) -> ~[json::Json] {
            match *value {
                NumericValue{representation: ref r, value: ref v, int_value: ref i}
                => ~[r.to_json(), v.to_json(),
                     JString(match *i { Some(_) => ~"integer", _ => ~"number" })]
            }
        }

        match *self {
            Ident(ref value) => JList(~[JString(~"ident"), value.to_json()]),
            AtKeyword(ref value) => JList(~[JString(~"at-keyword"), value.to_json()]),
            Hash(ref value) => JList(~[JString(~"hash"), value.to_json(),
                                       JString(~"unrestricted")]),
            IDHash(ref value) => JList(~[JString(~"hash"), value.to_json(), JString(~"id")]),
            String(ref value) => JList(~[JString(~"string"), value.to_json()]),
            URL(ref value) => JList(~[JString(~"url"), value.to_json()]),
            Delim('\\') => JString(~"\\"),
            Delim(value) => JString(str::from_char(value)),

            Number(ref value) => JList(~[JString(~"number")] + numeric(value)),
            Percentage(ref value) => JList(~[JString(~"percentage")] + numeric(value)),
            Dimension(ref value, ref unit)
            => JList(~[JString(~"dimension")] + numeric(value) + ~[unit.to_json()]),

            UnicodeRange { start: s, end: e }
            => JList(~[JString(~"unicode-range"), s.to_json(), e.to_json()]),

            WhiteSpace => JString(~" "),
            Colon => JString(~":"),
            Semicolon => JString(~";"),
            Comma => JString(~","),
            IncludeMatch => JString(~"~="),
            DashMatch => JString(~"|="),
            PrefixMatch => JString(~"^="),
            SuffixMatch => JString(~"$="),
            SubstringMatch => JString(~"*="),
            Column => JString(~"||"),
            CDO => JString(~"<!--"),
            CDC => JString(~"-->"),

            Function(ref name, ref arguments)
            => JList(~[JString(~"function"), name.to_json()] + arguments.map(|a| a.to_json())),
            ParenthesisBlock(ref content)
            => JList(~[JString(~"()")] + content.map(|c| c.to_json())),
            SquareBracketBlock(ref content)
            => JList(~[JString(~"[]")] + content.map(|c| c.to_json())),
            CurlyBracketBlock(ref content)
            => JList(~[JString(~"{}")] + list_to_json(content)),

            BadURL => JList(~[JString(~"error"), JString(~"bad-url")]),
            BadString => JList(~[JString(~"error"), JString(~"bad-string")]),
            CloseParenthesis => JList(~[JString(~"error"), JString(~")")]),
            CloseSquareBracket => JList(~[JString(~"error"), JString(~"]")]),
            CloseCurlyBracket => JList(~[JString(~"error"), JString(~"}")]),
        }
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::cell::RefCell;
use time::precise_time_ns;
use glfw;
use cgmath::vector::{Vector2};
use core::types::{Size2, MInt, Point2};
use core::conf::Config;
use core::fs::FileSystem;
use visualizer::mgl;
use visualizer::types::{MatId, ColorId, Time};
use visualizer::shader::Shader;
use visualizer::font_stash::FontStash;
use visualizer::context::Context;
use visualizer::state_visualizer::{
    StateVisualizer,
    StartGame,
    EndGame,
    QuitMenu,
};
use visualizer::game_state_visualizer::GameStateVisualizer;
use visualizer::menu_state_visualizer::MenuStateVisualizer;

type EventsReceiver = Receiver<(f64, glfw::WindowEvent)>;

pub struct Visualizer {
    visualizers: Vec<Box<StateVisualizer>>, // TODO: Vec -> Queue
    dtime: Time,
    last_time: Time,
    glfw: glfw::Glfw,
    events: EventsReceiver,
    context: Context,
    fs: FileSystem,
    should_close: bool,
}

fn create_win(glfw: &glfw::Glfw, win_size: Size2<MInt>)
    -> (glfw::Window, EventsReceiver)
{
    let w = win_size.w as u32;
    let h = win_size.h as u32;
    let title = "Marauder";
    let flags = glfw::Windowed;
    glfw.create_window(w, h, title, flags).unwrap()
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let fs = FileSystem::new();
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let config = Config::new(&fs.get(&Path::new("data/conf_visualizer.json")));
        let win_size = config.get::<Size2<MInt>>("screen_size");
        let (win, events) = create_win(&glfw, win_size);
        glfw.make_context_current(Some(&win));
        mgl::load_gl_funcs_with(|procname| glfw.get_proc_address(procname));
        mgl::init_opengl();
        win.set_all_polling(true);
        let font_size = config.get("font_size");
        let font_stash = FontStash::new(
            &fs.get(&Path::new("data/DroidSerif-Regular.ttf")), font_size);
        let shader = Shader::new(
            &fs.get(&Path::new("data/normal.vs.glsl")),
            &fs.get(&Path::new("data/normal.fs.glsl")),
        );
        let mvp_mat_id = MatId{id: shader.get_uniform("mvp_mat")};
        let basic_color_id = ColorId{id: shader.get_uniform("basic_color")};
        let context = Context {
            win: win,
            win_size: win_size,
            config: config,
            mouse_pos: Point2{v: Vector2::zero()},
            font_stash: RefCell::new(font_stash),
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            basic_color_id: basic_color_id,
        };
        let visualizer = box MenuStateVisualizer::new(&context);
        Visualizer {
            visualizers: vec![visualizer as Box<StateVisualizer>],
            dtime: Time{n: 0},
            last_time: Time{n: precise_time_ns()},
            glfw: glfw,
            events: events,
            context: context,
            fs: fs,
            should_close: false,
        }
    }

    fn get_events(&mut self) -> Vec<glfw::WindowEvent> {
        self.glfw.poll_events();
        let mut events = Vec::new();
        for (_, event) in glfw::flush_messages(&self.events) {
            events.push(event);
        }
        events
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    // TODO: simplify
    pub fn tick(&mut self) {
        {
            let events = self.get_events();
            let visualizer = self.visualizers.mut_last().unwrap(); // TODO: remove unwrap
            for event in events.iter() {
                visualizer.handle_event(&self.context, *event);
                self.context.handle_event(*event);
            }
            visualizer.logic();
            visualizer.draw(&self.context, self.dtime);
        }
        let cmd = self.visualizers.mut_last().unwrap().get_command(); // TODO: remove unwrap
        match cmd {
            Some(StartGame) => {
                let visualizer = box GameStateVisualizer::new(
                    &self.fs, &self.context);
                self.visualizers.push(visualizer as Box<StateVisualizer>);
            }
            Some(EndGame) => {
                self.visualizers.pop();
            },
            Some(QuitMenu) => {
                self.should_close = true;
            },
            None => {},
        }
        self.update_time();
    }

    pub fn update_time(&mut self) {
        let time = precise_time_ns();
        self.dtime.n = time - self.last_time.n;
        self.last_time.n = time;
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualzer/visualizer.rs: Removed useless todo-comment<commit_after>// See LICENSE file for copyright and license details.

use std::cell::RefCell;
use time::precise_time_ns;
use glfw;
use cgmath::vector::{Vector2};
use core::types::{Size2, MInt, Point2};
use core::conf::Config;
use core::fs::FileSystem;
use visualizer::mgl;
use visualizer::types::{MatId, ColorId, Time};
use visualizer::shader::Shader;
use visualizer::font_stash::FontStash;
use visualizer::context::Context;
use visualizer::state_visualizer::{
    StateVisualizer,
    StartGame,
    EndGame,
    QuitMenu,
};
use visualizer::game_state_visualizer::GameStateVisualizer;
use visualizer::menu_state_visualizer::MenuStateVisualizer;

type EventsReceiver = Receiver<(f64, glfw::WindowEvent)>;

pub struct Visualizer {
    visualizers: Vec<Box<StateVisualizer>>,
    dtime: Time,
    last_time: Time,
    glfw: glfw::Glfw,
    events: EventsReceiver,
    context: Context,
    fs: FileSystem,
    should_close: bool,
}

fn create_win(glfw: &glfw::Glfw, win_size: Size2<MInt>)
    -> (glfw::Window, EventsReceiver)
{
    let w = win_size.w as u32;
    let h = win_size.h as u32;
    let title = "Marauder";
    let flags = glfw::Windowed;
    glfw.create_window(w, h, title, flags).unwrap()
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let fs = FileSystem::new();
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let config = Config::new(&fs.get(&Path::new("data/conf_visualizer.json")));
        let win_size = config.get::<Size2<MInt>>("screen_size");
        let (win, events) = create_win(&glfw, win_size);
        glfw.make_context_current(Some(&win));
        mgl::load_gl_funcs_with(|procname| glfw.get_proc_address(procname));
        mgl::init_opengl();
        win.set_all_polling(true);
        let font_size = config.get("font_size");
        let font_stash = FontStash::new(
            &fs.get(&Path::new("data/DroidSerif-Regular.ttf")), font_size);
        let shader = Shader::new(
            &fs.get(&Path::new("data/normal.vs.glsl")),
            &fs.get(&Path::new("data/normal.fs.glsl")),
        );
        let mvp_mat_id = MatId{id: shader.get_uniform("mvp_mat")};
        let basic_color_id = ColorId{id: shader.get_uniform("basic_color")};
        let context = Context {
            win: win,
            win_size: win_size,
            config: config,
            mouse_pos: Point2{v: Vector2::zero()},
            font_stash: RefCell::new(font_stash),
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            basic_color_id: basic_color_id,
        };
        let visualizer = box MenuStateVisualizer::new(&context);
        Visualizer {
            visualizers: vec![visualizer as Box<StateVisualizer>],
            dtime: Time{n: 0},
            last_time: Time{n: precise_time_ns()},
            glfw: glfw,
            events: events,
            context: context,
            fs: fs,
            should_close: false,
        }
    }

    fn get_events(&mut self) -> Vec<glfw::WindowEvent> {
        self.glfw.poll_events();
        let mut events = Vec::new();
        for (_, event) in glfw::flush_messages(&self.events) {
            events.push(event);
        }
        events
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    // TODO: simplify
    pub fn tick(&mut self) {
        {
            let events = self.get_events();
            let visualizer = self.visualizers.mut_last().unwrap(); // TODO: remove unwrap
            for event in events.iter() {
                visualizer.handle_event(&self.context, *event);
                self.context.handle_event(*event);
            }
            visualizer.logic();
            visualizer.draw(&self.context, self.dtime);
        }
        let cmd = self.visualizers.mut_last().unwrap().get_command(); // TODO: remove unwrap
        match cmd {
            Some(StartGame) => {
                let visualizer = box GameStateVisualizer::new(
                    &self.fs, &self.context);
                self.visualizers.push(visualizer as Box<StateVisualizer>);
            }
            Some(EndGame) => {
                self.visualizers.pop();
            },
            Some(QuitMenu) => {
                self.should_close = true;
            },
            None => {},
        }
        self.update_time();
    }

    pub fn update_time(&mut self) {
        let time = precise_time_ns();
        self.dtime.n = time - self.last_time.n;
        self.last_time.n = time;
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>/**
 * 15.3 Do syntax
 * http://static.rust-lang.org/doc/master/tutorial.html#do-syntax
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */

// A function that takes a procedure as argument:
fn call_it(op: proc(v: int)) {
	op(10)
}

fn each(v: &[int], op: |v: &int|) {
	let mut n = 0;
	while n < v.len() {
		op(&v[n]);
		n += 1;
	}
}

fn main() {
	// As a caller, if we use a closure to provide the final operator argument, we can write it in a way that has a pleasant, block-like structure.
	call_it(proc(n) {
		println!("{:?}", n);
	});
	each([1, 2, 3], |n: &int| {
		println!("{:?}", n);
	});

	// |v: &int| is stack closure, not procedure: procedure is allocated at heap, and you can call it only once.
}
<commit_msg>Delete tutorial-15_3-do.rs<commit_after><|endoftext|>