<commit_before>#![macro_use]

use ast::Ast;
use ast_walk::{walk, LazyWalkReses, WalkRule};
use form::Form;
use name::*;
use num::bigint::BigInt;
use std::{self, rc::Rc};
use util::assoc::Assoc;
use walk_mode::{NegativeWalkMode, WalkMode};

/// Values in Unseemly.

#[derive(Debug, Clone, PartialEq)]
pub enum Value {
    Int(BigInt),
    Sequence(Vec<Rc<Value>>), // TODO: switch to a different core sequence type
    Function(Rc<Closure>),    // TODO: unsure if this Rc is needed
    BuiltInFunction(BIF),
    AbstractSyntax(Ast), // Unsure if this needs an Rc.
    Struct(Assoc<Name, Value>),
    Enum(Name, Vec<Value>), // A real compiler would probably tag with numbers...
}

pub use self::Value::*;

#[derive(Debug, Clone, PartialEq)]
pub struct Closure {
    pub body: Ast,
    pub params: Vec<Name>,
    pub env: Assoc<Name, Value>,
}

// Built-in function
pub struct BIF(pub Rc<(dyn Fn(Vec<Value>) -> Value)>);

impl PartialEq for BIF {
    fn eq(&self, other: &BIF) -> bool { self as *const BIF == other as *const BIF }
}

impl Clone for BIF {
    fn clone(&self) -> BIF { BIF(self.0.clone()) }
}

impl std::fmt::Display for Value {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            Int(ref bi) => write!(f, "{}", bi),
            Sequence(ref seq) => {
                for elt in seq {
                    write!(f, "{}", &*elt)?;
                }
                Ok(())
            }
            Function(_) => write!(f, "[closure]"),
            BuiltInFunction(_) => write!(f, "[built-in function]"),
            AbstractSyntax(ref ast) => write!(f, "'[{}]'", ast),
            Struct(ref parts) => {
                write!(f, "*[")?;
                for (k, v) in parts.iter_pairs() {
                    write!(f, "{}: {} ", k, v)?;
                }
                write!(f, "]*")
            }
            Enum(n, ref parts) => {
                write!(f, "+[{}", n)?;
                for p in parts.iter() {
                    write!(f, " {}", p)?;
                }
                write!(f, "]+")
            }
        }
    }
}

impl std::fmt::Debug for BIF {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str("[built-in function]")
    }
}

impl ::walk_mode::WalkElt for Value {
    fn from_ast(a: &Ast) -> Value { AbstractSyntax(a.clone()) }
    fn to_ast(&self) -> Ast {
        match *self {
            AbstractSyntax(ref a) => a.clone(),
            _ => icp!("[type error] {} is not syntax", self),
        }
    }

    fn core_env() -> Assoc<Name, Self> { ::runtime::core_values::core_values() }
}

custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct Eval {}
}
custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct Destructure {}
}

impl WalkMode for Eval {
    fn name() -> &'static str { "Evalu" }

    type Elt = Value;
    type Negated = Destructure;
    type Err = ();
    type D = ::walk_mode::Positive<Eval>;
    type ExtraInfo = ();

    fn get_walk_rule(f: &Form) -> WalkRule<Eval> { f.eval.pos().clone() }
    fn automatically_extend_env() -> bool { true }

    fn walk_var(n: Name, cnc: &LazyWalkReses<Eval>) -> Result<Value, ()> {
        Ok(cnc.env.find(&n).expect("Undefined var; did you use a type name as a value?").clone())
    }

    // TODO: maybe keep this from being called?
    fn underspecified(_: Name) -> Value { val!(enum "why is this here?", ) }
}

impl WalkMode for Destructure {
    fn name() -> &'static str { "Destr" }

    type Elt = Value;
    type Negated = Eval;
    type Err = ();
    type D = ::walk_mode::Negative<Destructure>;
    type ExtraInfo = ();

    /// The whole point of program evaluation is that the enviornment
    ///  isn't generateable from the source tree.
    /// Does that make sense? I suspect it does not.
    fn get_walk_rule(f: &Form) -> WalkRule<Destructure> { f.eval.neg().clone() }
    fn automatically_extend_env() -> bool { true } // TODO: think about this
}

impl NegativeWalkMode for Destructure {
    fn needs_pre_match() -> bool { false } // Values don't have binding (in this mode!)
}

impl ::walk_mode::WalkElt for Ast {
    fn from_ast(a: &Ast) -> Ast { a.clone() }
    fn to_ast(&self) -> Ast { self.clone() }
}

pub fn eval_top(expr: &Ast) -> Result<Value, ()> { eval(expr, Assoc::new()) }

pub fn eval(expr: &Ast, env: Assoc<Name, Value>) -> Result<Value, ()> {
    walk::<Eval>(expr, &LazyWalkReses::new_wrapper(env))
}

pub fn neg_eval(pat: &Ast, env: Assoc<Name, Value>) -> Result<Assoc<Name, Value>, ()> {
    walk::<Destructure>(pat, &LazyWalkReses::new_wrapper(env))
}

custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct QQuote {}
}
custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct QQuoteDestr {}
}

impl WalkMode for QQuote {
    fn name() -> &'static str { "QQuote" }

    // Why not `Ast`? Because QQuote and Eval need to share environments.
    type Elt = Value;
    type Negated = QQuoteDestr;
    type Err = ();
    type D = ::walk_mode::Positive<QQuote>;
    type ExtraInfo = ();

    fn walk_var(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> {
        let n_sp = &n.sp();
        Ok(val!(ast (vr n_sp)))
    }
    fn walk_atom(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> {
        let n_sp = &n.sp();
        Ok(val!(ast n_sp))
    }
    fn get_walk_rule(f: &Form) -> WalkRule<QQuote> { f.quasiquote.pos().clone() }
    fn automatically_extend_env() -> bool { false }
}

impl WalkMode for QQuoteDestr {
    fn name() -> &'static str { "QQDes" }

    type Elt = Value;
    type Negated = QQuote;
    type Err = ();
    type D = ::walk_mode::Negative<QQuoteDestr>;
    type ExtraInfo = ();

    fn walk_var(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
        let n_sp = &n.sp();
        if cnc.context_elt() == &val!(ast (vr n_sp)) {
            Ok(Assoc::<Name, Value>::new())
        } else {
            Err(Self::qlit_mismatch_error(val!(ast (vr n_sp)), cnc.context_elt().clone()))
        }
    }
    fn walk_atom(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
        let n_sp = &n.sp();
        if cnc.context_elt() == &val!(ast n_sp) {
            Ok(Assoc::<Name, Value>::new())
        } else {
            Err(Self::qlit_mismatch_error(val!(ast (vr n_sp)), cnc.context_elt().clone()))
        }
    }
    fn get_walk_rule(f: &Form) -> WalkRule<QQuoteDestr> { f.quasiquote.neg().clone() }
    fn automatically_extend_env() -> bool { false }
}

impl NegativeWalkMode for QQuoteDestr {
    fn needs_pre_match() -> bool { true } // Quoted syntax does have binding!
}

// `env` is a trap! We want a shifted `LazyWalkReses`!
// pub fn qquote(expr: &Ast, env: Assoc<Name, Value>) -> Result<Value, ()> {
//     walk::<QQuote>(expr, &LazyWalkReses::new_wrapper(env))
// }
//
// pub fn qquote_destr(pat: &Ast, env: Assoc<Name, Value>)
//         -> Result<Assoc<Name, Value>,()> {
//     walk::<QQuoteDestr>(pat, &LazyWalkReses::new_wrapper(env))
// }
<commit_msg>Make an error message clearer.<commit_after>#![macro_use]

use ast::Ast;
use ast_walk::{walk, LazyWalkReses, WalkRule};
use form::Form;
use name::*;
use num::bigint::BigInt;
use std::{self, rc::Rc};
use util::assoc::Assoc;
use walk_mode::{NegativeWalkMode, WalkMode};

/// Values in Unseemly.

#[derive(Debug, Clone, PartialEq)]
pub enum Value {
    Int(BigInt),
    Sequence(Vec<Rc<Value>>), // TODO: switch to a different core sequence type
    Function(Rc<Closure>),    // TODO: unsure if this Rc is needed
    BuiltInFunction(BIF),
    AbstractSyntax(Ast), // Unsure if this needs an Rc.
    Struct(Assoc<Name, Value>),
    Enum(Name, Vec<Value>), // A real compiler would probably tag with numbers...
}

pub use self::Value::*;

#[derive(Debug, Clone, PartialEq)]
pub struct Closure {
    pub body: Ast,
    pub params: Vec<Name>,
    pub env: Assoc<Name, Value>,
}

// Built-in function
pub struct BIF(pub Rc<(dyn Fn(Vec<Value>) -> Value)>);

impl PartialEq for BIF {
    fn eq(&self, other: &BIF) -> bool { self as *const BIF == other as *const BIF }
}

impl Clone for BIF {
    fn clone(&self) -> BIF { BIF(self.0.clone()) }
}

impl std::fmt::Display for Value {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            Int(ref bi) => write!(f, "{}", bi),
            Sequence(ref seq) => {
                for elt in seq {
                    write!(f, "{}", &*elt)?;
                }
                Ok(())
            }
            Function(_) => write!(f, "[closure]"),
            BuiltInFunction(_) => write!(f, "[built-in function]"),
            AbstractSyntax(ref ast) => write!(f, "'[{}]'", ast),
            Struct(ref parts) => {
                write!(f, "*[")?;
                for (k, v) in parts.iter_pairs() {
                    write!(f, "{}: {} ", k, v)?;
                }
                write!(f, "]*")
            }
            Enum(n, ref parts) => {
                write!(f, "+[{}", n)?;
                for p in parts.iter() {
                    write!(f, " {}", p)?;
                }
                write!(f, "]+")
            }
        }
    }
}

impl std::fmt::Debug for BIF {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        formatter.write_str("[built-in function]")
    }
}

impl ::walk_mode::WalkElt for Value {
    fn from_ast(a: &Ast) -> Value { AbstractSyntax(a.clone()) }
    fn to_ast(&self) -> Ast {
        match *self {
            AbstractSyntax(ref a) => a.clone(),
            _ => icp!("[type error] {} is not syntax", self),
        }
    }

    fn core_env() -> Assoc<Name, Self> { ::runtime::core_values::core_values() }
}

custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct Eval {}
}
custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct Destructure {}
}

impl WalkMode for Eval {
    fn name() -> &'static str { "Evalu" }

    type Elt = Value;
    type Negated = Destructure;
    type Err = ();
    type D = ::walk_mode::Positive<Eval>;
    type ExtraInfo = ();

