<commit_before>//! The ReQL data types

use std::result;
use std::ops::Deref;

use {Result, DateTime, chrono};
use errors::DriverError;
use ql2::proto::{Term, Datum, Term_TermType as TermType, Term_AssocPair as TermPair,
                 Datum_DatumType as DatumType, Datum_AssocPair as DatumPair};
use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use serde::{Serialize, Deserialize, Serializer, Deserializer};

pub trait FromJson {
    fn from_json<T: ToJson>(t: T) -> Result<Term> {
        // Datum
        let mut datum = Datum::new();
        match t.to_json()? {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::Number(val) => {
                match val.as_f64() {
                    Some(val) => {
                        datum.set_field_type(DatumType::R_NUM);
                        datum.set_r_num(val);
                    }
                    None => {
                        let msg = String::from("Value::Number could not be coerced to f64");
                        return Err(DriverError::Other(msg))?;
                    }
                }
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let mut args = Vec::new();
                for a in val.iter() {
                    args.push(Term::from_json(a)?.take_datum());
                }
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let mut args = Vec::new();
                for (name, arg) in val.into_iter() {
                    let mut obj = DatumPair::new();
                    obj.set_key(name.into());
                    obj.set_val(Term::from_json(arg)?.take_datum());
                    args.push(obj);
                }
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        Ok(term)
    }
}

impl FromJson for Term {}

trait IsDatum {
    fn is_datum(&self) -> bool;
}

trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TermType::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Vec<TermPair> {
    fn encode(&self) -> String {
        let mut opts = String::from("{");
        for term in self {
            opts.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
        }
        opts = opts.trim_right_matches(",").to_string();
        opts.push_str("}");
        opts
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DatumType::R_NULL => String::from("null"),
            DatumType::R_BOOL => format!("{}", self.get_r_bool()),
            DatumType::R_NUM => format!("{}", self.get_r_num()),
            DatumType::R_STR => format!("\"{}\"", self.get_r_str()),
            DatumType::R_ARRAY => {
                let mut args = format!("[{},[", TermType::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            }
            DatumType::R_OBJECT => {
                let mut args = String::from("{");
                for term in self.get_r_object() {
                    args.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("}");
                args
            }
            DatumType::R_JSON => {
                unimplemented!();
            }
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = Vec::new();
        if !self.is_datum() {
            res.push(format!("[{}", self.get_field_type().value()));
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push(datum.encode());
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = if self.has_field_type() {
                String::from("[")
            } else {
                String::new()
            };
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            if self.has_field_type() {
                args.push_str("]");
            }
            res.push(args);
        }
        let opts = self.clone().take_optargs().into_vec();
        if !opts.is_empty() {
            res.push(format!("{}", opts.encode()));
        }
        let mut res = res.join(",");
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Time {
    #[serde(rename = "$reql_type$")]
    reql_type: String,
    epoch_time: f64,
    timezone: String,
}

impl Deserialize for DateTime {
    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
        where D: Deserializer
    {
        let time = Time::deserialize(deserializer)?;
        let secs = time.epoch_time.trunc() as i64;
        let nsecs = time.epoch_time.fract().abs() as u32;
        let naive = chrono::NaiveDateTime::from_timestamp(secs, nsecs);
        let dt = chrono::DateTime::<chrono::UTC>::from_utc(naive, chrono::UTC);
        Ok(DateTime(dt))
    }
}

impl Serialize for DateTime {
    fn serialize<S>(&self, _serializer: S) -> result::Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!();
    }
}

impl Deref for DateTime {
    type Target = chrono::DateTime<chrono::UTC>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<commit_msg>Correct time serialisation<commit_after>//! The ReQL data types

use std::result;
use std::ops::Deref;

use {Result, DateTime, chrono};
use errors::DriverError;
use ql2::proto::{Term, Datum, Term_TermType as TermType, Term_AssocPair as TermPair,
                 Datum_DatumType as DatumType, Datum_AssocPair as DatumPair};
use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use serde::{Serialize, Deserialize, Serializer, Deserializer};

pub trait FromJson {
    fn from_json<T: ToJson>(t: T) -> Result<Term> {
        // Datum
        let mut datum = Datum::new();
        match t.to_json()? {
            Value::String(val) => {
                datum.set_field_type(DatumType::R_STR);
                datum.set_r_str(val);
            }
            Value::Bool(val) => {
                datum.set_field_type(DatumType::R_BOOL);
                datum.set_r_bool(val);
            }
            Value::Number(val) => {
                match val.as_f64() {
                    Some(val) => {
                        datum.set_field_type(DatumType::R_NUM);
                        datum.set_r_num(val);
                    }
                    None => {
                        let msg = String::from("Value::Number could not be coerced to f64");
                        return Err(DriverError::Other(msg))?;
                    }
                }
            }
            Value::Array(val) => {
                datum.set_field_type(DatumType::R_ARRAY);
                let mut args = Vec::new();
                for a in val.iter() {
                    args.push(Term::from_json(a)?.take_datum());
                }
                let arr = RepeatedField::from_vec(args);
                datum.set_r_array(arr);
            }
            Value::Object(val) => {
                datum.set_field_type(DatumType::R_OBJECT);
                let mut args = Vec::new();
                for (name, arg) in val.into_iter() {
                    let mut obj = DatumPair::new();
                    obj.set_key(name.into());
                    obj.set_val(Term::from_json(arg)?.take_datum());
                    args.push(obj);
                }
                let obj = RepeatedField::from_vec(args);
                datum.set_r_object(obj);
            }
            Value::Null => {
                datum.set_field_type(DatumType::R_NULL);
            }
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TermType::DATUM);
        term.set_datum(datum);
        Ok(term)
    }
}

impl FromJson for Term {}

trait IsDatum {
    fn is_datum(&self) -> bool;
}

trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TermType::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Vec<TermPair> {
    fn encode(&self) -> String {
        let mut opts = String::from("{");
        for term in self {
            opts.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
        }
        opts = opts.trim_right_matches(",").to_string();
        opts.push_str("}");
        opts
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DatumType::R_NULL => String::from("null"),
            DatumType::R_BOOL => format!("{}", self.get_r_bool()),
            DatumType::R_NUM => format!("{}", self.get_r_num()),
            DatumType::R_STR => format!("\"{}\"", self.get_r_str()),
            DatumType::R_ARRAY => {
                let mut args = format!("[{},[", TermType::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            }
            DatumType::R_OBJECT => {
                let mut args = String::from("{");
                for term in self.get_r_object() {
                    args.push_str(&format!("\"{}\":{},", term.get_key(), term.get_val().encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("}");
                args
            }
            DatumType::R_JSON => {
                unimplemented!();
            }
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = Vec::new();
        if !self.is_datum() {
            res.push(format!("[{}", self.get_field_type().value()));
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push(datum.encode());
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = if self.has_field_type() {
                String::from("[")
            } else {
                String::new()
            };
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            if self.has_field_type() {
                args.push_str("]");
            }
            res.push(args);
        }
        let opts = self.clone().take_optargs().into_vec();
        if !opts.is_empty() {
            res.push(format!("{}", opts.encode()));
        }
        let mut res = res.join(",");
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Time {
    #[serde(rename = "$reql_type$")]
    reql_type: String,
    epoch_time: f64,
    timezone: String,
}

impl Deserialize for DateTime {
    fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
        where D: Deserializer
    {
        let time = Time::deserialize(deserializer)?;
        let secs = time.epoch_time.trunc() as i64;
        // RethinkDB timestamps have millisecond precision so we need
        // to convert the milliseconds to nanoseconds first
        let nsecs = (time.epoch_time.fract().abs() * 1_000_000) as u32;
        let naive = chrono::NaiveDateTime::from_timestamp(secs, nsecs);
        let dt = chrono::DateTime::<chrono::UTC>::from_utc(naive, chrono::UTC);
        Ok(DateTime(dt))
    }
}

impl Serialize for DateTime {
    fn serialize<S>(&self, _serializer: S) -> result::Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!();
    }
}

impl Deref for DateTime {
    type Target = chrono::DateTime<chrono::UTC>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
<|endoftext|>


<commit_before>//! TODO FITZGEN

use std::collections::hash_map;

/// TODO FITZGEN
///
/// DWARF standard 4, section 7.5.4, page 154
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AbbreviationTag {
    ArrayType = 0x01,
    ClassType = 0x02,
    EntryPoint = 0x03,
    EnumerationType = 0x04,
    FormalParameter = 0x05,
    ImportedDeclaration = 0x08,
    Label = 0x0a,
    LexicalBlock = 0x0b,
    Member = 0x0d,
    PointerType = 0x0f,
    ReferenceType = 0x10,
    CompileUnit = 0x11,
    StringType = 0x12,
    StructureType = 0x13,
    SubroutineType = 0x15,
    Typedef = 0x16,
    UnionType = 0x17,
    UnspecifiedParameters = 0x18,
    Variant = 0x19,
    CommonBlock = 0x1a,
    CommonInclusion = 0x1b,
    Inheritance = 0x1c,
    InlinedSubroutine = 0x1d,
    Module = 0x1e,
    PtrToMemberType = 0x1f,
    SetType = 0x20,
    SubrangeType = 0x21,
    WithStmt = 0x22,
    AccessDeclaration = 0x23,
    BaseType = 0x24,
    CatchBlock = 0x25,
    ConstType = 0x26,
    Constant = 0x27,
    Enumerator = 0x28,
    FileType = 0x29,
    Friend = 0x2a,
    Namelist = 0x2b,
    NamelistItem = 0x2c,
    PackedType = 0x2d,
    Subprogram = 0x2e,
    TemplateTypeParameter = 0x2f,
    TemplateValueParameter = 0x30,
    ThrownType = 0x31,
    TryBlock = 0x32,
    VariantPart = 0x33,
    Variable = 0x34,
    VolatileType = 0x35,
    DwarfProcedure = 0x36,
    RestrictType = 0x37,
    InterfaceType = 0x38,
    Namespace = 0x39,
    ImportedModule = 0x3a,
    UnspecifiedType = 0x3b,
    PartialUnit = 0x3c,
    ImportedUnit = 0x3d,
    Condition = 0x3f,
    SharedType = 0x40,
    TypeUnit = 0x41,
    RvalueReferenceType = 0x42,
    TemplateAlias = 0x43,
    LoUser = 0x4080,
    HiUser = 0xffff,
}

/// TODO FITZGEN
///
/// DWARF standard 4, section 7.5.4, page 154
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AbbreviationHasChildren {
    /// TODO FITZGEN
    Yes = 0x0,

    /// TODO FITZGEN
    No = 0x1,
}

/// TODO FITZGEN
///
/// DWARF standard 4, section 7.5.4, page 155
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AttributeName {
    Sibling = 0x1,
    Location = 0x2,
    Name = 0x3,
    Ordering = 0x9,
    ByteSize = 0xb,
    BitOffset = 0xc,
    BitSize = 0x0d,
    StmtList = 0x10,
    LowPc = 0x11,
    HighPc = 0x12,
    Language = 0x13,
    Discr = 0x15,
    DiscrValue = 0x16,
    Visibility = 0x17,
    Import = 0x18,
    StringLength = 0x19,
    CommonReference = 0x1a,
    CompDir = 0x1b,
    ConstValue = 0x1c,
    ContainingType = 0x1d,
    DefaultValue = 0x1e,
    Inline = 0x20,
    IsOptional = 0x21,
    LowerBound = 0x22,
    Producer = 0x25,
    Prototyped = 0x27,
    ReturnAddr = 0x2a,
    StartScope = 0x2c,
    BitStride = 0x2e,
    UpperBound = 0x2f,
    AbstractOrigin = 0x31,
    Accessibility = 0x32,
    AddressClass = 0x33,
    Artificial = 0x34,
    BaseTypes = 0x35,
    CallingConvention = 0x36,
    Count = 0x37,
    DataMemberLocation = 0x38,
    DeclColumn = 0x39,
    DeclFile = 0x3a,
    DeclLine = 0x3b,
    Declaration = 0x3c,
    DiscrList = 0x3d,
    Encoding = 0x3e,
    External = 0x3f,
    FrameBase = 0x40,
    Friend = 0x41,
    IdentifierCase = 0x42,
    MacroInfo = 0x43,
    NamelistItem = 0x44,
    Priority = 0x45,
    Segment = 0x46,
    Specification = 0x47,
    StaticLink = 0x48,
    Type = 0x49,
    UseLocation = 0x4a,
    VariableParameter = 0x4b,
    Virtuality = 0x4c,
    VtableElemLocation = 0x4d,
    Allocated = 0x4e,
    Associated = 0x4f,
    DataLocation = 0x50,
    ByteStride = 0x51,
    EntryPc = 0x52,
    UseUtf8 = 0x53,
    Extension = 0x54,
    Ranges = 0x55,
    Trampoline = 0x56,
    CallColumn = 0x57,
    CallFile = 0x58,
    CallLine = 0x59,
    Description = 0x5a,
    BinaryScale = 0x5b,
    DecimalScale = 0x5c,
    Small = 0x5d,
    DecimalSign = 0x5e,
    DigitCount = 0x5f,
    PictureString = 0x60,
    Mutable = 0x61,
    ThreadsScaled = 0x62,
    Explicit = 0x63,
    ObjectPointer = 0x64,
    Endianity = 0x65,
    Elemental = 0x66,
    Pure = 0x67,
    Recursive = 0x68,
    Signature = 0x69,
    MainSubprogram = 0x6a,
    DataBitOffset = 0x6b,
    ConstExpr = 0x6c,
    EnumClass = 0x6d,
    LinkageName = 0x6e,
    LoUser = 0x2000,
    HiUser = 0x3fff,
}

/// TODO FITZGEN
///
/// DWARF standard 4, section 7.5.4, page 160
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AttributeForm {
    Addr = 0x01,
    Block2 = 0x03,
    Block4 = 0x04,
    Data2 = 0x05,
    Data4 = 0x06,
    Data8 = 0x07,
    String = 0x08,
    Block = 0x09,
    Block1 = 0x0a,
    Data1 = 0x0b,
    Flag = 0x0c,
    Sdata = 0x0d,
    Strp = 0x0e,
    Udata = 0x0f,
    RefAddr = 0x10,
    Ref1 = 0x11,
    Ref2 = 0x12,
    Ref4 = 0x13,
    Ref8 = 0x14,
    RefUdata = 0x15,
    Indirect = 0x16,
    SecOffset = 0x17,
    Exprloc = 0x18,
    FlagPresent = 0x19,
    RefSig8 = 0x20,
}

/// TODO FITZGEN
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AttributeSpecification {
    name: AttributeName,
    form: AttributeForm,
}

impl AttributeSpecification {
    /// TODO FITZGEN
    pub fn new(name: AttributeName, form: AttributeForm) -> AttributeSpecification {
        AttributeSpecification {
            name: name,
            form: form,
        }
    }

    /// TODO FITZGEN
    pub fn name(&self) -> AttributeName {
        self.name
    }

    /// TODO FITZGEN
    pub fn form(&self) -> AttributeForm {
        self.form
    }
}

/// TODO FITZGEN
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Abbreviation {
    code: u64,
    tag: AbbreviationTag,
    has_children: AbbreviationHasChildren,
    attributes: Vec<AttributeSpecification>,
}

impl Abbreviation {
    /// TODO FITZGEN
    pub fn new(code: u64,
               tag: AbbreviationTag,
               has_children: AbbreviationHasChildren,
               attributes: Vec<AttributeSpecification>) -> Abbreviation {
        Abbreviation {
            code: code,
            tag: tag,
            has_children: has_children,
            attributes: attributes,
        }
    }

    /// TODO FITZGEN
    pub fn code(&self) -> u64 {
        self.code
    }

    /// TODO FITZGEN
    pub fn tag(&self) -> AbbreviationTag {
        self.tag
    }

    /// TODO FITZGEN
    pub fn has_children(&self) -> bool {
        match self.has_children {
            AbbreviationHasChildren::Yes => true,
            AbbreviationHasChildren::No => false,
        }
    }

    /// TODO FITZGEN
    pub fn attributes(&self) -> &[AttributeSpecification] {
        &self.attributes[..]
    }
}

/// TODO FITZGEN
#[derive(Debug, Clone)]
pub struct Abbreviations {
    abbrevs: hash_map::HashMap<u64, Abbreviation>,
}

impl Abbreviations {
    /// TODO FITZGEN
    pub fn new() -> Abbreviations {
        Abbreviations {
            abbrevs: hash_map::HashMap::new(),
        }
    }

    /// TODO FITZGEN
    pub fn insert(&mut self, abbrev: Abbreviation) -> Result<(), ()> {
        match self.abbrevs.entry(abbrev.code) {
            hash_map::Entry::Occupied(_) =>
                Err(()),
            hash_map::Entry::Vacant(entry) => {
                entry.insert(abbrev);
                Ok(())
            },
        }
    }
}
<commit_msg>Fill in the documentation for src/types.rs<commit_after>use std::collections::hash_map;

/// Abbreviation tag types, aka `DW_TAG_whatever` in the standard.
///
/// DWARF standard 4, section 7.5.4, page 154
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AbbreviationTag {
    ArrayType = 0x01,
    ClassType = 0x02,
    EntryPoint = 0x03,
    EnumerationType = 0x04,
    FormalParameter = 0x05,
    ImportedDeclaration = 0x08,
    Label = 0x0a,
    LexicalBlock = 0x0b,
    Member = 0x0d,
    PointerType = 0x0f,
    ReferenceType = 0x10,
    CompileUnit = 0x11,
    StringType = 0x12,
    StructureType = 0x13,
    SubroutineType = 0x15,
    Typedef = 0x16,
    UnionType = 0x17,
    UnspecifiedParameters = 0x18,
    Variant = 0x19,
    CommonBlock = 0x1a,
    CommonInclusion = 0x1b,
    Inheritance = 0x1c,
    InlinedSubroutine = 0x1d,
    Module = 0x1e,
    PtrToMemberType = 0x1f,
    SetType = 0x20,
    SubrangeType = 0x21,
    WithStmt = 0x22,
    AccessDeclaration = 0x23,
    BaseType = 0x24,
    CatchBlock = 0x25,
    ConstType = 0x26,
    Constant = 0x27,
    Enumerator = 0x28,
    FileType = 0x29,
    Friend = 0x2a,
    Namelist = 0x2b,
    NamelistItem = 0x2c,
    PackedType = 0x2d,
    Subprogram = 0x2e,
    TemplateTypeParameter = 0x2f,
    TemplateValueParameter = 0x30,
    ThrownType = 0x31,
    TryBlock = 0x32,
    VariantPart = 0x33,
    Variable = 0x34,
    VolatileType = 0x35,
    DwarfProcedure = 0x36,
    RestrictType = 0x37,
    InterfaceType = 0x38,
    Namespace = 0x39,
    ImportedModule = 0x3a,
    UnspecifiedType = 0x3b,
    PartialUnit = 0x3c,
    ImportedUnit = 0x3d,
    Condition = 0x3f,
    SharedType = 0x40,
    TypeUnit = 0x41,
    RvalueReferenceType = 0x42,
    TemplateAlias = 0x43,
    LoUser = 0x4080,
    HiUser = 0xffff,
}

/// Whether an abbreviation's type has children or not, aka
/// `DW_CHILDREN_{yes,no}` in the standard.
///
/// DWARF standard 4, section 7.5.4, page 154
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AbbreviationHasChildren {
    /// TODO FITZGEN
    Yes = 0x0,

    /// TODO FITZGEN
    No = 0x1,
}

/// The set of possible attribute names, aka `DW_AT_whatever` in the standard.
///
/// DWARF standard 4, section 7.5.4, page 155
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AttributeName {
    Sibling = 0x1,
    Location = 0x2,
    Name = 0x3,
    Ordering = 0x9,
    ByteSize = 0xb,
    BitOffset = 0xc,
    BitSize = 0x0d,
    StmtList = 0x10,
    LowPc = 0x11,
    HighPc = 0x12,
    Language = 0x13,
    Discr = 0x15,
    DiscrValue = 0x16,
    Visibility = 0x17,
    Import = 0x18,
    StringLength = 0x19,
    CommonReference = 0x1a,
    CompDir = 0x1b,
    ConstValue = 0x1c,
    ContainingType = 0x1d,
    DefaultValue = 0x1e,
    Inline = 0x20,
    IsOptional = 0x21,
    LowerBound = 0x22,
    Producer = 0x25,
    Prototyped = 0x27,
    ReturnAddr = 0x2a,
    StartScope = 0x2c,
    BitStride = 0x2e,
    UpperBound = 0x2f,
    AbstractOrigin = 0x31,
    Accessibility = 0x32,
    AddressClass = 0x33,
    Artificial = 0x34,
    BaseTypes = 0x35,
    CallingConvention = 0x36,
    Count = 0x37,
    DataMemberLocation = 0x38,
    DeclColumn = 0x39,
    DeclFile = 0x3a,
    DeclLine = 0x3b,
    Declaration = 0x3c,
    DiscrList = 0x3d,
    Encoding = 0x3e,
    External = 0x3f,
    FrameBase = 0x40,
    Friend = 0x41,
    IdentifierCase = 0x42,
    MacroInfo = 0x43,
    NamelistItem = 0x44,
    Priority = 0x45,
    Segment = 0x46,
    Specification = 0x47,
    StaticLink = 0x48,
    Type = 0x49,
    UseLocation = 0x4a,
    VariableParameter = 0x4b,
    Virtuality = 0x4c,
    VtableElemLocation = 0x4d,
    Allocated = 0x4e,
    Associated = 0x4f,
    DataLocation = 0x50,
    ByteStride = 0x51,
    EntryPc = 0x52,
    UseUtf8 = 0x53,
    Extension = 0x54,
    Ranges = 0x55,
    Trampoline = 0x56,
    CallColumn = 0x57,
    CallFile = 0x58,
    CallLine = 0x59,
    Description = 0x5a,
    BinaryScale = 0x5b,
    DecimalScale = 0x5c,
    Small = 0x5d,
    DecimalSign = 0x5e,
    DigitCount = 0x5f,
    PictureString = 0x60,
    Mutable = 0x61,
    ThreadsScaled = 0x62,
    Explicit = 0x63,
    ObjectPointer = 0x64,
    Endianity = 0x65,
    Elemental = 0x66,
    Pure = 0x67,
    Recursive = 0x68,
    Signature = 0x69,
    MainSubprogram = 0x6a,
    DataBitOffset = 0x6b,
    ConstExpr = 0x6c,
    EnumClass = 0x6d,
    LinkageName = 0x6e,
    LoUser = 0x2000,
    HiUser = 0x3fff,
}

/// The type and encoding of an attribute, aka `DW_AT_whatever` in the standard.
///
/// DWARF standard 4, section 7.5.4, page 160
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AttributeForm {
    Addr = 0x01,
    Block2 = 0x03,
    Block4 = 0x04,
    Data2 = 0x05,
    Data4 = 0x06,
    Data8 = 0x07,
    String = 0x08,
    Block = 0x09,
    Block1 = 0x0a,
    Data1 = 0x0b,
    Flag = 0x0c,
    Sdata = 0x0d,
    Strp = 0x0e,
    Udata = 0x0f,
    RefAddr = 0x10,
    Ref1 = 0x11,
    Ref2 = 0x12,
    Ref4 = 0x13,
    Ref8 = 0x14,
    RefUdata = 0x15,
    Indirect = 0x16,
    SecOffset = 0x17,
    Exprloc = 0x18,
    FlagPresent = 0x19,
    RefSig8 = 0x20,
}

/// The description of an attribute in an abbreviated type. It is a pair of name
/// and form.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AttributeSpecification {
    name: AttributeName,
    form: AttributeForm,
}

impl AttributeSpecification {
    /// Construct a new `AttributeSpecification` from the given name and form.
    pub fn new(name: AttributeName, form: AttributeForm) -> AttributeSpecification {
        AttributeSpecification {
            name: name,
            form: form,
        }
    }

    /// Get the attribute's name.
    pub fn name(&self) -> AttributeName {
        self.name
    }

    /// Get the attribute's form.
    pub fn form(&self) -> AttributeForm {
        self.form
    }
}

/// An abbreviation describes the shape of a DIE type: its code, tag type,
/// whether it has children, and its set of attributes.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Abbreviation {
    code: u64,
    tag: AbbreviationTag,
    has_children: AbbreviationHasChildren,
    attributes: Vec<AttributeSpecification>,
}

impl Abbreviation {
    /// Construct a new `Abbreviation`.
    ///
    /// ### Panics
    ///
    /// Panics if `code` is `0`.
    pub fn new(code: u64,
               tag: AbbreviationTag,
               has_children: AbbreviationHasChildren,
               attributes: Vec<AttributeSpecification>) -> Abbreviation {
        assert!(code != 0);
        Abbreviation {
            code: code,
            tag: tag,
            has_children: has_children,
            attributes: attributes,
        }
    }

    /// Get this abbreviation's code.
    pub fn code(&self) -> u64 {
        self.code
    }

    /// Get this abbreviation's tag.
    pub fn tag(&self) -> AbbreviationTag {
        self.tag
    }

    /// Return true if this abbreviation's type has children, false otherwise.
    pub fn has_children(&self) -> bool {
        match self.has_children {
            AbbreviationHasChildren::Yes => true,
            AbbreviationHasChildren::No => false,
        }
    }

    /// Get this abbreviation's attributes.
    pub fn attributes(&self) -> &[AttributeSpecification] {
        &self.attributes[..]
    }
}

/// A set of type abbreviations.
#[derive(Debug, Clone)]
pub struct Abbreviations {
    abbrevs: hash_map::HashMap<u64, Abbreviation>,
}

impl Abbreviations {
    /// Construct a new, empty set of abbreviations.
    pub fn new() -> Abbreviations {
        Abbreviations {
            abbrevs: hash_map::HashMap::new(),
        }
    }

    /// Insert an abbreviation into the set.
    ///
    /// Returns `Ok` if it is the first abbreviation in the set with its code,
    /// `Err` if the code is a duplicate and there already exists an
    /// abbreviation in the set with the given abbreviation's code.
    pub fn insert(&mut self, abbrev: Abbreviation) -> Result<(), ()> {
        match self.abbrevs.entry(abbrev.code) {
            hash_map::Entry::Occupied(_) =>
                Err(()),
            hash_map::Entry::Vacant(entry) => {
                entry.insert(abbrev);
                Ok(())
            },
        }
    }
}
<|endoftext|>


<commit_before>//! Basic types and their methods for linear algebra

use ndarray::LinalgScalar;
use num_complex::Complex;
use num_traits::*;
use rand::Rng;
use rand::distributions::*;
use std::fmt::Debug;
use std::iter::Sum;
use std::ops::*;

use super::lapack_traits::LapackScalar;

pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;

macro_rules! trait_alias {
    ($name:ident: $($t:ident),*) => {

pub trait $name : $($t +)* {}

impl<T> $name for T where T: $($t +)* {}

}} // trait_alias!

trait_alias!(
    Field: LapackScalar,
    LinalgScalar,
    AssociatedReal,
    AssociatedComplex,
    Absolute,
    SquareRoot,
    Conjugate,
    RandNormal,
    Sum,
    Debug
);

trait_alias!(RealField: Field, Float);

/// Define associating real float type
pub trait AssociatedReal: Sized {
    type Real: Float + Mul<Self, Output = Self>;
    fn inject(Self::Real) -> Self;
}

/// Define associating complex type
pub trait AssociatedComplex: Sized {
    type Complex;
    fn inject(Self) -> Self::Complex;
}

/// Define `abs()` more generally
pub trait Absolute {
    type Output: RealField;
    fn squared(&self) -> Self::Output;
    fn abs(&self) -> Self::Output {
        self.squared().sqrt()
    }
}

/// Define `sqrt()` more generally
pub trait SquareRoot {
    fn sqrt(&self) -> Self;
}

/// Complex conjugate value
pub trait Conjugate: Copy {
    fn conj(self) -> Self;
}

/// Scalars which can be initialized from Gaussian random number
pub trait RandNormal {
    fn randn<R: Rng>(&mut R) -> Self;
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { r }
}

impl AssociatedReal for $complex {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { Self::new(r, 0.0) }
}

impl AssociatedComplex for $real {
    type Complex = $complex;
    fn inject(r: Self) -> Self::Complex { Self::Complex::new(r, 0.0) }
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
    fn inject(c: Self) -> Self::Complex { c }
}

impl Absolute for $real {
    type Output = Self;
    fn squared(&self) -> Self::Output {
        *self * *self
    }
    fn abs(&self) -> Self::Output {
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    type Output = $real;
    fn squared(&self) -> Self::Output {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Output {
        self.norm()
    }
}

impl SquareRoot for $real {
    fn sqrt(&self) -> Self {
        Float::sqrt(*self)
    }
}

impl SquareRoot for $complex {
    fn sqrt(&self) -> Self {
        Complex::sqrt(self)
    }
}

impl Conjugate for $real {
    fn conj(self) -> Self {
        self
    }
}

impl Conjugate for $complex {
    fn conj(self) -> Self {
        Complex::conj(&self)
    }
}

impl RandNormal for $real {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        dist.ind_sample(rng) as $real
    }
}

impl RandNormal for $complex {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        let re = dist.ind_sample(rng) as $real;
        let im = dist.ind_sample(rng) as $real;
        Self::new(re, im)
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<commit_msg>Method {add,sub,mul,div}_real and {add,sub,mul}_complex<commit_after>//! Basic types and their methods for linear algebra

use ndarray::LinalgScalar;
use num_complex::Complex;
use num_traits::*;
use rand::Rng;
use rand::distributions::*;
use std::fmt::Debug;
use std::iter::Sum;

use super::lapack_traits::LapackScalar;

pub use num_complex::Complex32 as c32;
pub use num_complex::Complex64 as c64;

macro_rules! trait_alias {
    ($name:ident: $($t:ident),*) => {

pub trait $name : $($t +)* {}

impl<T> $name for T where T: $($t +)* {}

}} // trait_alias!

trait_alias!(
    Field: LapackScalar,
    LinalgScalar,
    AssociatedReal,
    AssociatedComplex,
    Absolute,
    SquareRoot,
    Conjugate,
    RandNormal,
    Sum,
    Debug
);

trait_alias!(RealField: Field, Float);

/// Define associating real float type
pub trait AssociatedReal: Sized {
    type Real: Float;
    fn inject(Self::Real) -> Self;
    fn add_real(self, Self::Real) -> Self;
    fn sub_real(self, Self::Real) -> Self;
    fn mul_real(self, Self::Real) -> Self;
    fn div_real(self, Self::Real) -> Self;
}

/// Define associating complex type
pub trait AssociatedComplex: Sized {
    type Complex;
    fn inject(Self) -> Self::Complex;
    fn add_complex(self, Self::Complex) -> Self::Complex;
    fn sub_complex(self, Self::Complex) -> Self::Complex;
    fn mul_complex(self, Self::Complex) -> Self::Complex;
}

/// Define `abs()` more generally
pub trait Absolute {
    type Output: RealField;
    fn squared(&self) -> Self::Output;
    fn abs(&self) -> Self::Output {
        self.squared().sqrt()
    }
}

/// Define `sqrt()` more generally
pub trait SquareRoot {
    fn sqrt(&self) -> Self;
}

/// Complex conjugate value
pub trait Conjugate: Copy {
    fn conj(self) -> Self;
}

/// Scalars which can be initialized from Gaussian random number
pub trait RandNormal {
    fn randn<R: Rng>(&mut R) -> Self;
}

macro_rules! impl_traits {
    ($real:ty, $complex:ty) => {

impl AssociatedReal for $real {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { r }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedReal for $complex {
    type Real = $real;
    fn inject(r: Self::Real) -> Self { Self::new(r, 0.0) }
    fn add_real(self, r: Self::Real) -> Self { self + r }
    fn sub_real(self, r: Self::Real) -> Self { self - r }
    fn mul_real(self, r: Self::Real) -> Self { self * r }
    fn div_real(self, r: Self::Real) -> Self { self / r }
}

impl AssociatedComplex for $real {
    type Complex = $complex;
    fn inject(r: Self) -> Self::Complex { Self::Complex::new(r, 0.0) }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl AssociatedComplex for $complex {
    type Complex = $complex;
    fn inject(c: Self) -> Self::Complex { c }
    fn add_complex(self, c: Self::Complex) -> Self::Complex { self + c }
    fn sub_complex(self, c: Self::Complex) -> Self::Complex { self - c }
    fn mul_complex(self, c: Self::Complex) -> Self::Complex { self * c }
}

impl Absolute for $real {
    type Output = Self;
    fn squared(&self) -> Self::Output {
        *self * *self
    }
    fn abs(&self) -> Self::Output {
        Float::abs(*self)
    }
}

impl Absolute for $complex {
    type Output = $real;
    fn squared(&self) -> Self::Output {
        self.norm_sqr()
    }
    fn abs(&self) -> Self::Output {
        self.norm()
    }
}

impl SquareRoot for $real {
    fn sqrt(&self) -> Self {
        Float::sqrt(*self)
    }
}

impl SquareRoot for $complex {
    fn sqrt(&self) -> Self {
        Complex::sqrt(self)
    }
}

impl Conjugate for $real {
    fn conj(self) -> Self {
        self
    }
}

impl Conjugate for $complex {
    fn conj(self) -> Self {
        Complex::conj(&self)
    }
}

impl RandNormal for $real {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        dist.ind_sample(rng) as $real
    }
}

impl RandNormal for $complex {
    fn randn<R: Rng>(rng: &mut R) -> Self {
        let dist = Normal::new(0., 1.);
        let re = dist.ind_sample(rng) as $real;
        let im = dist.ind_sample(rng) as $real;
        Self::new(re, im)
    }
}

}} // impl_traits!

impl_traits!(f64, c64);
impl_traits!(f32, c32);
<|endoftext|>


<commit_before>use raw::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
#[cfg(not(ndebug))]
use std::fmt::{Show, Formatter, Result};
use std::kinds::marker::{ContravariantLifetime, NoCopy};
use std::mem::transmute;
use std::c_str::ToCStr;
use util::NativeRef;
/// The integer representation of a type
pub mod kind {
    use libc::c_int;
    #[cfg(not(ndebug))]
    use std::fmt::{Show, Formatter, Result};
    bitflags!(
        #[deriving(Copy)]
        /// The integer representation of a type
        flags TypeKind: c_int {
            const Void = 0,
            const SByte = 1,
            const UByte = 2,
            const Short = 3,
            const UShort = 4,
            const Int = 5,
            const UInt = 6,
            const NInt = 7,
            const NUInt = 8,
            const Long = 9,
            const ULong = 10,
            const Float32 = 11,
            const Float64 = 12,
            const NFloat = 13,
            const Struct = 14,
            const Union = 15,
            const Signature = 16,
            const Pointer = 17,
            const FirstTagged = 2,
            const SysBool = 10009,
            const SysChar = 10010
        }
    )
    #[cfg(not(ndebug))]
    impl Show for TypeKind {
        fn fmt(&self, fmt:&mut Formatter) -> Result {
            write!(fmt, "{}",
                if self.contains(SysBool) { "SysBool" }
                else if self.contains(SysChar) { "SysChar" }
                else if self.contains(SByte) { "SByte" }
                else if self.contains(UByte) { "UByte" }
                else if self.contains(Short) { "Short" }
                else if self.contains(UShort) { "UShort" }
                else if self.contains(Int) { "Int" }
                else if self.contains(UInt) { "UInt" }
                else if self.contains(NInt) { "NInt" }
                else if self.contains(NUInt) { "NUInt" }
                else if self.contains(Long) { "Long" }
                else if self.contains(ULong) { "ULong" }
                else if self.contains(Float32) { "Float32" }
                else if self.contains(Float64) { "Float64" }
                else if self.contains(NFloat) { "NFloat" }
                else if self.contains(Struct) { "Struct" }
                else if self.contains(Union) { "Union" }
                else if self.contains(Signature) { "Signature" }
                else if self.contains(Pointer) { "Void" }
                else { "Void" }
            )
        }
    }
}
#[cfg(not(ndebug))]
impl Show for Type {
    fn fmt(&self, fmt:&mut Formatter) -> Result {
        let kind = self.get_kind();
        if kind == kind::Signature {
            try!("fn(".fmt(fmt));
            for param in self.params() {
                try!(param.fmt(fmt));
            }
            write!(fmt, ") -> ({})", self.get_return())
        } else {
            kind.fmt(fmt)
        }
    }
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> PartialEq for Field<'a> {
    fn eq(&self, other:&Field<'a>) -> bool {
        self.index == other.index && self._type == other._type
    }
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(String::from_raw_buf(transmute(c_name)))
            }
        }
    }
    #[inline(always)]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline(always)]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// Iterates through all the fields of a struct
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        if self.index < self.length {
            let index = self.index;
            self.index += 1;
            Some(Field {
                index: index,
                _type: self._type,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
}
/// Iterator through all the arguments a function takes
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        if self.index < self.length {
            let index = self.index;
            self.index += 1;
            unsafe { NativeRef::from_opt_ptr(jit_type_get_param(self._type, index)) }
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
/// Types are not attached to a context so they are reference-counted by LibJIT,
/// so internally they are represented as `Rc<TypeData>`.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    no_copy: NoCopy
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            no_copy: NoCopy
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline(always)]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline(always)]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows callers to
    /// quickly classify a type to determine how it should be handled further.
    pub fn get_kind(&self) -> kind::TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type returned by this function type.
    pub fn get_return(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_return(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().into_inner()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<commit_msg>`Show` output for types gives Rust type names and detail it for structs and unions<commit_after>use raw::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
#[cfg(not(ndebug))]
use std::fmt::{Show, Formatter, Result};
use std::kinds::marker::{ContravariantLifetime, NoCopy};
use std::mem::transmute;
use std::c_str::ToCStr;
use util::NativeRef;
/// The integer representation of a type
pub mod kind {
    use libc::c_int;
    #[cfg(not(ndebug))]
    use std::fmt::{Show, Formatter, Result};
    bitflags!(
        #[deriving(Copy)]
        /// The integer representation of a type
        flags TypeKind: c_int {
            const Void = 0,
            const SByte = 1,
            const UByte = 2,
            const Short = 3,
            const UShort = 4,
            const Int = 5,
            const UInt = 6,
            const NInt = 7,
            const NUInt = 8,
            const Long = 9,
            const ULong = 10,
            const Float32 = 11,
            const Float64 = 12,
            const NFloat = 13,
            const Struct = 14,
            const Union = 15,
            const Signature = 16,
            const Pointer = 17,
            const FirstTagged = 2,
            const SysBool = 10009,
            const SysChar = 10010
        }
    )
    #[cfg(not(ndebug))]
    impl Show for TypeKind {
        fn fmt(&self, fmt:&mut Formatter) -> Result {
            write!(fmt, "{}",
                if self.contains(Union) { "union" }
                else if self.contains(Signature) { "signature" }
                else if self.contains(Pointer) { "pointer" }
                else if self.contains(Struct) { "struct" }
                else if self.contains(SysBool) { "bool" }
                else if self.contains(SysChar) { "char" }
                else if self.contains(SByte) { "i8" }
                else if self.contains(UByte) { "u8" }
                else if self.contains(Short) { "i16" }
                else if self.contains(UShort) { "u16" }
                else if self.contains(Int) { "i32" }
                else if self.contains(UInt) { "u32" }
                else if self.contains(NInt) { "int" }
                else if self.contains(NUInt) { "uint" }
                else if self.contains(Long) { "i64" }
                else if self.contains(ULong) { "u64" }
                else if self.contains(Float32) { "f32" }
                else if self.contains(Float64) { "f64" }
                else if self.contains(NFloat) { "float" }
                else { "()" }
            )
        }
    }
}
#[cfg(not(ndebug))]
impl Show for Type {
    fn fmt(&self, fmt:&mut Formatter) -> Result {
        let kind = self.get_kind();
        if kind.contains(kind::Signature) {
            try!("fn(".fmt(fmt));
            for param in self.params() {
                try!(param.fmt(fmt));
            }
            write!(fmt, ") -> ({})", self.get_return())
        } else if kind.contains(kind::Pointer) {
            write!(fmt, "&mut {}", self.get_ref())
        } else if kind.contains(kind::Struct) {
            try!("struct {".fmt(fmt));
            for field in self.fields() {
                try!("\n\t".fmt(fmt));
                if let Some(name) = field.get_name() {
                    try!(write!(fmt, "{}: ", name));
                }
                try!(write!(fmt, "{},", field.get_type()));
            }
            "\n}".fmt(fmt)
        } else if kind.contains(kind::Union) {
            try!("union {".fmt(fmt));
            for field in self.fields() {
                try!("\n\t".fmt(fmt));
                if let Some(name) = field.get_name() {
                    try!(write!(fmt, "{}: ", name));
                }
                try!(write!(fmt, "{},", field.get_type()));
            }
            "\n}".fmt(fmt)
        } else {
            kind.fmt(fmt)
        }
    }
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> PartialEq for Field<'a> {
    fn eq(&self, other:&Field<'a>) -> bool {
        self.index == other.index && self._type == other._type
    }
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(String::from_raw_buf(transmute(c_name)))
            }
        }
    }
    #[inline(always)]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline(always)]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// Iterates through all the fields of a struct
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        if self.index < self.length {
            let index = self.index;
            self.index += 1;
            Some(Field {
                index: index,
                _type: self._type,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
}
/// Iterator through all the arguments a function takes
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        if self.index < self.length {
            let index = self.index;
            self.index += 1;
            unsafe { NativeRef::from_opt_ptr(jit_type_get_param(self._type, index)) }
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
/// Types are not attached to a context so they are reference-counted by LibJIT,
/// so internally they are represented as `Rc<TypeData>`.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    no_copy: NoCopy
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            no_copy: NoCopy
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline(always)]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline(always)]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows callers to
    /// quickly classify a type to determine how it should be handled further.
    pub fn get_kind(&self) -> kind::TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type returned by this function type.
    pub fn get_return(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_return(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().into_inner()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<|endoftext|>


<commit_before>#![macro_escape]

use libc::c_ulonglong;

#[doc(hidden)]
pub fn marshal<T>(buf: &[u8],
                  padbefore: uint,
                  bytestodrop: uint,
                  f: |*mut u8, *const u8, c_ulonglong| -> T
                 ) -> (Vec<u8>, T) {
    let mut dst = Vec::with_capacity(buf.len() + padbefore);
    for _ in range(0, padbefore) {
        dst.push(0);
    }
    dst.push_all(buf);
    let pdst = dst.as_mut_ptr();
    let psrc = dst.as_ptr();
    let res = f(pdst, psrc, dst.len() as c_ulonglong);
    (dst.into_iter().skip(bytestodrop).collect(), res)
}

macro_rules! newtype_clone (($newtype:ident) => (
        impl Clone for $newtype {
            fn clone(&self) -> $newtype {
                let &$newtype(v) = self;
                $newtype(v)
            }
        }

        ));

macro_rules! newtype_drop (($newtype:ident) => (
        impl Drop for $newtype {
            fn drop(&mut self) {
                let &$newtype(ref mut v) = self;
                unsafe {
                    volatile_set_memory(v.as_mut_ptr(), 0, v.len());
                }
            }
        }
        ));

macro_rules! newtype_impl (($newtype:ident, $len:expr) => (
    impl $newtype {
        /**
         * `from_slice()` creates an object from a byte slice
         *
         * This function will fail and return None if the length of
         * the byte-slice isn't equal to the length of the object
         */
        pub fn from_slice(bs: &[u8]) -> Option<$newtype> {
            if bs.len() != $len {
                return None
            }
            let mut n = $newtype([0; $len]);
            {
                let $newtype(ref mut b) = n;
                for (bi, &bsi) in b.iter_mut().zip(bs.iter()) {
                    *bi = bsi
                }
            }
            Some(n)
        }
        /**
         * `as_slice()` returns a byte slice containing the object contents
         *
         * WARNING: it might be tempting to do comparisons on objects by
         * using `x.as_slice() == y.as_slice()`. This will open up for
         * timing attacks when comparing for example authenticator
         * tags. Because of this only use the comparison functions
         * exposed by the sodiumoxide API.
         */
        pub fn as_slice(&self) -> &[u8] {
            let &$newtype(ref bs) = self;
            bs.as_slice()
        }
        /**
         * `as_mut_slice()` returns a mutable byte slice containing the object
         * contents
         *
         * WARNING: it might be tempting to do comparisons on objects by
         * using `x.as_mut_slice() == y.as_mut_slice()`. This will
         * open up for timing attacks when comparing for example
         * authenticator tags. Because of this only use the comparison
         * functions exposed by the sodiumoxide API.
         */
        pub fn as_mut_slice(&mut self) -> &mut [u8] {
            let &$newtype(ref mut bs) = self;
            bs.as_mut_slice()
        }
    }
    ));
<commit_msg>Updated to new closure syntax<commit_after>#![macro_escape]

use libc::c_ulonglong;

#[doc(hidden)]
pub fn marshal<T, F>(buf: &[u8],
                     padbefore: uint,
                     bytestodrop: uint,
                     f: F
                     ) -> (Vec<u8>, T)
    where F: Fn(*mut u8, *const u8, c_ulonglong) -> T {
    let mut dst = Vec::with_capacity(buf.len() + padbefore);
    for _ in range(0, padbefore) {
        dst.push(0);
    }
    dst.push_all(buf);
    let pdst = dst.as_mut_ptr();
    let psrc = dst.as_ptr();
    let res = f(pdst, psrc, dst.len() as c_ulonglong);
    (dst.into_iter().skip(bytestodrop).collect(), res)
}

macro_rules! newtype_clone (($newtype:ident) => (
        impl Clone for $newtype {
            fn clone(&self) -> $newtype {
                let &$newtype(v) = self;
                $newtype(v)
            }
        }

        ));

macro_rules! newtype_drop (($newtype:ident) => (
        impl Drop for $newtype {
            fn drop(&mut self) {
                let &$newtype(ref mut v) = self;
                unsafe {
                    volatile_set_memory(v.as_mut_ptr(), 0, v.len());
                }
            }
        }
        ));

macro_rules! newtype_impl (($newtype:ident, $len:expr) => (
    impl $newtype {
        /**
         * `from_slice()` creates an object from a byte slice
         *
         * This function will fail and return None if the length of
         * the byte-slice isn't equal to the length of the object
         */
        pub fn from_slice(bs: &[u8]) -> Option<$newtype> {
            if bs.len() != $len {
                return None
            }
            let mut n = $newtype([0; $len]);
            {
                let $newtype(ref mut b) = n;
                for (bi, &bsi) in b.iter_mut().zip(bs.iter()) {
                    *bi = bsi
                }
            }
            Some(n)
        }
        /**
         * `as_slice()` returns a byte slice containing the object contents
         *
         * WARNING: it might be tempting to do comparisons on objects by
         * using `x.as_slice() == y.as_slice()`. This will open up for
         * timing attacks when comparing for example authenticator
         * tags. Because of this only use the comparison functions
         * exposed by the sodiumoxide API.
         */
        pub fn as_slice(&self) -> &[u8] {
            let &$newtype(ref bs) = self;
            bs.as_slice()
        }
        /**
         * `as_mut_slice()` returns a mutable byte slice containing the object
         * contents
         *
         * WARNING: it might be tempting to do comparisons on objects by
         * using `x.as_mut_slice() == y.as_mut_slice()`. This will
         * open up for timing attacks when comparing for example
         * authenticator tags. Because of this only use the comparison
         * functions exposed by the sodiumoxide API.
         */
        pub fn as_mut_slice(&mut self) -> &mut [u8] {
            let &$newtype(ref mut bs) = self;
            bs.as_mut_slice()
        }
    }
    ));
<|endoftext|>


<commit_before>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    pub data: Vec<u8>,
    pub bit_length: usize,
}

impl BitString {
    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        match (data.len(), bit_length) {
            (0, 0) => (),
            (_, 0) | (0, _) => return None,
            (i, j) if (i * 8 < j) || (i - 1) * 8 > j  => return None,
            _ => (),
        }

        return Some(BitString{
            data: data,
            bit_length: bit_length,
        })
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
    }
}
<commit_msg>style nits<commit_after>use std::{mem};

use num::{BigInt, One, Signed};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BitString {
    pub data: Vec<u8>,
    pub bit_length: usize,
}

impl BitString {
    pub fn new(data: Vec<u8>, bit_length: usize) -> Option<BitString> {
        match (data.len(), bit_length) {
            (0, 0) => (),
            (_, 0) | (0, _) => return None,
            (i, j) if (i * 8 < j) || (i - 1) * 8 > j => return None,
            _ => (),
        }

        return Some(BitString {
            data: data,
            bit_length: bit_length,
        });
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer: Sized {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                } else if data.is_empty() {
                    return Err(DeserializationError::InvalidValue);
                }

                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        if self.is_positive() {
            let (_, mut bytes) = self.to_bytes_be();
            if bytes[0] & 0x80 == 0x80 {
                // If the data has a leading 0x80, pad with a zero-byte.
                bytes.insert(0, 0);
            }
            return bytes;
        } else if self.is_negative() {
            // Convert negative numbers to two's-complement by subtracting one and inverting.
            let n_minus_1 = -self - BigInt::one();
            let (_, mut bytes) = n_minus_1.to_bytes_be();

            for i in 0..bytes.len() {
                bytes[i] ^= 0xff;
            }

            if bytes[0] & 0x80 == 0 {
                bytes.insert(0, 0xff);
            }
            return bytes;
        } else {
            return b"\x00".to_vec();
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data.is_empty() {
            return Err(DeserializationError::InvalidValue);
        }

        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{BitString, ObjectIdentifier};

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }

    #[test]
    fn test_bit_string_new() {
        assert!(BitString::new(b"".to_vec(), 1).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 0).is_none());
        assert!(BitString::new(b"\x00".to_vec(), 9).is_none());
    }
}
<|endoftext|>


<commit_before>use iron::prelude::*;
use maud::{Markup, PreEscaped, Render};
use pulldown_cmark;

use models::User;

pub fn layout(r: &Request, title: Option<&str>, body: Markup) -> Markup {
    html! {
        (PreEscaped("<!DOCTYPE html>"))
        html {
            meta charset="utf-8" /
            title {
                @if let Some(title) = title {
                    (title) " - "
                }
                "Karkinos"
            }
            meta name="viewport" content="width=device-width" /
            link rel="stylesheet" href=(url_for!(r, "static", "path" => "styles.css")) /
            body {
                h1 a href="/" {
                    span.thecrab "🦀"
                    "Karkinos"
                }
                @if let Some(title) = title {
                    h2 a href=(r.url) title="Link to this page" (title)
                }
                (body)
            }
        }
    }
}

pub fn home(r: &Request) -> Markup {
    layout(r, None, html! {
        (search_form(r, None))
        p {
            span.karkinos "KARKINOS"
            " is a database of people interested in the "
            a href="https://www.rust-lang.org" "Rust programming language"
            ". It uses the same data as "
            a href="http://rustaceans.org" "rustaceans.org"
            ", but presents it through a different interface."
        }
        p "I created Karkinos for these reasons:"
        ul {
            li "To provide access for users who browse with JavaScript disabled;"
            li "To rewrite the backend in Rust (instead of Node.js);"
            li {
                "As a proving ground for my template engine, "
                a href="https://github.com/lfairy/maud" "Maud"
                ";"
            }
            li "To screw around with CSS (this is the most important reason)."
        }
        p {
            "Karkinos is named after a very special "
            a href="https://en.wikipedia.org/wiki/Cancer_(constellation)#Names" "giant crab"
            "."
        }
        p {
            "The source code for this site can be found on "
            a href="https://github.com/lfairy/karkinos" "GitHub"
            "."
        }
    })
}

fn search_form(r: &Request, value: Option<&str>) -> Markup {
    html! {
        form action=(url_for!(r, "search")) {
            input name="q" id="q" type="search" placeholder="Search" value=(value.unwrap_or("")) /
        }
        @if value.is_none() {
            script (PreEscaped("document.getElementById('q').select()"))
        }
    }
}

pub fn not_found(r: &Request) -> Markup {
    layout(r, Some("Not found"), html! {
        p {
            "The page at "
            strong (r.url)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

pub fn search(r: &Request) -> Markup {
    layout(r, Some("Search"), html! {
        (search_form(r, None))
    })
}

pub fn search_results<'u, I>(r: &Request, query: &str, results: I) -> Markup where
    I: Iterator<Item=(Result<&'u User, &'u str>, String, u64)>,
{
    let title = format!("Search results for “{}”", query);
    let results = results.map(|(user, id, weight)| match user {
        Ok(user) => (user_box(r, &id, &user), id, weight),
        Err(..) => ((id.clone(), html! {}), id, weight),
    });
    let mut results = results.peekable();
    layout(r, Some(&title), html! {
        (search_form(r, Some(query)))
        @if results.peek().is_none() {
            p "No results found."
        }
        @for ((user_title, user_markup), id, weight) in results {
            h3 title={ "Weight: " (weight) } {
                a href=(url_for!(r, "user", "id" => &id[..])) (user_title)
            }
            (user_markup)
            hr /
        }
    })
}

pub fn user(r: &Request, id: &str, user: &User) -> Markup {
    let (title, body) = user_box(r, id, user);
    layout(r, Some(&title), body)
}

fn user_box(_r: &Request, id: &str, user: &User) -> (String, Markup) {
    let title = if let Some(ref name) = user.name {
        format!("{} ({})", name, id)
    } else {
        id.to_string()
    };
    (title, html! {
        table {
            @if let Some(ref nick) = user.irc {
                tr {
                    th "IRC"
                    td {
                        (nick)
                        @if !user.irc_channels.is_empty() {
                            " on "
                            @for (i, channel) in user.irc_channels.iter().enumerate() {
                                @if i > 0 { ", " }
                                a href={ "irc://irc.mozilla.org/" (channel) } {
                                    "#" (channel)
                                }
                            }
                        }
                    }
                }
            }
            @if let Some(ref x) = user.discourse {
                tr {
                    th "Discourse"
                    td a href={ "https://users.rust-lang.org/users/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.reddit {
                tr {
                    th "Reddit"
                    td a href={ "https://reddit.com/user/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.twitter {
                tr {
                    th "Twitter"
                    td a href={ "https://twitter.com/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.website {
                tr {
                    th "Website"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.blog {
                tr {
                    th "Blog"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.email {
                tr {
                    th "Email"
                    td a href={ "mailto:" (x) } (x)
                }
            }
        }
        @if let Some(ref x) = user.notes {
            div.notes (Markdown(x))
        }
    })
}

pub fn user_error(r: &Request, id: &str, error: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " exists, but their entry could not be parsed."
        }
        p {
            "(Error: " (error) ")"
        }
    })
}

pub fn user_not_found(r: &Request, id: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

struct Markdown<'a>(&'a str);

impl<'a> Render for Markdown<'a> {
    fn render_to(&self, buffer: &mut String) {
        let parser = pulldown_cmark::Parser::new(self.0);
        pulldown_cmark::html::push_html(buffer, parser);
    }
}
<commit_msg>Remove redundant "search results for" heading<commit_after>use iron::prelude::*;
use maud::{Markup, PreEscaped, Render};
use pulldown_cmark;

use models::User;

fn layout(r: &Request, title: Option<&str>, body: Markup) -> Markup {
    layout_inner(r, title, title, body)
}

fn layout_inner(r: &Request, head_title: Option<&str>, body_title: Option<&str>, body: Markup) -> Markup {
    html! {
        (PreEscaped("<!DOCTYPE html>"))
        html {
            meta charset="utf-8" /
            title {
                @if let Some(head_title) = head_title {
                    (head_title) " - "
                }
                "Karkinos"
            }
            meta name="viewport" content="width=device-width" /
            link rel="stylesheet" href=(url_for!(r, "static", "path" => "styles.css")) /
            body {
                h1 a href="/" {
                    span.thecrab "🦀"
                    "Karkinos"
                }
                @if let Some(body_title) = body_title {
                    h2 a href=(r.url) title="Link to this page" (body_title)
                }
                (body)
            }
        }
    }
}

pub fn home(r: &Request) -> Markup {
    layout(r, None, html! {
        (search_form(r, None))
        p {
            span.karkinos "KARKINOS"
            " is a database of people interested in the "
            a href="https://www.rust-lang.org" "Rust programming language"
            ". It uses the same data as "
            a href="http://rustaceans.org" "rustaceans.org"
            ", but presents it through a different interface."
        }
        p "I created Karkinos for these reasons:"
        ul {
            li "To provide access for users who browse with JavaScript disabled;"
            li "To rewrite the backend in Rust (instead of Node.js);"
            li {
                "As a proving ground for my template engine, "
                a href="https://github.com/lfairy/maud" "Maud"
                ";"
            }
            li "To screw around with CSS (this is the most important reason)."
        }
        p {
            "Karkinos is named after a very special "
            a href="https://en.wikipedia.org/wiki/Cancer_(constellation)#Names" "giant crab"
            "."
        }
        p {
            "The source code for this site can be found on "
            a href="https://github.com/lfairy/karkinos" "GitHub"
            "."
        }
    })
}

fn search_form(r: &Request, value: Option<&str>) -> Markup {
    html! {
        form action=(url_for!(r, "search")) {
            input name="q" id="q" type="search" placeholder="Search" value=(value.unwrap_or("")) /
        }
        @if value.is_none() {
            script (PreEscaped("document.getElementById('q').select()"))
        }
    }
}

pub fn not_found(r: &Request) -> Markup {
    layout(r, Some("Not found"), html! {
        p {
            "The page at "
            strong (r.url)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

pub fn search(r: &Request) -> Markup {
    layout(r, Some("Search"), html! {
        (search_form(r, None))
    })
}

pub fn search_results<'u, I>(r: &Request, query: &str, results: I) -> Markup where
    I: Iterator<Item=(Result<&'u User, &'u str>, String, u64)>,
{
    let title = format!("Search results for “{}”", query);
    let results = results.map(|(user, id, weight)| match user {
        Ok(user) => (user_box(r, &id, &user), id, weight),
        Err(..) => ((id.clone(), html! {}), id, weight),
    });
    let mut results = results.peekable();
    layout_inner(r, Some(&title), None, html! {
        (search_form(r, Some(query)))
        @if results.peek().is_none() {
            p "No results found."
        }
        @for ((user_title, user_markup), id, weight) in results {
            h3 title={ "Weight: " (weight) } {
                a href=(url_for!(r, "user", "id" => &id[..])) (user_title)
            }
            (user_markup)
            hr /
        }
    })
}

pub fn user(r: &Request, id: &str, user: &User) -> Markup {
    let (title, body) = user_box(r, id, user);
    layout(r, Some(&title), body)
}

fn user_box(_r: &Request, id: &str, user: &User) -> (String, Markup) {
    let title = if let Some(ref name) = user.name {
        format!("{} ({})", name, id)
    } else {
        id.to_string()
    };
    (title, html! {
        table {
            @if let Some(ref nick) = user.irc {
                tr {
                    th "IRC"
                    td {
                        (nick)
                        @if !user.irc_channels.is_empty() {
                            " on "
                            @for (i, channel) in user.irc_channels.iter().enumerate() {
                                @if i > 0 { ", " }
                                a href={ "irc://irc.mozilla.org/" (channel) } {
                                    "#" (channel)
                                }
                            }
                        }
                    }
                }
            }
            @if let Some(ref x) = user.discourse {
                tr {
                    th "Discourse"
                    td a href={ "https://users.rust-lang.org/users/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.reddit {
                tr {
                    th "Reddit"
                    td a href={ "https://reddit.com/user/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.twitter {
                tr {
                    th "Twitter"
                    td a href={ "https://twitter.com/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.website {
                tr {
                    th "Website"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.blog {
                tr {
                    th "Blog"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.email {
                tr {
                    th "Email"
                    td a href={ "mailto:" (x) } (x)
                }
            }
        }
        @if let Some(ref x) = user.notes {
            div.notes (Markdown(x))
        }
    })
}

pub fn user_error(r: &Request, id: &str, error: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " exists, but their entry could not be parsed."
        }
        p {
            "(Error: " (error) ")"
        }
    })
}

pub fn user_not_found(r: &Request, id: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

struct Markdown<'a>(&'a str);

impl<'a> Render for Markdown<'a> {
    fn render_to(&self, buffer: &mut String) {
        let parser = pulldown_cmark::Parser::new(self.0);
        pulldown_cmark::html::push_html(buffer, parser);
    }
}
<|endoftext|>