    fn get_walk_rule(f: &Form) -> WalkRule<Eval> { f.eval.pos().clone() }
    fn automatically_extend_env() -> bool { true }

    fn walk_var(n: Name, cnc: &LazyWalkReses<Eval>) -> Result<Value, ()> {
        match cnc.env.find(&n) {
            Some(v) => Ok(v.clone()),
            None => panic!("Undefined var `{}` in {}", n, cnc.env),
        }
    }

    // TODO: maybe keep this from being called?
    fn underspecified(_: Name) -> Value { val!(enum "why is this here?", ) }
}

impl WalkMode for Destructure {
    fn name() -> &'static str { "Destr" }

    type Elt = Value;
    type Negated = Eval;
    type Err = ();
    type D = ::walk_mode::Negative<Destructure>;
    type ExtraInfo = ();

    /// The whole point of program evaluation is that the enviornment
    ///  isn't generateable from the source tree.
    /// Does that make sense? I suspect it does not.
    fn get_walk_rule(f: &Form) -> WalkRule<Destructure> { f.eval.neg().clone() }
    fn automatically_extend_env() -> bool { true } // TODO: think about this
}

impl NegativeWalkMode for Destructure {
    fn needs_pre_match() -> bool { false } // Values don't have binding (in this mode!)
}

impl ::walk_mode::WalkElt for Ast {
    fn from_ast(a: &Ast) -> Ast { a.clone() }
    fn to_ast(&self) -> Ast { self.clone() }
}

pub fn eval_top(expr: &Ast) -> Result<Value, ()> { eval(expr, Assoc::new()) }

pub fn eval(expr: &Ast, env: Assoc<Name, Value>) -> Result<Value, ()> {
    walk::<Eval>(expr, &LazyWalkReses::new_wrapper(env))
}

pub fn neg_eval(pat: &Ast, env: Assoc<Name, Value>) -> Result<Assoc<Name, Value>, ()> {
    walk::<Destructure>(pat, &LazyWalkReses::new_wrapper(env))
}

custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct QQuote {}
}
custom_derive! {
    #[derive(Copy, Clone, Debug, Reifiable)]
    pub struct QQuoteDestr {}
}

impl WalkMode for QQuote {
    fn name() -> &'static str { "QQuote" }

    // Why not `Ast`? Because QQuote and Eval need to share environments.
    type Elt = Value;
    type Negated = QQuoteDestr;
    type Err = ();
    type D = ::walk_mode::Positive<QQuote>;
    type ExtraInfo = ();

    fn walk_var(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> {
        let n_sp = &n.sp();
        Ok(val!(ast (vr n_sp)))
    }
    fn walk_atom(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> {
        let n_sp = &n.sp();
        Ok(val!(ast n_sp))
    }
    fn get_walk_rule(f: &Form) -> WalkRule<QQuote> { f.quasiquote.pos().clone() }
    fn automatically_extend_env() -> bool { false }
}

impl WalkMode for QQuoteDestr {
    fn name() -> &'static str { "QQDes" }

    type Elt = Value;
    type Negated = QQuote;
    type Err = ();
    type D = ::walk_mode::Negative<QQuoteDestr>;
    type ExtraInfo = ();

    fn walk_var(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
        let n_sp = &n.sp();
        if cnc.context_elt() == &val!(ast (vr n_sp)) {
            Ok(Assoc::<Name, Value>::new())
        } else {
            Err(Self::qlit_mismatch_error(val!(ast (vr n_sp)), cnc.context_elt().clone()))
        }
    }
    fn walk_atom(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
        let n_sp = &n.sp();
        if cnc.context_elt() == &val!(ast n_sp) {
            Ok(Assoc::<Name, Value>::new())
        } else {
            Err(Self::qlit_mismatch_error(val!(ast (vr n_sp)), cnc.context_elt().clone()))
        }
    }
    fn get_walk_rule(f: &Form) -> WalkRule<QQuoteDestr> { f.quasiquote.neg().clone() }
    fn automatically_extend_env() -> bool { false }
}

impl NegativeWalkMode for QQuoteDestr {
    fn needs_pre_match() -> bool { true } // Quoted syntax does have binding!
}

// `env` is a trap! We want a shifted `LazyWalkReses`!
// pub fn qquote(expr: &Ast, env: Assoc<Name, Value>) -> Result<Value, ()> {
//     walk::<QQuote>(expr, &LazyWalkReses::new_wrapper(env))
// }
//
// pub fn qquote_destr(pat: &Ast, env: Assoc<Name, Value>)
//         -> Result<Assoc<Name, Value>,()> {
//     walk::<QQuoteDestr>(pat, &LazyWalkReses::new_wrapper(env))
// }
<|endoftext|>


<commit_before>pub use sys::cpuinfo as ll;

pub const CACHELINESIZE: isize = 128;

pub fn get_cpu_count() -> isize {
    unsafe { ll::SDL_GetCPUCount() as isize }
}

pub fn get_cpu_cache_line_size() -> isize {
    unsafe { ll::SDL_GetCPUCacheLineSize() as isize}
}

pub fn has_rdtsc() -> bool {
    unsafe { ll::SDL_HasRDTSC() == 1 }
}

pub fn has_alti_vec() -> bool {
    unsafe { ll::SDL_HasAltiVec() == 1 }
}

pub fn has_mmx() -> bool {
    unsafe { ll::SDL_HasMMX() == 1 }
}

pub fn has_3d_now() -> bool {
    unsafe { ll::SDL_Has3DNow() == 1 }
}

pub fn has_sse() -> bool {
    unsafe { ll::SDL_HasSSE() == 1 }
}

pub fn has_sse2() -> bool {
    unsafe { ll::SDL_HasSSE2() == 1 }
}

pub fn has_sse3() -> bool {
    unsafe { ll::SDL_HasSSE3() == 1 }
}

pub fn has_sse41() -> bool {
    unsafe { ll::SDL_HasSSE41() == 1 }
}

pub fn has_sse42() -> bool {
    unsafe { ll::SDL_HasSSE42() == 1 }
}

pub fn has_avx() -> bool {
    unsafe { ll::SDL_HasAVX() == 1 }
}

pub fn get_system_ram() -> isize {
    unsafe { ll::SDL_GetSystemRAM() as isize }
}
<commit_msg>Use correct integer types in cpuinfo<commit_after>pub use sys::cpuinfo as ll;

pub const CACHELINESIZE: u8 = 128;

pub fn get_cpu_count() -> i32 {
    unsafe { ll::SDL_GetCPUCount() }
}

pub fn get_cpu_cache_line_size() -> i32 {
    unsafe { ll::SDL_GetCPUCacheLineSize() }
}

pub fn has_rdtsc() -> bool {
    unsafe { ll::SDL_HasRDTSC() == 1 }
}

pub fn has_alti_vec() -> bool {
    unsafe { ll::SDL_HasAltiVec() == 1 }
}

pub fn has_mmx() -> bool {
    unsafe { ll::SDL_HasMMX() == 1 }
}

pub fn has_3d_now() -> bool {
    unsafe { ll::SDL_Has3DNow() == 1 }
}

pub fn has_sse() -> bool {
    unsafe { ll::SDL_HasSSE() == 1 }
}

pub fn has_sse2() -> bool {
    unsafe { ll::SDL_HasSSE2() == 1 }
}

pub fn has_sse3() -> bool {
    unsafe { ll::SDL_HasSSE3() == 1 }
}

pub fn has_sse41() -> bool {
    unsafe { ll::SDL_HasSSE41() == 1 }
}

pub fn has_sse42() -> bool {
    unsafe { ll::SDL_HasSSE42() == 1 }
}

pub fn has_avx() -> bool {
    unsafe { ll::SDL_HasAVX() == 1 }
}

pub fn get_system_ram() -> i32 {
    unsafe { ll::SDL_GetSystemRAM() }
}
<|endoftext|>


<commit_before>#![crate_id="sdl2_ttf#sdl2_ttf:0.1"]
#![crate_type = "lib"]
#![desc = "SDL2_ttf bindings and wrappers"]
#![comment = "SDL2_ttf bindings and wrappers"]
#![license = "MIT"]

extern crate sdl2;

use std::libc::{c_int, c_long};
use std::ptr;
use std::c_str::CString;
use std::num::FromPrimitive;
use sdl2::surface::Surface;
use sdl2::get_error;
use sdl2::pixels;
use sdl2::pixels::Color;
use sdl2::pixels::ll::SDL_Color;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_ttf")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_ttf")]
    extern {}
}

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link(name="SDL2_ttf")]
    extern {}
}

#[allow(non_camel_case_types, dead_code)]
mod ffi;

#[deriving(Show)]
pub enum Style {
    StyleNormal = ffi::TTF_STYLE_NORMAL as int,
    StyleBold   = ffi::TTF_STYLE_BOLD   as int,
    StyleItalic = ffi::TTF_STYLE_ITALIC as int,
    StyleUnderline = ffi::TTF_STYLE_UNDERLINE as int,
    StyleStrikeThrough = ffi::TTF_STYLE_STRIKETHROUGH as int
}

#[deriving(Show, Eq, FromPrimitive)]
pub enum Hinting {
    HintingNormal = ffi::TTF_HINTING_NORMAL as int,
    HintingLight  = ffi::TTF_HINTING_LIGHT  as int,
    HintingMono   = ffi::TTF_HINTING_MONO   as int,
    HintingNone   = ffi::TTF_HINTING_NONE   as int
}

#[deriving(Eq, Show)]
pub struct GlyphMetrics {
    minx: int,
    maxx: int,
    miny: int,
    maxy: int,
    advance: int
}

#[inline]
fn color_to_c_color(color: Color) -> SDL_Color {
    match color {
        pixels::RGB(r, g, b)     => SDL_Color { r: r, g: g, b: b, a: 255 },
        pixels::RGBA(r, g, b, a) => SDL_Color { r: r, g: g, b: b, a: a   }
    }
}

pub fn init() -> bool {
    unsafe {
        if ffi::TTF_WasInit() == 1 {
            true
        } else {
            ffi::TTF_Init() == 0
        }
    }
}

pub fn was_inited() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}

pub fn quit() {
    unsafe { ffi::TTF_Quit(); }
}

#[allow(raw_pointer_deriving)]
#[deriving(Eq)]
pub struct Font {
    priv raw: *ffi::TTF_Font,
    priv owned: bool
}

impl Drop for Font {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                // avoid close font after quit()
                if ffi::TTF_WasInit() == 1 {
                    ffi::TTF_CloseFont(self.raw);
                }
            }
        }
    }
}

fn wrap_font_styles(bitflags: u32) -> Vec<Style> {
    let styles = [StyleBold, StyleItalic, StyleUnderline, StyleStrikeThrough];
    styles.iter().filter_map(|&flag| {
        if bitflags & (flag as u32) != 0 { Some(flag) }
        else { None }
    }).collect()
}

impl Font {
    pub fn from_file(filename: &Path, ptsize: int) -> Result<~Font, ~str> {
        unsafe {
            let raw = ffi::TTF_OpenFont(filename.to_c_str().unwrap(), ptsize as c_int);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Font { raw: raw, owned: true })
            }
        }
    }

    pub fn from_file_index(filename: &Path, ptsize: int, index: int) -> Result<~Font, ~str> {
        unsafe {
            let raw = ffi::TTF_OpenFontIndex(filename.to_c_str().unwrap(), ptsize as c_int, index as c_long);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Font { raw: raw, owned: true })
            }
        }
    }

    pub fn get_style(&self) -> Vec<Style> {
        let raw = unsafe { ffi::TTF_GetFontStyle(self.raw) };
        wrap_font_styles(raw as u32)
    }

    pub fn set_style(&self, styles: &[Style]) {
        let flags = styles.iter().fold(0i32, |flags, flag| { flags | *flag as i32 });
        unsafe {
            ffi::TTF_SetFontStyle(self.raw, flags)
        }
    }

    pub fn get_outline(&self) -> int {
        unsafe {
            ffi::TTF_GetFontOutline(self.raw) as int
        }
    }

    pub fn set_outline(&self, outline: int) {
        unsafe {
            ffi::TTF_SetFontOutline(self.raw, outline as c_int)
        }
    }

    pub fn get_hinting(&self) -> Hinting {
        unsafe {
            FromPrimitive::from_i32(ffi::TTF_GetFontHinting(self.raw)).unwrap()
        }
    }

    pub fn set_hinting(&self, hinting: Hinting) {
        unsafe {
            ffi::TTF_SetFontHinting(self.raw, hinting as c_int)
        }
    }

    pub fn get_kerning(&self) -> bool {
        unsafe {
            ffi::TTF_GetFontKerning(self.raw) != 0
        }
    }

    pub fn set_kerning(&self, kerning: bool) {
        unsafe {
            ffi::TTF_SetFontKerning(self.raw, kerning as c_int)
        }
    }

    pub fn height(&self) -> int {
        unsafe {
            ffi::TTF_FontHeight(self.raw) as int
        }
    }

    pub fn ascent(&self) -> int {
        unsafe {
            ffi::TTF_FontAscent(self.raw) as int
        }
    }

    pub fn descent(&self) -> int {
        unsafe {
            ffi::TTF_FontDescent(self.raw) as int
        }
    }

    pub fn line_skip(&self) -> int {
        unsafe {
            ffi::TTF_FontLineSkip(self.raw) as int
        }
    }

    pub fn faces(&self) -> int {
        unsafe {
            ffi::TTF_FontFaces(self.raw) as int
        }
    }

    pub fn face_is_fixed_width(&self) -> bool {
        unsafe {
            ffi::TTF_FontFaceIsFixedWidth(self.raw) != 0
        }
    }

    pub fn face_family_name(&self) -> Option<~str> {
        unsafe {
            // not owns buffer
            let cname = ffi::TTF_FontFaceFamilyName(self.raw);
            if cname == ptr::null() {
                None
            } else {
                Some(CString::new(cname, false).as_str().unwrap().into_owned())
            }
        }
    }

    pub fn face_style_name(&self) -> Option<~str> {
        unsafe {
            let cname = ffi::TTF_FontFaceStyleName(self.raw);
            if cname == ptr::null() {
                None
            } else {
                Some(CString::new(cname, false).as_str().unwrap().into_owned())
            }
        }
    }

    // FIXME: bug
    pub fn glyph_is_provided(&self, ch: char) -> Option<uint> {
        unsafe {
            let ret = ffi::TTF_GlyphIsProvided(self.raw, ch as u16);
            if ret == 0 {
                None
            } else {
                Some(ret as uint)
            }
        }
    }

    pub fn glyph_metrics(&self, ch: char) -> Option<GlyphMetrics> {
        let minx = 0;
        let maxx = 0;
        let miny = 0;
        let maxy = 0;
        let advance = 0;
        let ret = unsafe {
            ffi::TTF_GlyphMetrics(self.raw, ch as u16,
                                  &minx, &maxx, &miny, &maxy, &advance)
        };
        if ret != 0 {
            None
        } else {
            Some(GlyphMetrics { minx: minx as int, maxx: maxx as int,
                                miny: miny as int, maxy: maxy as int,
                                advance: advance as int })
        }
    }

    pub fn size_bytes(&self, text: &[u8]) -> Result<(int, int), ~str> {
        let w = 0;
        let h = 0;
        let ret = unsafe {
            text.with_c_str(|ctext| {
                    ffi::TTF_SizeText(self.raw, ctext, &w, &h)
                })
        };
        if ret != 0 {
            Err(get_error())
        } else {
            Ok((w as int, h as int))
        }
    }

    pub fn size_str(&self, text: &str) -> Result<(int, int), ~str> {
        let w = 0;
        let h = 0;
        let ret = unsafe {
            text.with_c_str(|ctext| {
                    ffi::TTF_SizeUTF8(self.raw, ctext, &w, &h)
                })
        };
        if ret != 0 {
            Err(get_error())
        } else {
            Ok((w as int, h as int))
        }
    }

    // FIXME: represent UNICODE str in Rust
    pub fn size_unicode(&self, _text: &[u16]) -> Result<(int, int), ~str> {
        unimplemented!()
        // let w = 0;
        // let h = 0;
        // let ret = unsafe {
        //     ffi::TTF_SizeUNICODE(self.raw, cast::transmute(&ctext[0]), &w, &h)
        // };
        // if ret != 0 {
        //     Err(get_error())
        // } else {
        //     Ok((w as int, h as int))
        // }
    }

    pub fn render_bytes_solid(&self, text: &[u8], fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Solid(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_solid(&self, text: &str, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Solid(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_solid(&self, ch: char, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Solid(self.raw, ch as u16, color_to_c_color(fg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

        pub fn render_bytes_shaded(&self, text: &[u8], fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Shaded(self.raw, ctext, color_to_c_color(fg), color_to_c_color(bg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_shaded(&self, text: &str, fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Shaded(self.raw, ctext, color_to_c_color(fg), color_to_c_color(bg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_shaded(&self, ch: char, fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Shaded(self.raw, ch as u16, color_to_c_color(fg), color_to_c_color(bg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_bytes_blended(&self, text: &[u8], fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Blended(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_blended(&self, text: &str, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Blended(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_blended(&self, ch: char, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Blended(self.raw, ch as u16, color_to_c_color(fg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

}
<commit_msg>fix compile error: struct field now default private<commit_after>#![crate_id="sdl2_ttf#sdl2_ttf:0.1"]
#![crate_type = "lib"]
#![desc = "SDL2_ttf bindings and wrappers"]
#![comment = "SDL2_ttf bindings and wrappers"]
#![license = "MIT"]

extern crate sdl2;

use std::libc::{c_int, c_long};
use std::ptr;
use std::c_str::CString;
use std::num::FromPrimitive;
use sdl2::surface::Surface;
use sdl2::get_error;
use sdl2::pixels;
use sdl2::pixels::Color;
use sdl2::pixels::ll::SDL_Color;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_ttf")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_ttf")]
    extern {}
}

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link(name="SDL2_ttf")]
    extern {}
}

#[allow(non_camel_case_types, dead_code)]
mod ffi;

#[deriving(Show)]
pub enum Style {
    StyleNormal = ffi::TTF_STYLE_NORMAL as int,
    StyleBold   = ffi::TTF_STYLE_BOLD   as int,
    StyleItalic = ffi::TTF_STYLE_ITALIC as int,
    StyleUnderline = ffi::TTF_STYLE_UNDERLINE as int,
    StyleStrikeThrough = ffi::TTF_STYLE_STRIKETHROUGH as int
}

#[deriving(Show, Eq, FromPrimitive)]
pub enum Hinting {
    HintingNormal = ffi::TTF_HINTING_NORMAL as int,
    HintingLight  = ffi::TTF_HINTING_LIGHT  as int,
    HintingMono   = ffi::TTF_HINTING_MONO   as int,
    HintingNone   = ffi::TTF_HINTING_NONE   as int
}

#[deriving(Eq, Show)]
pub struct GlyphMetrics {
    minx: int,
    maxx: int,
    miny: int,
    maxy: int,
    advance: int
}

#[inline]
fn color_to_c_color(color: Color) -> SDL_Color {
    match color {
        pixels::RGB(r, g, b)     => SDL_Color { r: r, g: g, b: b, a: 255 },
        pixels::RGBA(r, g, b, a) => SDL_Color { r: r, g: g, b: b, a: a   }
    }
}

pub fn init() -> bool {
    unsafe {
        if ffi::TTF_WasInit() == 1 {
            true
        } else {
            ffi::TTF_Init() == 0
        }
    }
}

pub fn was_inited() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}

pub fn quit() {
    unsafe { ffi::TTF_Quit(); }
}

#[allow(raw_pointer_deriving)]
#[deriving(Eq)]
pub struct Font {
    raw: *ffi::TTF_Font,
    owned: bool
}

impl Drop for Font {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                // avoid close font after quit()
                if ffi::TTF_WasInit() == 1 {
                    ffi::TTF_CloseFont(self.raw);
                }
            }
        }
    }
}

fn wrap_font_styles(bitflags: u32) -> Vec<Style> {
    let styles = [StyleBold, StyleItalic, StyleUnderline, StyleStrikeThrough];
    styles.iter().filter_map(|&flag| {
        if bitflags & (flag as u32) != 0 { Some(flag) }
        else { None }
    }).collect()
}

impl Font {
    pub fn from_file(filename: &Path, ptsize: int) -> Result<~Font, ~str> {
        unsafe {
            let raw = ffi::TTF_OpenFont(filename.to_c_str().unwrap(), ptsize as c_int);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Font { raw: raw, owned: true })
            }
        }
    }

    pub fn from_file_index(filename: &Path, ptsize: int, index: int) -> Result<~Font, ~str> {
        unsafe {
            let raw = ffi::TTF_OpenFontIndex(filename.to_c_str().unwrap(), ptsize as c_int, index as c_long);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Font { raw: raw, owned: true })
            }
        }
    }

    pub fn get_style(&self) -> Vec<Style> {
        let raw = unsafe { ffi::TTF_GetFontStyle(self.raw) };
        wrap_font_styles(raw as u32)
    }

    pub fn set_style(&self, styles: &[Style]) {
        let flags = styles.iter().fold(0i32, |flags, flag| { flags | *flag as i32 });
        unsafe {
            ffi::TTF_SetFontStyle(self.raw, flags)
        }
    }

    pub fn get_outline(&self) -> int {
        unsafe {
            ffi::TTF_GetFontOutline(self.raw) as int
        }
    }

    pub fn set_outline(&self, outline: int) {
        unsafe {
            ffi::TTF_SetFontOutline(self.raw, outline as c_int)
        }
    }

    pub fn get_hinting(&self) -> Hinting {
        unsafe {
            FromPrimitive::from_i32(ffi::TTF_GetFontHinting(self.raw)).unwrap()
        }
    }

    pub fn set_hinting(&self, hinting: Hinting) {
        unsafe {
            ffi::TTF_SetFontHinting(self.raw, hinting as c_int)
        }
    }

    pub fn get_kerning(&self) -> bool {
        unsafe {
            ffi::TTF_GetFontKerning(self.raw) != 0
        }
    }

    pub fn set_kerning(&self, kerning: bool) {
        unsafe {
            ffi::TTF_SetFontKerning(self.raw, kerning as c_int)
        }
    }

    pub fn height(&self) -> int {
        unsafe {
            ffi::TTF_FontHeight(self.raw) as int
        }
    }

    pub fn ascent(&self) -> int {
        unsafe {
            ffi::TTF_FontAscent(self.raw) as int
        }
    }

    pub fn descent(&self) -> int {
        unsafe {
            ffi::TTF_FontDescent(self.raw) as int
        }
    }

    pub fn line_skip(&self) -> int {
        unsafe {
            ffi::TTF_FontLineSkip(self.raw) as int
        }
    }

    pub fn faces(&self) -> int {
        unsafe {
            ffi::TTF_FontFaces(self.raw) as int
        }
    }

    pub fn face_is_fixed_width(&self) -> bool {
        unsafe {
            ffi::TTF_FontFaceIsFixedWidth(self.raw) != 0
        }
    }

    pub fn face_family_name(&self) -> Option<~str> {
        unsafe {
            // not owns buffer
            let cname = ffi::TTF_FontFaceFamilyName(self.raw);
            if cname == ptr::null() {
                None
            } else {
                Some(CString::new(cname, false).as_str().unwrap().into_owned())
            }
        }
    }

    pub fn face_style_name(&self) -> Option<~str> {
        unsafe {
            let cname = ffi::TTF_FontFaceStyleName(self.raw);
            if cname == ptr::null() {
                None
            } else {
                Some(CString::new(cname, false).as_str().unwrap().into_owned())
            }
        }
    }

    // FIXME: bug
    pub fn glyph_is_provided(&self, ch: char) -> Option<uint> {
        unsafe {
            let ret = ffi::TTF_GlyphIsProvided(self.raw, ch as u16);
            if ret == 0 {
                None
            } else {
                Some(ret as uint)
            }
        }
    }

    pub fn glyph_metrics(&self, ch: char) -> Option<GlyphMetrics> {
        let minx = 0;
        let maxx = 0;
        let miny = 0;
        let maxy = 0;
        let advance = 0;
        let ret = unsafe {
            ffi::TTF_GlyphMetrics(self.raw, ch as u16,
                                  &minx, &maxx, &miny, &maxy, &advance)
        };
        if ret != 0 {
            None
        } else {
            Some(GlyphMetrics { minx: minx as int, maxx: maxx as int,
                                miny: miny as int, maxy: maxy as int,
                                advance: advance as int })
        }
    }

    pub fn size_bytes(&self, text: &[u8]) -> Result<(int, int), ~str> {
        let w = 0;
        let h = 0;
        let ret = unsafe {
            text.with_c_str(|ctext| {
                    ffi::TTF_SizeText(self.raw, ctext, &w, &h)
                })
        };
        if ret != 0 {
            Err(get_error())
        } else {
            Ok((w as int, h as int))
        }
    }

    pub fn size_str(&self, text: &str) -> Result<(int, int), ~str> {
        let w = 0;
        let h = 0;
        let ret = unsafe {
            text.with_c_str(|ctext| {
                    ffi::TTF_SizeUTF8(self.raw, ctext, &w, &h)
                })
        };
        if ret != 0 {
            Err(get_error())
        } else {
            Ok((w as int, h as int))
        }
    }

    // FIXME: represent UNICODE str in Rust
    pub fn size_unicode(&self, _text: &[u16]) -> Result<(int, int), ~str> {
        unimplemented!()
        // let w = 0;
        // let h = 0;
        // let ret = unsafe {
        //     ffi::TTF_SizeUNICODE(self.raw, cast::transmute(&ctext[0]), &w, &h)
        // };
        // if ret != 0 {
        //     Err(get_error())
        // } else {
        //     Ok((w as int, h as int))
        // }
    }

    pub fn render_bytes_solid(&self, text: &[u8], fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Solid(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_solid(&self, text: &str, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Solid(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_solid(&self, ch: char, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Solid(self.raw, ch as u16, color_to_c_color(fg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

        pub fn render_bytes_shaded(&self, text: &[u8], fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Shaded(self.raw, ctext, color_to_c_color(fg), color_to_c_color(bg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_shaded(&self, text: &str, fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Shaded(self.raw, ctext, color_to_c_color(fg), color_to_c_color(bg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_shaded(&self, ch: char, fg: Color, bg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Shaded(self.raw, ch as u16, color_to_c_color(fg), color_to_c_color(bg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_bytes_blended(&self, text: &[u8], fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderText_Blended(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_str_blended(&self, text: &str, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = text.with_c_str(|ctext| {
                    ffi::TTF_RenderUTF8_Blended(self.raw, ctext, color_to_c_color(fg))
                });
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    pub fn render_char_blended(&self, ch: char, fg: Color) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::TTF_RenderGlyph_Blended(self.raw, ch as u16, color_to_c_color(fg));
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

}
<|endoftext|>


<commit_before>use crate::*;
use rustc_target::abi::LayoutOf;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn pthread_create(
        &mut self,
        thread: OpTy<'tcx, Tag>,
        _attr: OpTy<'tcx, Tag>,
        start_routine: OpTy<'tcx, Tag>,
        arg: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.tcx.sess.warn(
            "thread support is experimental. \
             For example, Miri does not detect data races yet.",
        );

        let new_thread_id = this.create_thread()?;
        // Also switch to new thread so that we can push the first stackframe.
        let old_thread_id = this.set_active_thread(new_thread_id)?;

        let thread_info_place = this.deref_operand(thread)?;
        this.write_scalar(
            Scalar::from_uint(new_thread_id.to_u128(), thread_info_place.layout.size),
            thread_info_place.into(),
        )?;

        let fn_ptr = this.read_scalar(start_routine)?.not_undef()?;
        let instance = this.memory.get_fn(fn_ptr)?.as_instance()?;

        let func_arg = this.read_immediate(arg)?;

        let ret_place =
            this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into());

        this.call_function(
            instance,
            &[*func_arg],
            Some(ret_place.into()),
            StackPopCleanup::None { cleanup: true },
        )?;

        this.set_active_thread(old_thread_id)?;

        Ok(0)
    }

    fn pthread_join(
        &mut self,
        thread: OpTy<'tcx, Tag>,
        retval: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.is_null(this.read_scalar(retval)?.not_undef()?)? {
            throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
        }

        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
        this.join_thread(thread_id.into())?;

        Ok(0)
    }

    fn pthread_detach(&mut self, thread: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
        this.detach_thread(thread_id.into())?;

        Ok(0)
    }

    fn pthread_self(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let thread_id = this.get_active_thread()?;
        this.write_scalar(Scalar::from_uint(thread_id.to_u128(), dest.layout.size), dest)
    }

    fn prctl(
        &mut self,
        option: OpTy<'tcx, Tag>,
        arg2: OpTy<'tcx, Tag>,
        _arg3: OpTy<'tcx, Tag>,
        _arg4: OpTy<'tcx, Tag>,
        _arg5: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let option = this.read_scalar(option)?.to_i32()?;
        if option == this.eval_libc_i32("PR_SET_NAME")? {
            let address = this.read_scalar(arg2)?.not_undef()?;
            let name = this.memory.read_c_str(address)?.to_owned();
            this.set_active_thread_name(name)?;
        } else if option == this.eval_libc_i32("PR_GET_NAME")? {
            let address = this.read_scalar(arg2)?.not_undef()?;
            let name = this.get_active_thread_name()?.to_vec();
            this.memory.write_bytes(address, name)?;
        } else {
            throw_unsup_format!("unsupported prctl option {}", option);
        }

        Ok(0)
    }

    fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.yield_active_thread()?;

        Ok(0)
    }
}
<commit_msg>Add a FIXME.<commit_after>use crate::*;
use rustc_target::abi::LayoutOf;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn pthread_create(
        &mut self,
        thread: OpTy<'tcx, Tag>,
        _attr: OpTy<'tcx, Tag>,
        start_routine: OpTy<'tcx, Tag>,
        arg: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.tcx.sess.warn(
            "thread support is experimental. \
             For example, Miri does not detect data races yet.",
        );

        let new_thread_id = this.create_thread()?;
        // Also switch to new thread so that we can push the first stackframe.
        let old_thread_id = this.set_active_thread(new_thread_id)?;

        let thread_info_place = this.deref_operand(thread)?;
        this.write_scalar(
            Scalar::from_uint(new_thread_id.to_u128(), thread_info_place.layout.size),
            thread_info_place.into(),
        )?;

        let fn_ptr = this.read_scalar(start_routine)?.not_undef()?;
        let instance = this.memory.get_fn(fn_ptr)?.as_instance()?;

        let func_arg = this.read_immediate(arg)?;

        let ret_place =
            this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into());

        this.call_function(
            instance,
            &[*func_arg],
            Some(ret_place.into()),
            StackPopCleanup::None { cleanup: true },
        )?;

        this.set_active_thread(old_thread_id)?;

        Ok(0)
    }

    fn pthread_join(
        &mut self,
        thread: OpTy<'tcx, Tag>,
        retval: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.is_null(this.read_scalar(retval)?.not_undef()?)? {
            // FIXME: implement reading the thread function's return place.
            throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
        }

        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
        this.join_thread(thread_id.into())?;

        Ok(0)
    }

    fn pthread_detach(&mut self, thread: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
        this.detach_thread(thread_id.into())?;

        Ok(0)
    }

    fn pthread_self(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        let this = self.eval_context_mut();

        let thread_id = this.get_active_thread()?;
        this.write_scalar(Scalar::from_uint(thread_id.to_u128(), dest.layout.size), dest)
    }

    fn prctl(
        &mut self,
        option: OpTy<'tcx, Tag>,
        arg2: OpTy<'tcx, Tag>,
        _arg3: OpTy<'tcx, Tag>,
        _arg4: OpTy<'tcx, Tag>,
        _arg5: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let option = this.read_scalar(option)?.to_i32()?;
        if option == this.eval_libc_i32("PR_SET_NAME")? {
            let address = this.read_scalar(arg2)?.not_undef()?;
            let name = this.memory.read_c_str(address)?.to_owned();
            this.set_active_thread_name(name)?;
        } else if option == this.eval_libc_i32("PR_GET_NAME")? {
            let address = this.read_scalar(arg2)?.not_undef()?;
            let name = this.get_active_thread_name()?.to_vec();
            this.memory.write_bytes(address, name)?;
        } else {
            throw_unsup_format!("unsupported prctl option {}", option);
        }

        Ok(0)
    }

    fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        this.yield_active_thread()?;

        Ok(0)
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
extern crate hyper;

#[macro_use]
extern crate serde_derive;

use std::process::{Command};
use std::io::Read;
use hyper::header::ContentType;
use hyper::client::Client;
use serde_json::Value;

#[derive(Serialize, Deserialize)]
struct RPCRequest {
    jsonrpc: String,
    method: String,
    params: Vec<String>,
    id: usize,
}

#[derive(Serialize, Deserialize)]
struct RPCObjectRequest<T> {
    jsonrpc: String,
    method: String,
    params: T,
    id: usize,
}

#[derive(Serialize, Deserialize)]
struct RPCObjectResponse<T> {
    jsonrpc: String,
    result: T,
    id: usize,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCTransaction {
    pub hash: String,
    pub nonce: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub transactionIndex: String,
    pub from: String,
    pub to: String,
    pub value: String,
    pub gas: String,
    pub gasPrice: String,
    pub input: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCCall {
    pub from: String,
    pub to: String,
    pub gas: String,
    pub gasPrice: String,
    pub value: String,
    pub data: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCBlock {
    pub number: String,
    pub hash: String,
    pub parentHash: String,
    pub nonce: String,
    pub sha3Uncles: String,
    pub logsBloom: String,
    pub transactionsRoot: String,
    pub stateRoot: String,
    pub miner: String,
    pub difficulty: String,
    pub totalDifficulty: String,
    pub extraData: String,
    pub size: String,
    pub gasLimit: String,
    pub gasUsed: String,
    pub timestamp: String,
    pub transactions: Vec<String>,
    pub uncles: Vec<String>
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum RPCSyncStatus {
    NotSync(bool),
    Sync {
        startingBlock: String,
        currentBlock: String,
        highestBlock: String,
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCTransactionReceipt {
    pub transactionHash: String,
    pub transactionIndex: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub cumulativeGasUsed: String,
    pub gasUsed: String,
    pub contractAddress: String,
    pub logs: Vec<RPCLog>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCLog {
    pub removed: bool,
    pub logIndex: String,
    pub transactionIndex: String,
    pub transactionHash: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub address: String,
    pub data: String,
    pub topics: Vec<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCFilter {
    pub fromBlock: String,
    pub toBlock: String,
    pub address: String,
    pub topics: Vec<String>,
}

pub struct GethRPCClient {
    endpoint: String,
    free_id: usize,
}

impl GethRPCClient {
    pub fn new(endpoint: &str) -> Self {
        GethRPCClient {
            endpoint: endpoint.to_string(),
            free_id: 1,
        }
    }

    fn rpc_request<T: serde::Deserialize>(&mut self, method: &str, params: Vec<String>) -> T {
        self.rpc_object_request::<Vec<String>, T>(method, params)
    }

    fn rpc_object_request<Req: serde::Serialize, Res: serde::Deserialize>(&mut self, method: &str, params: Req) -> Res {
        let request = RPCObjectRequest {
            jsonrpc: "2.0".to_string(),
            method: method.to_string(),
            params: params,
            id: self.free_id,
        };
        self.free_id = self.free_id + 1;

        let client = Client::new();
        let mut response_raw = client.post(&self.endpoint)
            .header(ContentType::json())
            .body(&serde_json::to_string(&request).unwrap())
            .send().unwrap();
        let mut buffer = String::new();
        response_raw.read_to_string(&mut buffer).unwrap();

        let response: RPCObjectResponse<Res> = serde_json::from_str(&buffer).unwrap();
        response.result
    }

    pub fn client_version(&mut self) -> String {
        self.rpc_request::<String>("web3_clientVersion", vec![])
    }

    pub fn net_version(&mut self) -> String {
        self.rpc_request::<String>("net_version", vec![])
    }

    pub fn net_listening(&mut self) -> bool {
        self.rpc_request::<bool>("net_listening", vec![])
    }

    pub fn net_peer_count(&mut self) -> String {
        self.rpc_request::<String>("net_peerCount", vec![])
    }

    pub fn sha3(&mut self, data: &str) -> String {
        self.rpc_request::<String>("web3_sha3", vec![])
    }

    pub fn protocol_version(&mut self) -> String {
        self.rpc_request::<String>("eth_protocolVersion", vec![])
    }

    pub fn syncing(&mut self) -> RPCSyncStatus {
        self.rpc_request::<RPCSyncStatus>("eth_syncing", vec![])
    }

    pub fn coinbase(&mut self) -> String {
        self.rpc_request::<String>("eth_coinbase", vec![])
    }

    pub fn mining(&mut self) -> bool {
        self.rpc_request::<bool>("eth_mining", vec![])
    }

    pub fn hashrate(&mut self) -> String {
        self.rpc_request::<String>("eth_hashrate", vec![])
    }

    pub fn gas_price(&mut self) -> String {
        self.rpc_request::<String>("eth_gasPrice", vec![])
    }

    pub fn accounts(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_accounts", vec![])
    }

    pub fn block_number(&mut self) -> String {
        self.rpc_request::<String>("eth_blockNumber", vec![])
    }

    pub fn get_balance(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getBalance",
                                   vec![address.to_string(), number.to_string()])
    }

    pub fn get_storage_at(&mut self, address: &str, index: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getStorageAt",
                                   vec![address.to_string(), index.to_string(), number.to_string()])
    }

    pub fn get_transaction_count(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getTransactionCount",
                                   vec![address.to_string(), number.to_string()])
    }

    pub fn get_block_transaction_count_by_hash(&mut self, hash: &str) -> String {
        self.rpc_request::<String>("eth_getBlockTransactionCountByHash",
                                   vec![hash.to_string()])
    }

    pub fn get_block_transaction_count_by_number(&mut self, number: &str) -> String {
        self.rpc_request::<String>("eth_getBlockTransactionCountByNumber",
                                   vec![number.to_string()])
    }

    pub fn get_uncle_count_by_block_hash(&mut self, hash: &str) -> String {
        self.rpc_request::<String>("eth_getUncleCountByBlockHash",
                                   vec![hash.to_string()])
    }

    pub fn get_uncle_count_by_block_number(&mut self, number: &str) -> String {
        self.rpc_request::<String>("eth_getUncleCountByBlockNumber",
                                   vec![number.to_string()])
    }

    pub fn get_code(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getCode", vec![address.to_string(), number.to_string()])
    }

    pub fn sign(&mut self, address: &str, message: &str) -> String {
        self.rpc_request::<String>("eth_sign", vec![address.to_string(), message.to_string()])
    }

    pub fn send_transaction(&mut self, transaction: RPCTransaction) -> String {
        unimplemented!()
    }

    pub fn send_raw_transaction(&mut self, data: &str) -> String {
        self.rpc_request::<String>("eth_sendRawTransaction", vec![data.to_string()])
    }

    pub fn call(&mut self, transaction: RPCCall, number: &str) -> String {
        self.rpc_object_request::<(RPCCall, String), String>("eth_call", (transaction, number.to_string()))
    }

    pub fn estimate_gas(&mut self, transaction: RPCTransaction) -> String {
        unimplemented!()
    }

    pub fn get_block_by_hash(&mut self, hash: &str) -> RPCBlock {
        self.rpc_object_request::<(String, bool), RPCBlock>("eth_getBlockByHash",
                                                            (hash.to_string(), false))
    }

    pub fn get_block_by_number(&mut self, number: &str) -> RPCBlock {
        self.rpc_object_request::<(String, bool), RPCBlock>("eth_getBlockByNumber",
                                                            (number.to_string(), false))
    }

    pub fn get_transaction_by_hash(&mut self, hash: &str) -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByHash",
                                           vec![hash.to_string()])
    }

    pub fn get_transaction_by_block_hash_and_index(&mut self, hash: &str, index: &str) -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByBlockHashAndIndex",
                                           vec![hash.to_string(), index.to_string()])
    }

    pub fn get_transaction_by_block_number_and_index(&mut self, number: &str, index: &str)
                                                 -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByBlockNumberAndIndex",
                                           vec![number.to_string(), index.to_string()])
    }

    pub fn get_transaction_receipt(&mut self, hash: &str) -> RPCTransactionReceipt {
        self.rpc_request::<RPCTransactionReceipt>("eth_getTransactionReceipt",
                                                 vec![hash.to_string()])
    }

    pub fn get_uncle_by_block_hash_and_index(&mut self, hash: &str, index: &str) -> RPCBlock {
        self.rpc_request::<RPCBlock>("eth_getUncleByBlockHashAndIndex",
                                     vec![hash.to_string(), index.to_string()])
    }

    pub fn get_uncle_by_block_number_and_index(&mut self, number: &str, index: &str) -> RPCBlock {
        self.rpc_request::<RPCBlock>("eth_getUncleByBlockNumberAndIndex",
                                     vec![number.to_string(), index.to_string()])
    }

    pub fn get_compilers(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_getCompilers", vec![])
    }

    pub fn compile_solidity(&mut self, source: &str) -> String {
        unimplemented!()
    }

    pub fn compile_lll(&mut self, source: &str) -> String {
        self.rpc_request::<String>("eth_compileLLL", vec![source.to_string()])
    }

    pub fn compile_serpent(&mut self, source: &str) -> String {
        self.rpc_request::<String>("eth_compileSerpent", vec![source.to_string()])
    }

    pub fn new_filter(&mut self, filter: RPCFilter) -> String {
        unimplemented!()
    }

    pub fn new_block_filter(&mut self) -> String {
        self.rpc_request::<String>("eth_newBlockFilter", vec![])
    }

    pub fn new_pending_transaction_filter(&mut self) -> String {
        self.rpc_request::<String>("eth_newPendingTransactionFilter", vec![])
    }

    pub fn uninstall_filter(&mut self, id: &str) -> bool {
        self.rpc_request::<bool>("eth_uninstallFilter", vec![id.to_string()])
    }

    pub fn get_filter_changes(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_filter_logs(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_logs(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_work(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_getWork", vec![])
    }

    pub fn submit_work(&mut self, nonce: &str, pow: &str, mix: &str) -> bool {
        self.rpc_request::<bool>("eth_submitWork",
                                 vec![nonce.to_string(), pow.to_string(), mix.to_string()])
    }

    pub fn submit_hashrate(&mut self, hashrate: &str, id: &str) -> bool {
        self.rpc_request::<bool>("eth_submitHashrate",
                                 vec![hashrate.to_string(), id.to_string()])
    }

    pub fn put_string(&mut self, db: &str, key: &str, value: &str) -> bool {
        self.rpc_request::<bool>("db_putString",
                                 vec![db.to_string(), key.to_string(), value.to_string()])
    }

    pub fn get_string(&mut self, db: &str, key: &str) -> String {
        self.rpc_request::<String>("db_getString",
                                   vec![db.to_string(), key.to_string()])
    }

    pub fn put_hex(&mut self, db: &str, key: &str, value: &str) -> bool {
        self.rpc_request::<bool>("db_putHex",
                                 vec![db.to_string(), key.to_string(), value.to_string()])
    }

    pub fn get_hex(&mut self, db: &str, key: &str) -> String {
        self.rpc_request::<String>("db_getHex",
                                   vec![db.to_string(), key.to_string()])
    }
}

pub fn regression(address: &str) -> bool {
    let mut client = GethRPCClient::new("http://localhost:8545");
    let height = usize::from_str_radix(&client.block_number(), 16).unwrap();
    println!("height: {}", height);

    for blk_no in 49439..height {
        let block = client.get_block_by_number(format!("0x{:x}", blk_no).as_str());
        println!("{:?}", block);
    }
    false
}
<commit_msg>Problem: RPC is slow<commit_after>extern crate serde;
extern crate serde_json;
extern crate hyper;

#[macro_use]
extern crate serde_derive;

use std::process::{Command};
use std::io::Read;
use hyper::header::ContentType;
use hyper::client::Client;
use serde_json::Value;

#[derive(Serialize, Deserialize)]
struct RPCRequest {
    jsonrpc: String,
    method: String,
    params: Vec<String>,
    id: usize,
}

#[derive(Serialize, Deserialize)]
struct RPCObjectRequest<T> {
    jsonrpc: String,
    method: String,
    params: T,
    id: usize,
}

#[derive(Serialize, Deserialize)]
struct RPCObjectResponse<T> {
    jsonrpc: String,
    result: T,
    id: usize,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCTransaction {
    pub hash: String,
    pub nonce: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub transactionIndex: String,
    pub from: String,
    pub to: String,
    pub value: String,
    pub gas: String,
    pub gasPrice: String,
    pub input: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCCall {
    pub from: String,
    pub to: String,
    pub gas: String,
    pub gasPrice: String,
    pub value: String,
    pub data: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCBlock {
    pub number: String,
    pub hash: String,
    pub parentHash: String,
    pub nonce: String,
    pub sha3Uncles: String,
    pub logsBloom: String,
    pub transactionsRoot: String,
    pub stateRoot: String,
    pub miner: String,
    pub difficulty: String,
    pub totalDifficulty: String,
    pub extraData: String,
    pub size: String,
    pub gasLimit: String,
    pub gasUsed: String,
    pub timestamp: String,
    pub transactions: Vec<String>,
    pub uncles: Vec<String>
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum RPCSyncStatus {
    NotSync(bool),
    Sync {
        startingBlock: String,
        currentBlock: String,
        highestBlock: String,
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCTransactionReceipt {
    pub transactionHash: String,
    pub transactionIndex: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub cumulativeGasUsed: String,
    pub gasUsed: String,
    pub contractAddress: String,
    pub logs: Vec<RPCLog>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCLog {
    pub removed: bool,
    pub logIndex: String,
    pub transactionIndex: String,
    pub transactionHash: String,
    pub blockHash: String,
    pub blockNumber: String,
    pub address: String,
    pub data: String,
    pub topics: Vec<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RPCFilter {
    pub fromBlock: String,
    pub toBlock: String,
    pub address: String,
    pub topics: Vec<String>,
}

pub struct GethRPCClient {
    endpoint: String,
    free_id: usize,
    http: Client,
}

impl GethRPCClient {
    pub fn new(endpoint: &str) -> Self {
        GethRPCClient {
            endpoint: endpoint.to_string(),
            free_id: 1,
            http: Client::new(),
        }
    }

    fn rpc_request<T: serde::Deserialize>(&mut self, method: &str, params: Vec<String>) -> T {
        self.rpc_object_request::<Vec<String>, T>(method, params)
    }

    fn rpc_object_request<Req: serde::Serialize, Res: serde::Deserialize>(&mut self, method: &str, params: Req) -> Res {
        let request = RPCObjectRequest {
            jsonrpc: "2.0".to_string(),
            method: method.to_string(),
            params: params,
            id: self.free_id,
        };
        self.free_id = self.free_id + 1;

        let mut response_raw = self.http.post(&self.endpoint)
            .header(ContentType::json())
            .body(&serde_json::to_string(&request).unwrap())
            .send().unwrap();
        let mut buffer = String::new();
        response_raw.read_to_string(&mut buffer).unwrap();

        let response: RPCObjectResponse<Res> = serde_json::from_str(&buffer).unwrap();
        response.result
    }

    pub fn client_version(&mut self) -> String {
        self.rpc_request::<String>("web3_clientVersion", vec![])
    }

    pub fn net_version(&mut self) -> String {
        self.rpc_request::<String>("net_version", vec![])
    }

    pub fn net_listening(&mut self) -> bool {
        self.rpc_request::<bool>("net_listening", vec![])
    }

    pub fn net_peer_count(&mut self) -> String {
        self.rpc_request::<String>("net_peerCount", vec![])
    }

    pub fn sha3(&mut self, data: &str) -> String {
        self.rpc_request::<String>("web3_sha3", vec![])
    }

    pub fn protocol_version(&mut self) -> String {
        self.rpc_request::<String>("eth_protocolVersion", vec![])
    }

    pub fn syncing(&mut self) -> RPCSyncStatus {
        self.rpc_request::<RPCSyncStatus>("eth_syncing", vec![])
    }

    pub fn coinbase(&mut self) -> String {
        self.rpc_request::<String>("eth_coinbase", vec![])
    }

    pub fn mining(&mut self) -> bool {
        self.rpc_request::<bool>("eth_mining", vec![])
    }

    pub fn hashrate(&mut self) -> String {
        self.rpc_request::<String>("eth_hashrate", vec![])
    }

    pub fn gas_price(&mut self) -> String {
        self.rpc_request::<String>("eth_gasPrice", vec![])
    }

    pub fn accounts(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_accounts", vec![])
    }

    pub fn block_number(&mut self) -> String {
        self.rpc_request::<String>("eth_blockNumber", vec![])
    }

    pub fn get_balance(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getBalance",
                                   vec![address.to_string(), number.to_string()])
    }

    pub fn get_storage_at(&mut self, address: &str, index: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getStorageAt",
                                   vec![address.to_string(), index.to_string(), number.to_string()])
    }

    pub fn get_transaction_count(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getTransactionCount",
                                   vec![address.to_string(), number.to_string()])
    }

    pub fn get_block_transaction_count_by_hash(&mut self, hash: &str) -> String {
        self.rpc_request::<String>("eth_getBlockTransactionCountByHash",
                                   vec![hash.to_string()])
    }

    pub fn get_block_transaction_count_by_number(&mut self, number: &str) -> String {
        self.rpc_request::<String>("eth_getBlockTransactionCountByNumber",
                                   vec![number.to_string()])
    }

    pub fn get_uncle_count_by_block_hash(&mut self, hash: &str) -> String {
        self.rpc_request::<String>("eth_getUncleCountByBlockHash",
                                   vec![hash.to_string()])
    }

    pub fn get_uncle_count_by_block_number(&mut self, number: &str) -> String {
        self.rpc_request::<String>("eth_getUncleCountByBlockNumber",
                                   vec![number.to_string()])
    }

    pub fn get_code(&mut self, address: &str, number: &str) -> String {
        self.rpc_request::<String>("eth_getCode", vec![address.to_string(), number.to_string()])
    }

    pub fn sign(&mut self, address: &str, message: &str) -> String {
        self.rpc_request::<String>("eth_sign", vec![address.to_string(), message.to_string()])
    }

    pub fn send_transaction(&mut self, transaction: RPCTransaction) -> String {
        unimplemented!()
    }

    pub fn send_raw_transaction(&mut self, data: &str) -> String {
        self.rpc_request::<String>("eth_sendRawTransaction", vec![data.to_string()])
    }

    pub fn call(&mut self, transaction: RPCCall, number: &str) -> String {
        self.rpc_object_request::<(RPCCall, String), String>("eth_call", (transaction, number.to_string()))
    }

    pub fn estimate_gas(&mut self, transaction: RPCTransaction) -> String {
        unimplemented!()
    }

    pub fn get_block_by_hash(&mut self, hash: &str) -> RPCBlock {
        self.rpc_object_request::<(String, bool), RPCBlock>("eth_getBlockByHash",
                                                            (hash.to_string(), false))
    }

    pub fn get_block_by_number(&mut self, number: &str) -> RPCBlock {
        self.rpc_object_request::<(String, bool), RPCBlock>("eth_getBlockByNumber",
                                                            (number.to_string(), false))
    }

    pub fn get_transaction_by_hash(&mut self, hash: &str) -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByHash",
                                           vec![hash.to_string()])
    }

    pub fn get_transaction_by_block_hash_and_index(&mut self, hash: &str, index: &str) -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByBlockHashAndIndex",
                                           vec![hash.to_string(), index.to_string()])
    }

    pub fn get_transaction_by_block_number_and_index(&mut self, number: &str, index: &str)
                                                 -> RPCTransaction {
        self.rpc_request::<RPCTransaction>("eth_getTransactionByBlockNumberAndIndex",
                                           vec![number.to_string(), index.to_string()])
    }

    pub fn get_transaction_receipt(&mut self, hash: &str) -> RPCTransactionReceipt {
        self.rpc_request::<RPCTransactionReceipt>("eth_getTransactionReceipt",
                                                 vec![hash.to_string()])
    }

    pub fn get_uncle_by_block_hash_and_index(&mut self, hash: &str, index: &str) -> RPCBlock {
        self.rpc_request::<RPCBlock>("eth_getUncleByBlockHashAndIndex",
                                     vec![hash.to_string(), index.to_string()])
    }

    pub fn get_uncle_by_block_number_and_index(&mut self, number: &str, index: &str) -> RPCBlock {
        self.rpc_request::<RPCBlock>("eth_getUncleByBlockNumberAndIndex",
                                     vec![number.to_string(), index.to_string()])
    }

    pub fn get_compilers(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_getCompilers", vec![])
    }

    pub fn compile_solidity(&mut self, source: &str) -> String {
        unimplemented!()
    }

    pub fn compile_lll(&mut self, source: &str) -> String {
        self.rpc_request::<String>("eth_compileLLL", vec![source.to_string()])
    }

    pub fn compile_serpent(&mut self, source: &str) -> String {
        self.rpc_request::<String>("eth_compileSerpent", vec![source.to_string()])
    }

    pub fn new_filter(&mut self, filter: RPCFilter) -> String {
        unimplemented!()
    }

    pub fn new_block_filter(&mut self) -> String {
        self.rpc_request::<String>("eth_newBlockFilter", vec![])
    }

    pub fn new_pending_transaction_filter(&mut self) -> String {
        self.rpc_request::<String>("eth_newPendingTransactionFilter", vec![])
    }

    pub fn uninstall_filter(&mut self, id: &str) -> bool {
        self.rpc_request::<bool>("eth_uninstallFilter", vec![id.to_string()])
    }

    pub fn get_filter_changes(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_filter_logs(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_logs(&mut self, id: &str) -> String {
        unimplemented!()
    }

    pub fn get_work(&mut self) -> Vec<String> {
        self.rpc_request::<Vec<String>>("eth_getWork", vec![])
    }

    pub fn submit_work(&mut self, nonce: &str, pow: &str, mix: &str) -> bool {
        self.rpc_request::<bool>("eth_submitWork",
                                 vec![nonce.to_string(), pow.to_string(), mix.to_string()])
    }

    pub fn submit_hashrate(&mut self, hashrate: &str, id: &str) -> bool {
        self.rpc_request::<bool>("eth_submitHashrate",
                                 vec![hashrate.to_string(), id.to_string()])
    }

    pub fn put_string(&mut self, db: &str, key: &str, value: &str) -> bool {
        self.rpc_request::<bool>("db_putString",
                                 vec![db.to_string(), key.to_string(), value.to_string()])
    }

    pub fn get_string(&mut self, db: &str, key: &str) -> String {
        self.rpc_request::<String>("db_getString",
                                   vec![db.to_string(), key.to_string()])
    }

    pub fn put_hex(&mut self, db: &str, key: &str, value: &str) -> bool {
        self.rpc_request::<bool>("db_putHex",
                                 vec![db.to_string(), key.to_string(), value.to_string()])
    }

    pub fn get_hex(&mut self, db: &str, key: &str) -> String {
        self.rpc_request::<String>("db_getHex",
                                   vec![db.to_string(), key.to_string()])
    }
}

pub fn regression(address: &str) -> bool {
    let mut client = GethRPCClient::new("http://localhost:8545");
    let height = usize::from_str_radix(&client.block_number(), 16).unwrap();
    println!("height: {}", height);

    for blk_no in 49439..height {
        let block = client.get_block_by_number(format!("0x{:x}", blk_no).as_str());
        println!("{:?}", block);
    }
    false
}
<|endoftext|>


<commit_before>// TODO: Implement `libtock_runtime` and `libtock_unittest`, which are
// referenced in the comment on `RawSyscalls`.

/// `RawSyscalls` allows a fake Tock kernel to be injected into components for
/// unit testing. It is implemented by `libtock_runtime::TockSyscalls` and
/// `libtock_unittest::FakeSyscalls`. Components should not use `RawSyscalls`
/// directly; instead, use the `Syscalls` trait, which provides higher-level
/// interfaces to the system calls.

// RawSyscalls is designed to minimize the amount of handwritten assembly code
// needed without generating unnecessary instructions. There are a few major
// factors affecting its design:
//     1. Most system calls only clobber r0-r4 (*), while yield has a far longer
//        clobber list. As such, yield must have its own assembly
//        implementation.
//     2. The compiler is unable to optimize away unused arguments. For example,
//        memop's "get process RAM start address" operation only needs r0 set,
//        while memop's "break" operation needs both r0 and r1 set. If our
//        inline assembly calls "get process RAM start address" but sets both r0
//        and r1, the compiler doesn't know that r1 will be
//        ignored so setting that register will not be optimized away. Therefore
//        we want to set the minimum number of argument registers possible.
//     3. The cost of specifying unused return registers is only that of
//        unnecessarily marking a register as clobbered. Explanation: After
//        inlining, an unused register is marked as "changed by the assembly"
//        but can immediately be re-used by the compiler, which is the same as a
//        clobbered register. System calls should generally be
//        inlined -- and even if they aren't, the unused return values will
//        probably be passed in caller-saved registers (this is true for the C
//        ABI, so probably true for the Rust ABI), which are treated as
//        clobbered regardless.
//
// (*) When this file refers to registers, it uses the same naming convention as
// the Tock 2.0 syscalls TRD. Registers r0-r4 correspond to ARM registers r0-r4
// and RISC-V registers a0-a4.
//
// Currently, yield takes exactly one argument, to specify what yield type to
// do. Therefore we only need one raw yield call.
//
// Subscribe, command, read-write allow, and read-only allow all take four
// argument types. Even when calling command IDs that have unused arguments, we
// still need to clear the argument registers so as to avoid passing
// confidential data to capsules (this is in line with Tock's threat model). As
// such, four_arg_syscall() is used for all subscribe, command, read-only allow,
// and read-write allow system calls.
//
// Memop takes 1 or 2 arguments (operation and an optional argument). Because it
// is part of the core kernel, it is okay for us to leave arbitrary data in the
// argument register for operations where the argument register is unused
// (again, in line with Tock's threat model). Memop returns up to 2 return
// arguments, so we don't need to mark r2 and r3 as clobbered. As such, we need
// two raw memop calls: one for operations without an argument and one for
// operations with an argument.
//
// Because the variables passed in and out of raw system calls represent
// register values, they are of type usize. In cases where it doesn't make sense
// to pass a pointer-sized value, libtock_unittest::FakeSyscalls may panic if a
// too-large value is passed.
pub trait RawSyscalls {
    // raw_yield should:
    //     1. Call syscall class 0
    //     2. Use register r0 for input and output as an inlateout register,
    //        passing in r0_in and returning its value.
    //     3. Mark all caller-saved registers as lateout clobbers.
    //     4. NOT provide any of the following options:
    //            pure             (yield has side effects)
    //            nomem            (a callback can read + write globals)
    //            readonly         (a callback can write globals)
    //            preserves_flags  (a callback can change flags)
    //            noreturn         (yield is expected to return)
    //            nostack          (a callback needs the stack)
    //
    // Design note: This is safe because the yield types that currently exist
    // are safe. If an unsafe yield type is added, we will need to make
    // raw_yield unsafe. Although raw_yield shouldn't be called by code outside
    // this crate, it can be, so that is a backwards-incompatible change. We
    // pass YieldType rather than a usize because if we used usize directly then
    // this API becomes unsound if the kernel adds support for an unsafe yield
    // type (or even one that takes one more argument).
    fn raw_yield(r0_in: YieldType) -> usize;

    // four_arg_syscall is used to invoke the subscribe, command, read-write
    // allow, and read-only allow system calls.
    //
    // four_arg_syscall's inline assembly should have the following properties:
    //     1. Calls the syscall class specified by class
    //     2. Passes r0-r3 in the corresponding registers as inlateout
    //        registers. Returns r0-r3 in order.
    //     3. Does not mark any registers as clobbered.
    //     4. Has all of the following options:
    //            preserves_flags  (these system calls do not touch flags)
    //            nostack          (these system calls do not touch the stack)
    //     5. Does NOT have any of the following options:
    //            pure      (these system calls have side effects)
    //            nomem     (the compiler needs to write to globals before allow)
    //            readonly  (rw allow can modify memory)
    //            noreturn  (all these system calls are expected to return)
    //
    /// # Safety
    /// `four_arg_syscall` must NOT be used to invoke yield. Otherwise, it has
    /// the same safety invariants as the underlying system call, which varies
    /// depending on the system call class.
    unsafe fn four_arg_syscall(
        r0: usize,
        r1: usize,
        r2: usize,
        r3: usize,
        class: u8,
    ) -> (usize, usize, usize, usize);

    // zero_arg_memop is used to invoke memop operations that do not accept an
    // argument register. Because there are no memop commands that set r2 or r3,
    // this only needs to return r0 and r1.
    //
    // Memop commands may panic in the unit test environment, as not all memop
    // calls can be sensibly implemented in that environment.
    //
    // zero_arg_memop's inline assembly should have the following properties:
    //     1. Calls syscall class 5
    //     2. Specifies r0 as an inlateout register, and r1 as a lateout
    //        register.
    //     3. Does not mark any registers as clobbered.
    //     4. Has all of the following options:
    //            preserves_flags
    //            nostack
    //            nomem            (it is okay for the compiler to cache globals
    //                              across memop calls)
    //     5. Does NOT have any of the following options:
    //            pure      (two invocations of the same memop can return
    //                       different values)
    //            readonly  (incompatible with nomem)
    //            noreturn
    //
    // Design note: like raw_yield, this is safe because memops that currently
    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
    // so that if the kernel adds an unsafe memop this API doesn't become
    // unsound.
    fn zero_arg_memop(r0_in: ZeroArgMemop) -> (usize, usize);

    // one_arg_memop is used to invoke memop operations that take an argument.
    // Because there are no memop operations that set r2 or r3, this only needs
    // to return r0 and r1.
    //
    // one_arg_memop's inline assembly should:
    //     1. Call syscall class 5
    //     2. Specify r0 and r1 as inlateout registers, and return (r0, r1)
    //     3. Not mark any registers as clobbered.
    //     4. Have all of the following options:
    //            preserves_flags
    //            nostack
    //            nomem            (the compiler can cache globals across memop
    //                              calls)
    //     5. Does NOT have any of the following options:
    //            pure      Two invocations of sbrk can return different values
    //            readonly  Incompatible with nomem
    //            noreturn
    //
    // Design note: like raw_yield, this is safe because memops that currently
    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
    // so that if the kernel adds an unsafe memop this API doesn't become
    // unsound.
    fn one_arg_memop(r0_in: OneArgMemop, r1: usize) -> (usize, usize);
}

#[non_exhaustive]
#[repr(usize)]
pub enum OneArgMemop {
    Brk = 0,
    Sbrk = 1,
    FlashRegionStart = 8,
    FlashRegionEnd = 9,
    SpecifyStackTop = 10,
    SpecifyHeapStart = 11,
}

// TODO: When the numeric values (0 and 1) are assigned to the yield types,
// specify those values here.
#[non_exhaustive]
#[repr(usize)]
pub enum YieldType {
    Wait,
    NoWait,
}

#[non_exhaustive]
#[repr(usize)]
pub enum ZeroArgMemop {
    MemoryStart = 2,
    MemoryEnd = 3,
    FlashStart = 4,
    FlashEnd = 5,
    GrantStart = 6,
    FlashRegions = 7,
}
<commit_msg>Clarify some of the `memop` comments.<commit_after>// TODO: Implement `libtock_runtime` and `libtock_unittest`, which are
// referenced in the comment on `RawSyscalls`.

/// `RawSyscalls` allows a fake Tock kernel to be injected into components for
/// unit testing. It is implemented by `libtock_runtime::TockSyscalls` and
/// `libtock_unittest::FakeSyscalls`. Components should not use `RawSyscalls`
/// directly; instead, use the `Syscalls` trait, which provides higher-level
/// interfaces to the system calls.

// RawSyscalls is designed to minimize the amount of handwritten assembly code
// needed without generating unnecessary instructions. There are a few major
// factors affecting its design:
//     1. Most system calls only clobber r0-r4 (*), while yield has a far longer
//        clobber list. As such, yield must have its own assembly
//        implementation.
//     2. The compiler is unable to optimize away unused arguments. For example,
//        memop's "get process RAM start address" operation only needs r0 set,
//        while memop's "break" operation needs both r0 and r1 set. If our
//        inline assembly calls "get process RAM start address" but sets both r0
//        and r1, the compiler doesn't know that r1 will be
//        ignored so setting that register will not be optimized away. Therefore
//        we want to set the minimum number of argument registers possible.
//     3. The cost of specifying unused return registers is only that of
//        unnecessarily marking a register as clobbered. Explanation: After
//        inlining, an unused register is marked as "changed by the assembly"
//        but can immediately be re-used by the compiler, which is the same as a
//        clobbered register. System calls should generally be
//        inlined -- and even if they aren't, the unused return values will
//        probably be passed in caller-saved registers (this is true for the C
//        ABI, so probably true for the Rust ABI), which are treated as
//        clobbered regardless.
//
// (*) When this file refers to registers, it uses the same naming convention as
// the Tock 2.0 syscalls TRD. Registers r0-r4 correspond to ARM registers r0-r4
// and RISC-V registers a0-a4.
//
// Currently, yield takes exactly one argument, to specify what yield type to
// do. Therefore we only need one raw yield call.
//
// Subscribe, command, read-write allow, and read-only allow all take four
// argument types. Even when calling command IDs that have unused arguments, we
// still need to clear the argument registers so as to avoid passing
// confidential data to capsules (this is in line with Tock's threat model). As
// such, four_arg_syscall() is used for all subscribe, command, read-only allow,
// and read-write allow system calls.
//
// Memop takes 1 or 2 arguments (operation and an optional argument). Because it
// is part of the core kernel, it is okay for us to leave arbitrary data in the
// argument register for operations where the argument register is unused
// (again, in line with Tock's threat model). As such, for efficiency, we need
// two raw memop calls: one for operations without an argument and one for
// operations with an argument.
//
// The success type for Memop calls depends on the operation perform. However,
// all *currently defined* memop operations return either Success or Success
// with u32. Therefore, the memop implementations only need to mark r0 and r1 as
// clobbered, not r2 and r3. This choice of clobbers will need to be revisited
// if and when a memop operation that returns more data is added.
//
// Because the variables passed in and out of raw system calls represent
// register values, they are of type usize. In cases where it doesn't make sense
// to pass a pointer-sized value, libtock_unittest::FakeSyscalls may panic if a
// too-large value is passed.
pub trait RawSyscalls {
    // raw_yield should:
    //     1. Call syscall class 0
    //     2. Use register r0 for input and output as an inlateout register,
    //        passing in r0_in and returning its value.
    //     3. Mark all caller-saved registers as lateout clobbers.
    //     4. NOT provide any of the following options:
    //            pure             (yield has side effects)
    //            nomem            (a callback can read + write globals)
    //            readonly         (a callback can write globals)
    //            preserves_flags  (a callback can change flags)
    //            noreturn         (yield is expected to return)
    //            nostack          (a callback needs the stack)
    //
    // Design note: This is safe because the yield types that currently exist
    // are safe. If an unsafe yield type is added, we will need to make
    // raw_yield unsafe. Although raw_yield shouldn't be called by code outside
    // this crate, it can be, so that is a backwards-incompatible change. We
    // pass YieldType rather than a usize because if we used usize directly then
    // this API becomes unsound if the kernel adds support for an unsafe yield
    // type (or even one that takes one more argument).
    fn raw_yield(r0_in: YieldType) -> usize;

    // four_arg_syscall is used to invoke the subscribe, command, read-write
    // allow, and read-only allow system calls.
    //
    // four_arg_syscall's inline assembly should have the following properties:
    //     1. Calls the syscall class specified by class
    //     2. Passes r0-r3 in the corresponding registers as inlateout
    //        registers. Returns r0-r3 in order.
    //     3. Does not mark any registers as clobbered.
    //     4. Has all of the following options:
    //            preserves_flags  (these system calls do not touch flags)
    //            nostack          (these system calls do not touch the stack)
    //     5. Does NOT have any of the following options:
    //            pure      (these system calls have side effects)
    //            nomem     (the compiler needs to write to globals before allow)
    //            readonly  (rw allow can modify memory)
    //            noreturn  (all these system calls are expected to return)
    //
    /// # Safety
    /// `four_arg_syscall` must NOT be used to invoke yield. Otherwise, it has
    /// the same safety invariants as the underlying system call, which varies
    /// depending on the system call class.
    unsafe fn four_arg_syscall(
        r0: usize,
        r1: usize,
        r2: usize,
        r3: usize,
        class: u8,
    ) -> (usize, usize, usize, usize);

    // zero_arg_memop is used to invoke memop operations that do not accept an
    // argument register. Because there are no memop commands that set r2 or r3,
    // this only needs to return r0 and r1.
    //
    // Memop commands may panic in the unit test environment, as not all memop
    // calls can be sensibly implemented in that environment.
    //
    // zero_arg_memop's inline assembly should have the following properties:
    //     1. Calls syscall class 5
    //     2. Specifies r0 as an inlateout register, and r1 as a lateout
    //        register.
    //     3. Does not mark any registers as clobbered.
    //     4. Has all of the following options:
    //            preserves_flags
    //            nostack
    //            nomem            (it is okay for the compiler to cache globals
    //                              across memop calls)
    //     5. Does NOT have any of the following options:
    //            pure      (two invocations of the same memop can return
    //                       different values)
    //            readonly  (incompatible with nomem)
    //            noreturn
    //
    // Design note: like raw_yield, this is safe because memops that currently
    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
    // so that if the kernel adds an unsafe memop -- or one that can clobber
    // r2/r3 --  this API doesn't become unsound.
    fn zero_arg_memop(r0_in: ZeroArgMemop) -> (usize, usize);

    // one_arg_memop is used to invoke memop operations that take an argument.
    // Because there are no memop operations that set r2 or r3, this only needs
    // to return r0 and r1.
    //
    // one_arg_memop's inline assembly should:
    //     1. Call syscall class 5
    //     2. Specify r0 and r1 as inlateout registers, and return (r0, r1)
    //     3. Not mark any registers as clobbered.
    //     4. Have all of the following options:
    //            preserves_flags
    //            nostack
    //            nomem            (the compiler can cache globals across memop
    //                              calls)
    //     5. Does NOT have any of the following options:
    //            pure      Two invocations of sbrk can return different values
    //            readonly  Incompatible with nomem
    //            noreturn
    //
    // Design note: like raw_yield, this is safe because memops that currently
    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
    // so that if the kernel adds an unsafe memop -- or one that can clobber
    // r2/r3 -- this API doesn't become unsound.
    fn one_arg_memop(r0_in: OneArgMemop, r1: usize) -> (usize, usize);
}

#[non_exhaustive]
#[repr(usize)]
pub enum OneArgMemop {
    Brk = 0,
    Sbrk = 1,
    FlashRegionStart = 8,
    FlashRegionEnd = 9,
    SpecifyStackTop = 10,
    SpecifyHeapStart = 11,
    // Note: before adding new memop operations, make sure the assumptions in
    // the design notes on `one_arg_memop` are valid for the new operation type.
}

// TODO: When the numeric values (0 and 1) are assigned to the yield types,
// specify those values here.
#[non_exhaustive]
#[repr(usize)]
pub enum YieldType {
    Wait,
    NoWait,
}

#[non_exhaustive]
#[repr(usize)]
pub enum ZeroArgMemop {
    MemoryStart = 2,
    MemoryEnd = 3,
    FlashStart = 4,
    FlashEnd = 5,
    GrantStart = 6,
    FlashRegions = 7,
    // Note: before adding new memop operations, make sure the assumptions in
    // the design notes on `zero_arg_memop` are valid for the new operation
    // type.
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use error::Result;

// We can probably pull this from Win32_OperatingSystem
#[derive(Debug)]
pub struct Uname {
    pub sys_name: String, // static - Windows
    pub node_name: String, // __SERVER
    pub release: String, // Version
    pub version: String, // Caption
    pub machine: String, // OSArchitecture - but converted to standard x86_64 or i386
}

pub fn uname() -> Result<Uname> {
    Ok(Uname{
        sys_name: String::from("Windows"),
        node_name: String::from("CHEF-WIN10"),
        release: String::from("10.0.14915"),
        version: String::from("Microsoft Windows 10 Enterprise Insider Preview"),
        machine: String::from("x86_64"),
    })
}
<commit_msg>fix cargo fmt error<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use error::Result;

// We can probably pull this from Win32_OperatingSystem
#[derive(Debug)]
pub struct Uname {
    pub sys_name: String, // static - Windows
    pub node_name: String, // __SERVER
    pub release: String, // Version
    pub version: String, // Caption
    pub machine: String, // OSArchitecture - but converted to standard x86_64 or i386
}

pub fn uname() -> Result<Uname> {
    Ok(Uname {
        sys_name: String::from("Windows"),
        node_name: String::from("CHEF-WIN10"),
        release: String::from("10.0.14915"),
        version: String::from("Microsoft Windows 10 Enterprise Insider Preview"),
        machine: String::from("x86_64"),
    })
}
<|endoftext|>