<commit_before>extern crate rusttype;
use rusttype::*;
fn main() {
    use std::io::Write;
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font
    {
        let height: f32 = 20.1; // to get 80 chars across (fits most terminals); adjust as desired
        let pixel_height = height.ceil() as usize;
        // 2x scale in x direction to counter the aspect ratio of monospace characters.
        let scale = PixelsXY(height*2.0, height);
        let v_metrics = font.v_metrics(scale);
        let offset = point(0.0, v_metrics.ascent);
        let to_draw: Vec<_> = font.layout("Hello!", scale, offset).collect();
        // Finds the most visually pleasing width to display
        let width = to_draw.iter().map(|g| g.h_metrics().advance_width)
            .fold(0.0, |x, y| x + y).ceil() as usize;
        println!("width: {}, height: {}", width, pixel_height);
        // Rasterise directly into ASCII art.
        let mut data = vec![b'@'; width * pixel_height];
        let mapping = b"@%#x+=:-. "; // The approximation of greyscale
        let mapping_scale = (mapping.len()-1) as f32;
        for g in to_draw {
            if let Some(bb) = g.pixel_bounding_box() {
                g.draw(|x, y, v| {
                    let i = (v*mapping_scale + 0.5) as usize;
                    // Something's wrong if you get $ in the output.
                    let c = mapping.get(i).cloned().unwrap_or(b'$');
                    let x = (x as i32 + bb.min.x) as usize;
                    let y = (y as i32 + bb.min.y) as usize;
                    data[(x + y * width)] = c;
                })
            }
        }
        // Print it out
        let stdout = ::std::io::stdout();
        let mut handle = stdout.lock();
        for j in 0..pixel_height {
            handle.write(&data[j*width..(j+1)*width]).unwrap();
            handle.write(b"\n").unwrap();
        }
    }
}
<commit_msg>Tidied up the example<commit_after>extern crate rusttype;

use rusttype::{FontCollection, PixelsXY, point};
use std::io::Write;

fn main() {
    let font_data = include_bytes!("Gudea-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap(); // only succeeds if collection consists of one font
    {
        // Desired font pixel height
        let height: f32 = 20.1; // to get 80 chars across (fits most terminals); adjust as desired
        let pixel_height = height.ceil() as usize;

        // 2x scale in x direction to counter the aspect ratio of monospace characters.
        let scale = PixelsXY(height*2.0, height);

        let v_metrics = font.v_metrics(scale);
        let offset = point(0.0, v_metrics.ascent);

        // Glyphs to draw for "Hello!". Feel free to try other strings.
        let to_draw: Vec<_> = font.layout("Hello!", scale, offset).collect();

        // Find the most visually pleasing width to display
        let width = to_draw.iter().map(|g| g.h_metrics().advance_width)
            .fold(0.0, |x, y| x + y).ceil() as usize;

        println!("width: {}, height: {}", width, pixel_height);

        // Rasterise directly into ASCII art.
        let mut pixel_data = vec![b'@'; width * pixel_height];
        let mapping = b"@%#x+=:-. "; // The approximation of greyscale
        let mapping_scale = (mapping.len()-1) as f32;
        for g in to_draw {
            if let Some(bb) = g.pixel_bounding_box() {
                g.draw(|x, y, v| {
                    // v should be in the range 0.0 to 1.0
                    let i = (v*mapping_scale + 0.5) as usize;
                    // so something's wrong if you get $ in the output.
                    let c = mapping.get(i).cloned().unwrap_or(b'$');
                    let x = (x as i32 + bb.min.x) as usize;
                    let y = (y as i32 + bb.min.y) as usize;
                    pixel_data[(x + y * width)] = c;
                })
            }
        }

        // Print it out
        let stdout = ::std::io::stdout();
        let mut handle = stdout.lock();
        for j in 0..pixel_height {
            handle.write(&pixel_data[j*width..(j+1)*width]).unwrap();
            handle.write(b"\n").unwrap();
        }
    }
}
<|endoftext|>


<commit_before>//! Acceleration (base unit meter per second squared, m · s⁻²).

quantity! {
    /// Acceleration (base unit meter per second squared, m · s⁻²).
    quantity: Acceleration; "acceleration";
    /// Dimension of acceleration, LT⁻² (base unit meter per second squared, m · s⁻²).
    dimension: ISQ<
        P1,     // length
        Z0,     // mass
        N2,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottameter_per_second_squared: prefix!(yotta); "Ym/s²", "yottameter per second squared",
            "yottameters per second squared";
        @zettameter_per_second_squared: prefix!(zetta); "Zm/s²", "zettameter per second squared",
            "zettameters per second squared";
        @exameter_per_second_squared: prefix!(exa); "Em/s²", "exameter per second squared",
            "exameters per second squared";
        @petameter_per_second_squared: prefix!(peta); "Pm/s²", "petameter per second squared",
            "petameters per second squared";
        @terameter_per_second_squared: prefix!(tera); "Tm/s²", "terameter per second squared",
            "terameters per second squared";
        @gigameter_per_second_squared: prefix!(giga); "Gm/s²", "gigameter per second squared",
            "gigameters per second squared";
        @megameter_per_second_squared: prefix!(mega); "Mm/s²", "megameter per second squared",
            "megameters per second squared";
        @kilometer_per_second_squared: prefix!(kilo); "km/s²", "kilometer per second squared",
            "kilometers per second squared";
        @hectometer_per_second_squared: prefix!(hecto); "hm/s²", "hectometer per second squared",
            "hectometers per second squared";
        @decameter_per_second_squared: prefix!(deca); "dam/s²", "decameter per second squared",
            "decameters per second squared";
        @meter_per_second_squared: prefix!(none); "m/s²", "meter per second squared",
            "meters per second squared";
        @decimeter_per_second_squared: prefix!(deci); "dm/s²", "decimeter per second squared",
            "decimeters per second squared";
        @centimeter_per_second_squared: prefix!(centi); "cm/s²", "centimeter per second squared",
            "centimeters per second squared";
        @millimeter_per_second_squared: prefix!(milli); "mm/s²", "millimeter per second squared",
            "millimeters per second squared";
        @micrometer_per_second_squared: prefix!(micro); "µm/s²", "micrometer per second squared",
            "micrometers per second squared";
        @nanometer_per_second_squared: prefix!(nano); "nm/s²", "nanometer per second squared",
            "nanometers per second squared";
        @picometer_per_second_squared: prefix!(pico); "pm/s²", "picometer per second squared",
            "picometers per second squared";
        @femtometer_per_second_squared: prefix!(femto); "fm/s²", "femtometer per second squared",
            "femtometers per second squared";
        @attometer_per_second_squared: prefix!(atto); "am/s²", "attometer per second squared",
            "attometers per second squared";
        @zeptometer_per_second_squared: prefix!(zepto); "zm/s²", "zeptometer per second squared",
            "zeptometers per second squared";
        @yoctometer_per_second_squared: prefix!(yocto); "ym/s²", "yoctometer per second squared",
            "yoctometers per second squared";

        @foot_per_second_squared: 3.048_E-1; "ft/s²", "foot per second squared",
            "feet per second squared";
        @galileo: 1.0_E-2; "Gal", "galileo", "galileos";
        @inch_per_second_squared: 2.54_E-2; "in/s²", "inch per second squared",
            "inches per second squared";
        @millimeter_per_minute_squared: 2.777_777_777_777_777_8_E-7; "mm/min²",
            "millimeter per minute squared", "millimeters per minute squared";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use crate::si::acceleration as a;
        use crate::si::length as l;
        use crate::si::quantities::*;
        use crate::si::time as t;
        use crate::tests::Test;
        use crate::num::One;

        #[test]
        fn check_dimension() {
            let _: Acceleration<V> = Length::new::<l::meter>(V::one()) /
                (Time::new::<t::second>(V::one()) * Time::new::<t::second>(V::one()));
        }

        #[test]
        fn check_units() {
            test::<l::yottameter, t::second, a::yottameter_per_second_squared>();
            test::<l::zettameter, t::second, a::zettameter_per_second_squared>();
            test::<l::exameter, t::second, a::exameter_per_second_squared>();
            test::<l::petameter, t::second, a::petameter_per_second_squared>();
            test::<l::terameter, t::second, a::terameter_per_second_squared>();
            test::<l::gigameter, t::second, a::gigameter_per_second_squared>();
            test::<l::megameter, t::second, a::megameter_per_second_squared>();
            test::<l::kilometer, t::second, a::kilometer_per_second_squared>();
            test::<l::hectometer, t::second, a::hectometer_per_second_squared>();
            test::<l::decameter, t::second, a::decameter_per_second_squared>();
            test::<l::meter, t::second, a::meter_per_second_squared>();
            test::<l::decimeter, t::second, a::decimeter_per_second_squared>();
            test::<l::centimeter, t::second, a::centimeter_per_second_squared>();
            test::<l::millimeter, t::second, a::millimeter_per_second_squared>();
            test::<l::micrometer, t::second, a::micrometer_per_second_squared>();
            test::<l::nanometer, t::second, a::nanometer_per_second_squared>();
            test::<l::picometer, t::second, a::picometer_per_second_squared>();
            test::<l::femtometer, t::second, a::femtometer_per_second_squared>();
            test::<l::attometer, t::second, a::attometer_per_second_squared>();
            test::<l::zeptometer, t::second, a::zeptometer_per_second_squared>();
            test::<l::yoctometer, t::second, a::yoctometer_per_second_squared>();

            test::<l::foot, t::second, a::foot_per_second_squared>();
            test::<l::centimeter, t::second, a::galileo>();
            test::<l::inch, t::second, a::inch_per_second_squared>();
            test::<l::millimeter, t::minute, a::millimeter_per_minute_squared>();

            fn test<L: l::Conversion<V>, T: t::Conversion<V>, A: a::Conversion<V>>() {
                Test::assert_eq(&Acceleration::new::<A>(V::one()),
                    &(Length::new::<L>(V::one()) /
                        (Time::new::<T>(V::one()) * Time::new::<T>(V::one()))));
            }
        }
    }
}
<commit_msg>Add standard_gravity as a unit of acceleration.<commit_after>//! Acceleration (base unit meter per second squared, m · s⁻²).

quantity! {
    /// Acceleration (base unit meter per second squared, m · s⁻²).
    quantity: Acceleration; "acceleration";
    /// Dimension of acceleration, LT⁻² (base unit meter per second squared, m · s⁻²).
    dimension: ISQ<
        P1,     // length
        Z0,     // mass
        N2,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottameter_per_second_squared: prefix!(yotta); "Ym/s²", "yottameter per second squared",
            "yottameters per second squared";
        @zettameter_per_second_squared: prefix!(zetta); "Zm/s²", "zettameter per second squared",
            "zettameters per second squared";
        @exameter_per_second_squared: prefix!(exa); "Em/s²", "exameter per second squared",
            "exameters per second squared";
        @petameter_per_second_squared: prefix!(peta); "Pm/s²", "petameter per second squared",
            "petameters per second squared";
        @terameter_per_second_squared: prefix!(tera); "Tm/s²", "terameter per second squared",
            "terameters per second squared";
        @gigameter_per_second_squared: prefix!(giga); "Gm/s²", "gigameter per second squared",
            "gigameters per second squared";
        @megameter_per_second_squared: prefix!(mega); "Mm/s²", "megameter per second squared",
            "megameters per second squared";
        @kilometer_per_second_squared: prefix!(kilo); "km/s²", "kilometer per second squared",
            "kilometers per second squared";
        @hectometer_per_second_squared: prefix!(hecto); "hm/s²", "hectometer per second squared",
            "hectometers per second squared";
        @decameter_per_second_squared: prefix!(deca); "dam/s²", "decameter per second squared",
            "decameters per second squared";
        @meter_per_second_squared: prefix!(none); "m/s²", "meter per second squared",
            "meters per second squared";
        @decimeter_per_second_squared: prefix!(deci); "dm/s²", "decimeter per second squared",
            "decimeters per second squared";
        @centimeter_per_second_squared: prefix!(centi); "cm/s²", "centimeter per second squared",
            "centimeters per second squared";
        @millimeter_per_second_squared: prefix!(milli); "mm/s²", "millimeter per second squared",
            "millimeters per second squared";
        @micrometer_per_second_squared: prefix!(micro); "µm/s²", "micrometer per second squared",
            "micrometers per second squared";
        @nanometer_per_second_squared: prefix!(nano); "nm/s²", "nanometer per second squared",
            "nanometers per second squared";
        @picometer_per_second_squared: prefix!(pico); "pm/s²", "picometer per second squared",
            "picometers per second squared";
        @femtometer_per_second_squared: prefix!(femto); "fm/s²", "femtometer per second squared",
            "femtometers per second squared";
        @attometer_per_second_squared: prefix!(atto); "am/s²", "attometer per second squared",
            "attometers per second squared";
        @zeptometer_per_second_squared: prefix!(zepto); "zm/s²", "zeptometer per second squared",
            "zeptometers per second squared";
        @yoctometer_per_second_squared: prefix!(yocto); "ym/s²", "yoctometer per second squared",
            "yoctometers per second squared";

        @foot_per_second_squared: 3.048_E-1; "ft/s²", "foot per second squared",
            "feet per second squared";
        @galileo: 1.0_E-2; "Gal", "galileo", "galileos";
        @inch_per_second_squared: 2.54_E-2; "in/s²", "inch per second squared",
            "inches per second squared";
        @millimeter_per_minute_squared: 2.777_777_777_777_777_8_E-7; "mm/min²",
            "millimeter per minute squared", "millimeters per minute squared";
        @standard_gravity: 9.806_65_E0; "g₀", "standard acceleration of gravity",
            "standard accelerations of gravity";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use crate::si::acceleration as a;
        use crate::si::length as l;
        use crate::si::quantities::*;
        use crate::si::time as t;
        use crate::tests::Test;
        use crate::num::One;

        #[test]
        fn check_dimension() {
            let _: Acceleration<V> = Length::new::<l::meter>(V::one()) /
                (Time::new::<t::second>(V::one()) * Time::new::<t::second>(V::one()));
        }

        #[test]
        fn check_units() {
            test::<l::yottameter, t::second, a::yottameter_per_second_squared>();
            test::<l::zettameter, t::second, a::zettameter_per_second_squared>();
            test::<l::exameter, t::second, a::exameter_per_second_squared>();
            test::<l::petameter, t::second, a::petameter_per_second_squared>();
            test::<l::terameter, t::second, a::terameter_per_second_squared>();
            test::<l::gigameter, t::second, a::gigameter_per_second_squared>();
            test::<l::megameter, t::second, a::megameter_per_second_squared>();
            test::<l::kilometer, t::second, a::kilometer_per_second_squared>();
            test::<l::hectometer, t::second, a::hectometer_per_second_squared>();
            test::<l::decameter, t::second, a::decameter_per_second_squared>();
            test::<l::meter, t::second, a::meter_per_second_squared>();
            test::<l::decimeter, t::second, a::decimeter_per_second_squared>();
            test::<l::centimeter, t::second, a::centimeter_per_second_squared>();
            test::<l::millimeter, t::second, a::millimeter_per_second_squared>();
            test::<l::micrometer, t::second, a::micrometer_per_second_squared>();
            test::<l::nanometer, t::second, a::nanometer_per_second_squared>();
            test::<l::picometer, t::second, a::picometer_per_second_squared>();
            test::<l::femtometer, t::second, a::femtometer_per_second_squared>();
            test::<l::attometer, t::second, a::attometer_per_second_squared>();
            test::<l::zeptometer, t::second, a::zeptometer_per_second_squared>();
            test::<l::yoctometer, t::second, a::yoctometer_per_second_squared>();

            test::<l::foot, t::second, a::foot_per_second_squared>();
            test::<l::centimeter, t::second, a::galileo>();
            test::<l::inch, t::second, a::inch_per_second_squared>();
            test::<l::millimeter, t::minute, a::millimeter_per_minute_squared>();

            fn test<L: l::Conversion<V>, T: t::Conversion<V>, A: a::Conversion<V>>() {
                Test::assert_eq(&Acceleration::new::<A>(V::one()),
                    &(Length::new::<L>(V::one()) /
                        (Time::new::<T>(V::one()) * Time::new::<T>(V::one()))));
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate touchpage;

use failure::err_msg;
use failure::Error as FError;
use serde_json::Value;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use touchpage::control_nexus::PrintUpdateMsg;
use touchpage::controls;
use touchpage::controls::Orientation::{Horizontal, Vertical};
use touchpage::guibuilder as G;
use touchpage::json as J;
use touchpage::webserver::startwebserver;
use touchpage::websocketserver::startserver;

fn main() {
  // println!("Hello, world!");

  let meh = PrintUpdateMsg {};

  let mbhtml = match load_string("index.html") {
    Ok(html) => Some(html),
    _ => None,
  };

  let rootv: Result<String, FError> = build_gui()
    .and_then(|gui| gui.to_root())
    .map(|root| J::serialize_root(&root))
    .and_then(|rootv| serde_json::to_string_pretty(&rootv).map_err(|_| err_msg("uh oh")));
    // .and_then(|st| write_string(st.as_str(), "json.out"));

  let gooey = match rootv {
    Ok(s) => s,
    Err(e) => {
      println!("error loading controls! {}", e);
      GUI.to_string()
      },
  };

  match startserver(gooey.as_str(), Box::new(meh), "localhost", "9001", false) {
    Ok(_) => (),
    Err(e) => println!("error starting websocket server: {},", e),
  }
  startwebserver("localhost", "8000", "9001", mbhtml, true);
}

fn build_gui() -> Result<G::Gui, FError> {
  let mut gui = G::Gui::new_gui("test".to_string());
  gui
    .add_sizer(Vertical)?
    .add_label("lb3".to_string(), "blah".to_string())?
    .add_label("lb0".to_string(), "blah1".to_string())?
    .add_label("lb1".to_string(), "blah2".to_string())?
    .add_label("lb2".to_string(), "blah4444".to_string())?
    .add_sizer(Horizontal)?
    .add_button("b1".to_string(), None)?
    .add_slider("hs1".to_string(), None, Horizontal)?
    .add_slider("hs2".to_string(), None, Horizontal)?
    .add_slider("hs3".to_string(), None, Horizontal)?
    .add_slider("hs4".to_string(), None, Horizontal)?
    .end_sizer()?
    .add_xy("xy".to_string(), Some("xycontrol".to_string()))?
    .end_sizer()?;
  Ok(gui)
}

const GUI: &'static str = r##"
{
  "title": "test",
  "rootControl":
    { "type": "sizer",
      "orientation": "vertical",
      "proportions": [0.1,0.3,0.6],
      "controls": [
       { "type": "label"
       , "name": "lb3"
       , "label": "error loading controls!"
       }
      ]
    }
}"##;

pub fn load_string(file_name: &str) -> Result<String, FError> {
  let path = &Path::new(&file_name);
  let mut inf = File::open(path)?;
  let mut result = String::new();
  inf.read_to_string(&mut result)?;
  Ok(result)
}

pub fn write_string(text: &str, file_name: &str) -> Result<(), FError> {
  let path = &Path::new(&file_name);
  let mut inf = File::create(path)?;
  inf.write(text.as_bytes())?;
  Ok(())
}
<commit_msg>reconfig example for non-local connections<commit_after>extern crate touchpage;

use failure::err_msg;
use failure::Error as FError;
use serde_json::Value;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use touchpage::control_nexus::PrintUpdateMsg;
use touchpage::controls;
use touchpage::controls::Orientation::{Horizontal, Vertical};
use touchpage::guibuilder as G;
use touchpage::json as J;
use touchpage::webserver::startwebserver;
use touchpage::websocketserver::startserver;

fn main() {
  // println!("Hello, world!");

  let meh = PrintUpdateMsg {};

  let mbhtml = match load_string("index.html") {
    Ok(html) => Some(html),
    _ => None,
  };

  let rootv: Result<String, FError> = build_gui()
    .and_then(|gui| gui.to_root())
    .map(|root| J::serialize_root(&root))
    .and_then(|rootv| serde_json::to_string_pretty(&rootv).map_err(|_| err_msg("uh oh")));
    // .and_then(|st| write_string(st.as_str(), "json.out"));

  let gooey = match rootv {
    Ok(s) => s,
    Err(e) => {
      println!("error loading controls! {}", e);
      GUI.to_string()
      },
  };

  match startserver(gooey.as_str(), Box::new(meh), "0.0.0.0", "9001", false) {
    Ok(_) => (),
    Err(e) => println!("error starting websocket server: {},", e),
  }
  startwebserver("0.0.0.0", "8000", "9001", mbhtml, true);
}

fn build_gui() -> Result<G::Gui, FError> {
  let mut gui = G::Gui::new_gui("test".to_string());
  gui
    .add_sizer(Vertical)?
    .add_label("lb3".to_string(), "blah".to_string())?
    .add_label("lb0".to_string(), "blah1".to_string())?
    .add_label("lb1".to_string(), "blah2".to_string())?
    .add_label("lb2".to_string(), "blah4444".to_string())?
    .add_sizer(Horizontal)?
    .add_button("b1".to_string(), None)?
    .add_slider("hs1".to_string(), None, Horizontal)?
    .add_slider("hs2".to_string(), None, Horizontal)?
    .add_slider("hs3".to_string(), None, Horizontal)?
    .add_slider("hs4".to_string(), None, Horizontal)?
    .end_sizer()?
    .add_xy("xy".to_string(), Some("xycontrol".to_string()))?
    .end_sizer()?;
  Ok(gui)
}

const GUI: &'static str = r##"
{
  "title": "test",
  "rootControl":
    { "type": "sizer",
      "orientation": "vertical",
      "proportions": [0.1,0.3,0.6],
      "controls": [
       { "type": "label"
       , "name": "lb3"
       , "label": "error loading controls!"
       }
      ]
    }
}"##;

pub fn load_string(file_name: &str) -> Result<String, FError> {
  let path = &Path::new(&file_name);
  let mut inf = File::open(path)?;
  let mut result = String::new();
  inf.read_to_string(&mut result)?;
  Ok(result)
}

pub fn write_string(text: &str, file_name: &str) -> Result<(), FError> {
  let path = &Path::new(&file_name);
  let mut inf = File::create(path)?;
  inf.write(text.as_bytes())?;
  Ok(())
}
<|endoftext|>


<commit_before>trait Parser<T, E> {
    fn next(&mut self) -> Option<T>;
    fn preview(&self) -> Option<&T>;
    fn current_pos(&self) -> (i32, i32);
    fn error(&self, message: &str) -> E;
}

macro_rules! next {
    ($p:expr) => {
        match $p.next() {
            Some(x) => x,
            None => return Err($p.error("unexpected eof")),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: Vec<i32>) -> TP {
            TP { input: VecDeque::from(input) }
        }
    }

    impl Parser<i32, String> for TP {
        fn next(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error(&self, message: &str) -> String {
            message.to_string()
        }
    }

    macro_rules! with_res {
        (test $i:ident, $b:block) => {
            #[test]
            fn $i() {
                let result = || {
                    $b;
                    Ok(())
                };
                result().unwrap()
            }
        };
        (panic $e:expr, $i:ident, $b:block) => {
            #[test]
            #[should_panic(expected = $e)]
            fn $i() {
                let result = || {
                    $b;
                    Ok(())
                };
                result().unwrap()
            }
        };
    }

    with_res!(test next_success, {
        let mut p = TP::new(vec![1, 2, 3]);
        assert_eq!(next!(p), 1);
        assert_eq!(next!(p), 2);
        assert_eq!(next!(p), 3);
    });

    with_res!(panic "unexpected eof", next_fail_empty, {
        let mut p = TP::new(vec![]);
        assert_eq!(next!(p), 1);
    });
}
<commit_msg>Use slice as TP::new()'s input type<commit_after>trait Parser<T, E> {
    fn next(&mut self) -> Option<T>;
    fn preview(&self) -> Option<&T>;
    fn current_pos(&self) -> (i32, i32);
    fn error(&self, message: &str) -> E;
}

macro_rules! next {
    ($p:expr) => {
        match $p.next() {
            Some(x) => x,
            None => return Err($p.error("unexpected eof")),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn next(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error(&self, message: &str) -> String {
            message.to_string()
        }
    }

    macro_rules! with_res {
        (test $i:ident, $b:block) => {
            #[test]
            fn $i() {
                let result = || {
                    $b;
                    Ok(())
                };
                result().unwrap()
            }
        };
        (panic $e:expr, $i:ident, $b:block) => {
            #[test]
            #[should_panic(expected = $e)]
            fn $i() {
                let result = || {
                    $b;
                    Ok(())
                };
                result().unwrap()
            }
        };
    }

    with_res!(test next_success, {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(next!(p), 1);
        assert_eq!(next!(p), 2);
        assert_eq!(next!(p), 3);
    });

    with_res!(panic "unexpected eof", next_fail_empty, {
        let mut p = TP::new(&[]);
        assert_eq!(next!(p), 1);
    });
}
<|endoftext|>


<commit_before>use cfg_if::cfg_if;
use std::time::Instant;

/// Trait for the platform thread parker implementation.
///
/// All unsafe methods are unsafe because the Unix thread parker is based on
/// pthread mutexes and condvars. Those primitives must not be moved and used
/// from any other memory address than the one they were located at when they
/// were initialized. As such, it's UB to call any unsafe method on
/// `ThreadParkerT` if the implementing instance has moved since the last
/// call to any of the unsafe methods.
pub trait ThreadParkerT {
    type UnparkHandle: UnparkHandleT;

    const IS_CHEAP_TO_CONSTRUCT: bool;

    fn new() -> Self;

    /// Prepares the parker. This should be called before adding it to the queue.
    unsafe fn prepare_park(&self);

    /// Checks if the park timed out. This should be called while holding the
    /// queue lock after park_until has returned false.
    unsafe fn timed_out(&self) -> bool;

    /// Parks the thread until it is unparked. This should be called after it has
    /// been added to the queue, after unlocking the queue.
    unsafe fn park(&self);

    /// Parks the thread until it is unparked or the timeout is reached. This
    /// should be called after it has been added to the queue, after unlocking
    /// the queue. Returns true if we were unparked and false if we timed out.
    unsafe fn park_until(&self, timeout: Instant) -> bool;

    /// Locks the parker to prevent the target thread from exiting. This is
    /// necessary to ensure that thread-local ThreadData objects remain valid.
    /// This should be called while holding the queue lock.
    unsafe fn unpark_lock(&self) -> Self::UnparkHandle;
}

/// Handle for a thread that is about to be unparked. We need to mark the thread
/// as unparked while holding the queue lock, but we delay the actual unparking
/// until after the queue lock is released.
pub trait UnparkHandleT {
    /// Wakes up the parked thread. This should be called after the queue lock is
    /// released to avoid blocking the queue for too long.
    ///
    /// This method is unsafe for the same reason as the unsafe methods in
    /// `ThreadParkerT`.
    #[inline]
    unsafe fn unpark(self);
}

cfg_if! {
    if #[cfg(all(has_sized_atomics, any(target_os = "linux", target_os = "android")))] {
        #[path = "linux.rs"]
        mod imp;
    } else if #[cfg(unix)] {
        #[path = "unix.rs"]
        mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows/mod.rs"]
        mod imp;
    } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] {
        #[path = "redox.rs"]
        mod imp;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        #[path = "sgx.rs"]
        mod imp;
    } else if #[cfg(all(
        feature = "nightly",
        target_arch = "wasm32",
        target_feature = "atomics"
    ))] {
        #[path = "wasm_atomic.rs"]
        mod imp;
    } else if #[cfg(target_arch = "wasm32")] {
        #[path = "wasm.rs"]
        mod imp;
    } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] {
        #[path = "cloudabi.rs"]
        mod imp;
    } else {
        #[path = "generic.rs"]
        mod imp;
    }
}

pub use self::imp::{thread_yield, ThreadParker, UnparkHandle};
<commit_msg>Remove #[inline] on function with no body<commit_after>use cfg_if::cfg_if;
use std::time::Instant;

/// Trait for the platform thread parker implementation.
///
/// All unsafe methods are unsafe because the Unix thread parker is based on
/// pthread mutexes and condvars. Those primitives must not be moved and used
/// from any other memory address than the one they were located at when they
/// were initialized. As such, it's UB to call any unsafe method on
/// `ThreadParkerT` if the implementing instance has moved since the last
/// call to any of the unsafe methods.
pub trait ThreadParkerT {
    type UnparkHandle: UnparkHandleT;

    const IS_CHEAP_TO_CONSTRUCT: bool;

    fn new() -> Self;

    /// Prepares the parker. This should be called before adding it to the queue.
    unsafe fn prepare_park(&self);

    /// Checks if the park timed out. This should be called while holding the
    /// queue lock after park_until has returned false.
    unsafe fn timed_out(&self) -> bool;

    /// Parks the thread until it is unparked. This should be called after it has
    /// been added to the queue, after unlocking the queue.
    unsafe fn park(&self);

    /// Parks the thread until it is unparked or the timeout is reached. This
    /// should be called after it has been added to the queue, after unlocking
    /// the queue. Returns true if we were unparked and false if we timed out.
    unsafe fn park_until(&self, timeout: Instant) -> bool;

    /// Locks the parker to prevent the target thread from exiting. This is
    /// necessary to ensure that thread-local ThreadData objects remain valid.
    /// This should be called while holding the queue lock.
    unsafe fn unpark_lock(&self) -> Self::UnparkHandle;
}

/// Handle for a thread that is about to be unparked. We need to mark the thread
/// as unparked while holding the queue lock, but we delay the actual unparking
/// until after the queue lock is released.
pub trait UnparkHandleT {
    /// Wakes up the parked thread. This should be called after the queue lock is
    /// released to avoid blocking the queue for too long.
    ///
    /// This method is unsafe for the same reason as the unsafe methods in
    /// `ThreadParkerT`.
    unsafe fn unpark(self);
}

cfg_if! {
    if #[cfg(all(has_sized_atomics, any(target_os = "linux", target_os = "android")))] {
        #[path = "linux.rs"]
        mod imp;
    } else if #[cfg(unix)] {
        #[path = "unix.rs"]
        mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows/mod.rs"]
        mod imp;
    } else if #[cfg(all(has_sized_atomics, target_os = "redox"))] {
        #[path = "redox.rs"]
        mod imp;
    } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] {
        #[path = "sgx.rs"]
        mod imp;
    } else if #[cfg(all(
        feature = "nightly",
        target_arch = "wasm32",
        target_feature = "atomics"
    ))] {
        #[path = "wasm_atomic.rs"]
        mod imp;
    } else if #[cfg(target_arch = "wasm32")] {
        #[path = "wasm.rs"]
        mod imp;
    } else if #[cfg(all(feature = "nightly", target_os = "cloudabi"))] {
        #[path = "cloudabi.rs"]
        mod imp;
    } else {
        #[path = "generic.rs"]
        mod imp;
    }
}

pub use self::imp::{thread_yield, ThreadParker, UnparkHandle};
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (R, Option<Vec<u8>>);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("poll reading");
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((self.reader.take().unwrap(), Some(result))))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((self.reader.take().unwrap(), None)))
                }
                println!("got length: {}", buf[0]);
                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
                self.wrote_header = true;
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr) -> Box<Future<Item=(), Error=::std::io::Error> + Send> {
    use all::All;

    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
        tokio_core::io::write_all(stream, [0]).map(|(a,_)| a)
    });

    let mut subscribers = Vec::new();
    for _ in 0..1 {
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
            tokio_core::io::write_all(stream, [1]).map(|(a,_)| a)
        }));
    }

    Box::new(publisher.join(All::new(subscribers.into_iter())).and_then(|(publisher, subscribers)| {
        println!("connected");

        tie_knot((publisher, subscribers, 10i32), |(publisher, subscribers, n)| {
            println!("looping {}", n);
            Writing::new(publisher, vec![n as u8, 1,2,3]).and_then(move |publisher| {
                All::new(subscribers.into_iter().map(|s| {
                    Reading::new(s).and_then(|(s, m)| {
                        println!("got: {:?}", m);
                        Ok(s)
                    })
                })).and_then(move |subscribers| {
                    futures::finished(((publisher, subscribers, n - 1), n > 0))
                })
            })
        }).map(|_| ())
    }))
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .arg(Arg::with_name("server")
             .required(false)
             .long("server")
             .short("s")
             .value_name("address")
             .default_value("127.0.0.1:8080")
             .help("TODO"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = matches.value_of("server").unwrap();
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let _child = ::std::process::Command::new(executable)
        .arg(addr_str)
        .stdout(::std::process::Stdio::inherit())
        .stderr(::std::process::Stdio::inherit())
        .spawn();

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();

    let f = pool.spawn(new_task(&handle, &addr));

    try!(core.run(f));

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<commit_msg>help text<commit_after>extern crate byteorder;
extern crate clap;

#[macro_use]
extern crate futures;
extern crate futures_cpupool;

#[macro_use]
extern crate tokio_core;

use futures::{Async, Poll, Future};

mod all {
    use futures::{Async, Poll, Future};
    enum ElemState<T> where T: Future {
        Pending(T),
        Done(T::Item),
    }

    pub struct All<T> where T: Future {
        elems: Vec<ElemState<T>>,
    }

    impl <T> All<T> where T: Future {
        pub fn new<I>(futures: I) -> All<T> where I: Iterator<Item=T> {
            let mut result = All { elems: Vec::new() };
            for f in futures {
                result.elems.push(ElemState::Pending(f))
            }
            result
        }
    }

    impl <T> Future for All<T> where T: Future {
        type Item = Vec<T::Item>;
        type Error = T::Error;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            let mut all_done = true;

            for idx in 0 .. self.elems.len() {
                let done_val = match &mut self.elems[idx] {
                    &mut ElemState::Pending(ref mut t) => {
                        match t.poll() {
                            Ok(Async::Ready(t)) => t,
                            Ok(Async::NotReady) => {
                                all_done = false;
                                continue
                            }
                            Err(e) => return Err(e),
                        }
                    }
                    &mut ElemState::Done(ref mut _v) => continue,
                };

                self.elems[idx] = ElemState::Done(done_val);
            }

            if all_done {
                let mut result = Vec::new();
                let elems = ::std::mem::replace(&mut self.elems, Vec::new());
                for e in elems.into_iter() {
                    match e {
                        ElemState::Done(t) => result.push(t),
                        _ => unreachable!(),
                    }
                }
                Ok(Async::Ready(result))
            } else {
                Ok(Async::NotReady)
            }
        }
    }
}

struct Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    f: F,
    in_progress: T,
}

fn tie_knot<F, S, T, E>(initial_state: S, f: F) -> Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>,
{
    let in_progress = f(initial_state);
    Knot {
        f: f,
        in_progress: in_progress,
    }
}

impl <F, S, T, E> Future for Knot<F, S, T, E>
    where F: Fn(S) -> T,
          T: Future<Item=(S, bool), Error=E>
{
    type Item = S;
    type Error = E;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            let (s, more) = try_ready!(self.in_progress.poll());
            if more {
                self.in_progress = (self.f)(s);
            } else {
                return Ok(Async::Ready(s))
            }
        }
    }
}

struct Reading<R> where R: ::std::io::Read {
    reader: Option<R>,
    buffer: Vec<u8>,
    pos: usize,
    frame_end: Option<u8>,
}

impl <R> Reading<R> where R: ::std::io::Read {
    fn new(reader: R) -> Reading<R> {
        Reading {
            reader: Some(reader),
            buffer: Vec::new(),
            pos: 0,
            frame_end: None,
        }
    }
}

impl <R> Future for Reading<R> where R: ::std::io::Read {
    type Item = (R, Option<Vec<u8>>);
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        println!("poll reading");
        loop {
            if let Some(frame_end) = self.frame_end {
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut self.buffer[self.pos..frame_end as usize]));
                self.pos += n;
                if self.pos == frame_end as usize {
                    self.pos = 0;
                    let result = ::std::mem::replace(&mut self.buffer, Vec::new());
                    self.frame_end = None;
                    return Ok(Async::Ready((self.reader.take().unwrap(), Some(result))))
                }
            } else {
                let mut buf = [0u8];
                let n = try_nb!(self.reader.as_mut().unwrap().read(&mut buf));
                if n == 0 { // EOF
                    return Ok(Async::Ready((self.reader.take().unwrap(), None)))
                }
                println!("got length: {}", buf[0]);
                self.frame_end = Some(buf[0]);
                self.buffer = vec![0; buf[0] as usize];
            }
        }
    }
}

pub struct Writing<W> where W: ::std::io::Write {
    writer: Option<W>,
    message: Vec<u8>,
    pos: usize,
    wrote_header: bool,
}

impl <W> Writing<W> where W: ::std::io::Write {
    fn new(writer: W, message: Vec<u8>) -> Writing<W> {
        Writing {
            writer: Some(writer),
            message: message,
            pos: 0,
            wrote_header: false,
        }
    }
}

impl <W> Future for Writing<W> where W: ::std::io::Write {
    type Item = W;
    type Error = ::std::io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.wrote_header {
                let buf = [self.message.len() as u8];
                try_nb!(self.writer.as_mut().unwrap().write(&buf));
                self.wrote_header = true;
            } else {
                let n = try_nb!(self.writer.as_mut().unwrap().write(&self.message[self.pos..]));
                self.pos += n;
                if self.pos >= self.message.len() {
                    return Ok(Async::Ready(self.writer.take().unwrap()))
                }
            }
        }
    }
}

fn new_task(handle: &::tokio_core::reactor::Handle,
            addr: &::std::net::SocketAddr) -> Box<Future<Item=(), Error=::std::io::Error> + Send> {
    use all::All;

    let publisher = ::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
        tokio_core::io::write_all(stream, [0]).map(|(a,_)| a)
    });

    let mut subscribers = Vec::new();
    for _ in 0..1 {
        subscribers.push(::tokio_core::net::TcpStream::connect(addr, handle).and_then(|stream| {
            tokio_core::io::write_all(stream, [1]).map(|(a,_)| a)
        }));
    }

    Box::new(publisher.join(All::new(subscribers.into_iter())).and_then(|(publisher, subscribers)| {
        println!("connected");

        tie_knot((publisher, subscribers, 10i32), |(publisher, subscribers, n)| {
            println!("looping {}", n);
            Writing::new(publisher, vec![n as u8, 1,2,3]).and_then(move |publisher| {
                All::new(subscribers.into_iter().map(|s| {
                    Reading::new(s).and_then(|(s, m)| {
                        println!("got: {:?}", m);
                        Ok(s)
                    })
                })).and_then(move |subscribers| {
                    futures::finished(((publisher, subscribers, n - 1), n > 0))
                })
            })
        }).map(|_| ())
    }))
}

pub fn run() -> Result<(), ::std::io::Error> {
    use clap::{App, Arg};
    let matches = App::new("Zillions benchmarker")
        .version("0.0.0")
        .about("Does awesome things")
        .arg(Arg::with_name("EXECUTABLE")
             .required(true)
             .index(1)
             .help("The executable to benchmark"))
        .arg(Arg::with_name("server")
             .required(false)
             .long("server")
             .short("s")
             .value_name("address")
             .default_value("127.0.0.1:8080")
             .help("address to use to connect to server"))
        .get_matches();

    let executable = matches.value_of("EXECUTABLE").unwrap();

    println!("exectuable: {}", executable);

    let addr_str = matches.value_of("server").unwrap();
    let addr = match addr_str.parse::<::std::net::SocketAddr>() {
        Ok(a) => a,
        Err(e) => {
            panic!("failed to parse socket address {}", e);
        }
    };

    let _child = ::std::process::Command::new(executable)
        .arg(addr_str)
        .stdout(::std::process::Stdio::inherit())
        .stderr(::std::process::Stdio::inherit())
        .spawn();

    // start tokio reactor
    let mut core = try!(::tokio_core::reactor::Core::new());

    let handle = core.handle();

    let pool = ::futures_cpupool::CpuPool::new_num_cpus();

    let f = pool.spawn(new_task(&handle, &addr));

    try!(core.run(f));

    Ok(())
}

pub fn main() {
    run().expect("top level error");
}
<|endoftext|>


<commit_before>use std::fmt::Display;

use raw_cpuid::CpuId;
use termimad::{minimad::TextTemplate, minimad::TextTemplateExpander, MadSkin};

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn make_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, u64)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_table_display<'a, 'b, D: Display>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, D)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for (attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_feature_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, bool)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let desc = if desc { "✅" } else { "❌" };
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", desc);
    }

    expander
}

fn print_title_line(title: &str, attr: Option<&str>) {
    let skin = MadSkin::default();
    if let Some(opt) = attr {
        skin.print_text(format!("## {} = \"{}\"\n", title, opt).as_str());
    } else {
        skin.print_text(format!("## {}\n", title).as_str());
    }
}

fn print_title_attr(title: &str, attr: &str) {
    print_title_line(title, Some(attr));
}

fn print_title(title: &str) {
    print_title_line(title, None)
}

fn print_subtitle(title: &str) {
    let skin = MadSkin::default();
    skin.print_text(format!("### {}\n", title).as_str());
}

fn main() {
    let cpuid = CpuId::new();
    let skin = MadSkin::default();

    skin.print_text("# CpuId\n");

    let table_template = TextTemplate::from(
        r#"
    |-:|-:|
    ${feature-rows
    |**${attr-name}**|${attr-avail}|
    }
    |-|-|
    "#,
    );

    if let Some(info) = cpuid.get_vendor_info() {
        print_title_attr("vendor_id (0x00)", info.as_str());
    }

    if let Some(info) = cpuid.get_feature_info() {
        print_title("version information (1/eax):");
        let table = make_table(
            &table_template,
            &[
                ("base family", info.base_family_id().into()),
                ("base model", info.base_model_id().into()),
                ("stepping", info.stepping_id().into()),
                ("extended family", info.extended_family_id().into()),
                ("extended model", info.extended_model_id().into()),
                ("family", info.family_id().into()),
                ("model", info.model_id().into()),
            ],
        );
        skin.print_expander(table);

        print_title("miscellaneous (1/ebx):");
        let table = make_table(
            &table_template,
            &[
                (
                    "processor APIC physical id",
                    info.initial_local_apic_id().into(),
                ),
                ("max. cpus", info.max_logical_processor_ids().into()),
                ("CLFLUSH line size", info.cflush_cache_line_size().into()),
                ("brand index", info.brand_index().into()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/edx):");
        let table = make_feature_table(
            &table_template,
            &[
                ("fpu", info.has_fpu()),
                ("vme", info.has_vme()),
                ("de", info.has_de()),
                ("pse", info.has_pse()),
                ("tsc", info.has_tsc()),
                ("msr", info.has_msr()),
                ("pae", info.has_pae()),
                ("mce", info.has_mce()),
                ("cmpxchg8b", info.has_cmpxchg8b()),
                ("apic", info.has_apic()),
                ("sysenter_sysexit", info.has_sysenter_sysexit()),
                ("mtrr", info.has_mtrr()),
                ("pge", info.has_pge()),
                ("mca", info.has_mca()),
                ("cmov", info.has_cmov()),
                ("pat", info.has_pat()),
                ("pse36", info.has_pse36()),
                ("psn", info.has_psn()),
                ("clflush", info.has_clflush()),
                ("ds", info.has_ds()),
                ("acpi", info.has_acpi()),
                ("mmx", info.has_mmx()),
                ("fxsave_fxstor", info.has_fxsave_fxstor()),
                ("sse", info.has_sse()),
                ("sse2", info.has_sse2()),
                ("ss", info.has_ss()),
                ("htt", info.has_htt()),
                ("tm", info.has_tm()),
                ("pbe", info.has_pbe()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/ecx):");

        let table = make_feature_table(
            &table_template,
            &[
                ("sse3", info.has_sse3()),
                ("pclmulqdq", info.has_pclmulqdq()),
                ("ds_area", info.has_ds_area()),
                ("monitor_mwait", info.has_monitor_mwait()),
                ("cpl", info.has_cpl()),
                ("vmx", info.has_vmx()),
                ("smx", info.has_smx()),
                ("eist", info.has_eist()),
                ("tm2", info.has_tm2()),
                ("ssse3", info.has_ssse3()),
                ("cnxtid", info.has_cnxtid()),
                ("fma", info.has_fma()),
                ("cmpxchg16b", info.has_cmpxchg16b()),
                ("pdcm", info.has_pdcm()),
                ("pcid", info.has_pcid()),
                ("dca", info.has_dca()),
                ("sse41", info.has_sse41()),
                ("sse42", info.has_sse42()),
                ("x2apic", info.has_x2apic()),
                ("movbe", info.has_movbe()),
                ("popcnt", info.has_popcnt()),
                ("tsc_deadline", info.has_tsc_deadline()),
                ("aesni", info.has_aesni()),
                ("xsave", info.has_xsave()),
                ("oxsave", info.has_oxsave()),
                ("avx", info.has_avx()),
                ("f16c", info.has_f16c()),
                ("rdrand", info.has_rdrand()),
                ("hypervisor", info.has_hypervisor()),
            ],
        );
        skin.print_expander(table);
    }

    if let Some(info) = cpuid.get_cache_info() {
        println!("Cache");
        println!("{:?}", info);
    }

    if let Some(info) = cpuid.get_processor_serial() {
        print_title_attr(
            "processor serial number (0x03)",
            format!(
                "{:0>8x}-{:0>8x}-{:0>8x}",
                info.serial_upper(),
                info.serial_middle(),
                info.serial_lower()
            )
            .as_str(),
        );
    }

    if let Some(iter) = cpuid.get_cache_parameters() {
        print_title("deterministic cache parameters (0x04):");
        for cache in iter {
            print_subtitle(format!("L{} Cache:", cache.level()).as_str());

            let size = (cache.associativity()
                * cache.physical_line_partitions()
                * cache.coherency_line_size()
                * cache.sets()) as u64;

            let mut attrs = vec![
                ("cache type", format!("{:?}", cache.cache_type())),
                ("cache level", format!("{}", cache.level())),
                (
                    "self-initializing cache level",
                    if cache.is_self_initializing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "fully associative cache",
                    if cache.is_fully_associative() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "threads sharing this cache",
                    format!("{}", cache.max_cores_for_cache()),
                ),
                (
                    "processor cores on this die",
                    format!("{}", cache.max_cores_for_package()),
                ),
                (
                    "system coherency line size",
                    format!("{}", cache.coherency_line_size()),
                ),
                (
                    "physical line partitions",
                    format!("{}", cache.physical_line_partitions()),
                ),
                (
                    "ways of associativity",
                    format!("{}", cache.associativity()),
                ),
                (
                    "WBINVD/INVD acts on lower caches",
                    if cache.is_write_back_invalidate() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "inclusive to lower caches",
                    if cache.is_inclusive() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "complex cache indexing",
                    if cache.has_complex_indexing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                ("number of sets", format!("{}", cache.sets())),
                ("(size synth.)", format!("{}", size)),
            ];

            let table = make_table_display(&table_template, &*attrs);
            skin.print_expander(table);
        }
    }

    if let Some(info) = cpuid.get_monitor_mwait_info() {
        print_title("MONITOR/MWAIT (0x05):");

        let mut attrs = vec![
            (
                "smallest monitor-line size",
                format!("{:?}", info.smallest_monitor_line()),
            ),
            (
                "largest monitor-line size",
                format!("{}", info.largest_monitor_line()),
            ),
            (
                "MONITOR/MWAIT exts supported",
                if info.extensions_supported() {
                    "✅".to_string()
                } else {
                    "❌".to_string()
                },
            ),
        ];

        let table = make_table_display(&table_template, &*attrs);
        skin.print_expander(table);

        println!("{:?}", info);
    }

    /*
    ///   MONITOR/MWAIT (5):
    ///      smallest monitor-line size (bytes)       = 0x40 (64)
    ///      largest monitor-line size (bytes)        = 0x40 (64)
    ///      enum of Monitor-MWAIT exts supported     = true
    ///      supports intrs as break-event for MWAIT  = true
    ///      number of C0 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C1 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C2 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C3 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C4 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C5 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C6 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C7 sub C-states using MWAIT    = 0x0 (0)

        */

    /*
    if let Some(info) = cpuid.get_thermal_power_info() {
        println!("Thermal Power");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_feature_info() {
        println!("Extended Features");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_direct_cache_access_info() {
        println!("Direct Cache Access");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_performance_monitoring_info() {
        println!("Performance Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_topology_info() {
        println!("Extended Topology");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_state_info() {
        println!("Extended State");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_monitoring_info() {
        println!("RDT Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_allocation_info() {
        println!("RDT Allocation");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_sgx_info() {
        println!("Software Guard Extensions");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_trace_info() {
        println!("Processor Trace");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_tsc_info() {
        println!("TSC");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_frequency_info() {
        println!("Processor Frequency");
        println!("{:?}", info);
    }
    if let Some(dats) = cpuid.get_deterministic_address_translation_info() {
        println!("Deterministic Address Translation");
        for dat in dats {
            println!("{:?}", dat);
        }
    }
    if let Some(info) = cpuid.get_soc_vendor_info() {
        println!("SoC Vendor Info");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_brand_string() {
        println!("Processor Brand String");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_memory_encryption_info() {
        println!("Memory Encryption Info");
        println!("{:?}", info);
    }
    */
}
<commit_msg>Add CX states.<commit_after>use std::fmt::Display;

use raw_cpuid::CpuId;
use termimad::{minimad::TextTemplate, minimad::TextTemplateExpander, MadSkin};

fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

fn make_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, u64)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();
    expander.set("app-version", "2");

    for &(attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_table_display<'a, 'b, D: Display>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, D)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();

    for (attr, desc) in attrs {
        let sdesc = string_to_static_str(format!("{}", desc));
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", sdesc);
    }

    expander
}

fn make_feature_table<'a, 'b>(
    text_template: &'a TextTemplate<'b>,
    attrs: &[(&'b str, bool)],
) -> TextTemplateExpander<'a, 'b> {
    let mut expander = text_template.expander();

    for &(attr, desc) in attrs {
        let desc = if desc { "✅" } else { "❌" };
        expander
            .sub("feature-rows")
            .set("attr-name", attr)
            .set("attr-avail", desc);
    }

    expander
}

fn print_title_line(title: &str, attr: Option<&str>) {
    let skin = MadSkin::default();
    if let Some(opt) = attr {
        skin.print_text(format!("## {} = \"{}\"\n", title, opt).as_str());
    } else {
        skin.print_text(format!("## {}\n", title).as_str());
    }
}

fn print_title_attr(title: &str, attr: &str) {
    print_title_line(title, Some(attr));
}

fn print_title(title: &str) {
    print_title_line(title, None)
}

fn print_subtitle(title: &str) {
    let skin = MadSkin::default();
    skin.print_text(format!("### {}\n", title).as_str());
}

fn main() {
    let cpuid = CpuId::new();
    let skin = MadSkin::default();

    skin.print_text("# CpuId\n");

    let table_template = TextTemplate::from(
        r#"
    |-:|-:|
    ${feature-rows
    |**${attr-name}**|${attr-avail}|
    }
    |-|-|
    "#,
    );

    if let Some(info) = cpuid.get_vendor_info() {
        print_title_attr("vendor_id (0x00)", info.as_str());
    }

    if let Some(info) = cpuid.get_feature_info() {
        print_title("version information (1/eax):");
        let table = make_table(
            &table_template,
            &[
                ("base family", info.base_family_id().into()),
                ("base model", info.base_model_id().into()),
                ("stepping", info.stepping_id().into()),
                ("extended family", info.extended_family_id().into()),
                ("extended model", info.extended_model_id().into()),
                ("family", info.family_id().into()),
                ("model", info.model_id().into()),
            ],
        );
        skin.print_expander(table);

        print_title("miscellaneous (1/ebx):");
        let table = make_table(
            &table_template,
            &[
                (
                    "processor APIC physical id",
                    info.initial_local_apic_id().into(),
                ),
                ("max. cpus", info.max_logical_processor_ids().into()),
                ("CLFLUSH line size", info.cflush_cache_line_size().into()),
                ("brand index", info.brand_index().into()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/edx):");
        let table = make_feature_table(
            &table_template,
            &[
                ("fpu", info.has_fpu()),
                ("vme", info.has_vme()),
                ("de", info.has_de()),
                ("pse", info.has_pse()),
                ("tsc", info.has_tsc()),
                ("msr", info.has_msr()),
                ("pae", info.has_pae()),
                ("mce", info.has_mce()),
                ("cmpxchg8b", info.has_cmpxchg8b()),
                ("apic", info.has_apic()),
                ("sysenter_sysexit", info.has_sysenter_sysexit()),
                ("mtrr", info.has_mtrr()),
                ("pge", info.has_pge()),
                ("mca", info.has_mca()),
                ("cmov", info.has_cmov()),
                ("pat", info.has_pat()),
                ("pse36", info.has_pse36()),
                ("psn", info.has_psn()),
                ("clflush", info.has_clflush()),
                ("ds", info.has_ds()),
                ("acpi", info.has_acpi()),
                ("mmx", info.has_mmx()),
                ("fxsave_fxstor", info.has_fxsave_fxstor()),
                ("sse", info.has_sse()),
                ("sse2", info.has_sse2()),
                ("ss", info.has_ss()),
                ("htt", info.has_htt()),
                ("tm", info.has_tm()),
                ("pbe", info.has_pbe()),
            ],
        );
        skin.print_expander(table);

        print_title("feature information (1/ecx):");

        let table = make_feature_table(
            &table_template,
            &[
                ("sse3", info.has_sse3()),
                ("pclmulqdq", info.has_pclmulqdq()),
                ("ds_area", info.has_ds_area()),
                ("monitor_mwait", info.has_monitor_mwait()),
                ("cpl", info.has_cpl()),
                ("vmx", info.has_vmx()),
                ("smx", info.has_smx()),
                ("eist", info.has_eist()),
                ("tm2", info.has_tm2()),
                ("ssse3", info.has_ssse3()),
                ("cnxtid", info.has_cnxtid()),
                ("fma", info.has_fma()),
                ("cmpxchg16b", info.has_cmpxchg16b()),
                ("pdcm", info.has_pdcm()),
                ("pcid", info.has_pcid()),
                ("dca", info.has_dca()),
                ("sse41", info.has_sse41()),
                ("sse42", info.has_sse42()),
                ("x2apic", info.has_x2apic()),
                ("movbe", info.has_movbe()),
                ("popcnt", info.has_popcnt()),
                ("tsc_deadline", info.has_tsc_deadline()),
                ("aesni", info.has_aesni()),
                ("xsave", info.has_xsave()),
                ("oxsave", info.has_oxsave()),
                ("avx", info.has_avx()),
                ("f16c", info.has_f16c()),
                ("rdrand", info.has_rdrand()),
                ("hypervisor", info.has_hypervisor()),
            ],
        );
        skin.print_expander(table);
    }

    if let Some(info) = cpuid.get_cache_info() {
        println!("Cache");
        println!("{:?}", info);
    }

    if let Some(info) = cpuid.get_processor_serial() {
        print_title_attr(
            "processor serial number (0x03)",
            format!(
                "{:0>8x}-{:0>8x}-{:0>8x}",
                info.serial_upper(),
                info.serial_middle(),
                info.serial_lower()
            )
            .as_str(),
        );
    }

    if let Some(iter) = cpuid.get_cache_parameters() {
        print_title("deterministic cache parameters (0x04):");
        for cache in iter {
            print_subtitle(format!("L{} Cache:", cache.level()).as_str());

            let size = (cache.associativity()
                * cache.physical_line_partitions()
                * cache.coherency_line_size()
                * cache.sets()) as u64;

            let mut attrs = vec![
                ("cache type", format!("{:?}", cache.cache_type())),
                ("cache level", format!("{}", cache.level())),
                (
                    "self-initializing cache level",
                    if cache.is_self_initializing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "fully associative cache",
                    if cache.is_fully_associative() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "threads sharing this cache",
                    format!("{}", cache.max_cores_for_cache()),
                ),
                (
                    "processor cores on this die",
                    format!("{}", cache.max_cores_for_package()),
                ),
                (
                    "system coherency line size",
                    format!("{}", cache.coherency_line_size()),
                ),
                (
                    "physical line partitions",
                    format!("{}", cache.physical_line_partitions()),
                ),
                (
                    "ways of associativity",
                    format!("{}", cache.associativity()),
                ),
                (
                    "WBINVD/INVD acts on lower caches",
                    if cache.is_write_back_invalidate() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "inclusive to lower caches",
                    if cache.is_inclusive() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                (
                    "complex cache indexing",
                    if cache.has_complex_indexing() {
                        "✅".to_string()
                    } else {
                        "❌".to_string()
                    },
                ),
                ("number of sets", format!("{}", cache.sets())),
                ("(size synth.)", format!("{}", size)),
            ];

            let table = make_table_display(&table_template, &*attrs);
            skin.print_expander(table);
        }
    }

    if let Some(info) = cpuid.get_monitor_mwait_info() {
        print_title("MONITOR/MWAIT (0x05):");

        let mut attrs = vec![
            (
                "smallest monitor-line size",
                format!("{:?}", info.smallest_monitor_line()),
            ),
            (
                "largest monitor-line size",
                format!("{}", info.largest_monitor_line()),
            ),
            (
                "MONITOR/MWAIT exts supported",
                if info.extensions_supported() {
                    "✅".to_string()
                } else {
                    "❌".to_string()
                },
            ),
            (
                "Interrupts as break-event for MWAIT",
                if info.interrupts_as_break_event() {
                    "✅".to_string()
                } else {
                    "❌".to_string()
                },
            ),
        ];

        let table = make_table_display(&table_template, &*attrs);
        skin.print_expander(table);

        skin.print_text("number of CX sub C-states using MWAIT:\n");
        let cstate_table = TextTemplate::from(
            r#"
        |:-|-:|
        |**C0**|**C1**|**C2**|**C3**|**C4**|**C5**|**C6**|**C7**|
        |${c0}|${c1}|${c2}|${c3}|${c4}|${c5}|${c6}|${c7}|
        |-|-|
        "#,
        );
        let c0 = format!("{}", info.supported_c0_states());
        let c1 = format!("{}", info.supported_c1_states());
        let c2 = format!("{}", info.supported_c2_states());
        let c3 = format!("{}", info.supported_c3_states());
        let c4 = format!("{}", info.supported_c4_states());
        let c5 = format!("{}", info.supported_c5_states());
        let c6 = format!("{}", info.supported_c6_states());
        let c7 = format!("{}", info.supported_c7_states());

        let mut ctbl = cstate_table.expander();
        ctbl.set("c0", c0.as_str());
        ctbl.set("c1", c1.as_str());
        ctbl.set("c2", c2.as_str());
        ctbl.set("c3", c3.as_str());
        ctbl.set("c4", c4.as_str());
        ctbl.set("c5", c5.as_str());
        ctbl.set("c6", c6.as_str());
        ctbl.set("c7", c7.as_str());
        skin.print_expander(ctbl);
    }

    /*
    ///   MONITOR/MWAIT (5):
    ///      smallest monitor-line size (bytes)       = 0x40 (64)
    ///      largest monitor-line size (bytes)        = 0x40 (64)
    ///      enum of Monitor-MWAIT exts supported     = true
    ///      supports intrs as break-event for MWAIT  = true
    ///      number of C0 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C1 sub C-states using MWAIT    = 0x1 (1)
    ///      number of C2 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C3 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C4 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C5 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C6 sub C-states using MWAIT    = 0x0 (0)
    ///      number of C7 sub C-states using MWAIT    = 0x0 (0)

        */

    /*
    if let Some(info) = cpuid.get_thermal_power_info() {
        println!("Thermal Power");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_feature_info() {
        println!("Extended Features");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_direct_cache_access_info() {
        println!("Direct Cache Access");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_performance_monitoring_info() {
        println!("Performance Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_topology_info() {
        println!("Extended Topology");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_extended_state_info() {
        println!("Extended State");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_monitoring_info() {
        println!("RDT Monitoring");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_rdt_allocation_info() {
        println!("RDT Allocation");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_sgx_info() {
        println!("Software Guard Extensions");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_trace_info() {
        println!("Processor Trace");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_tsc_info() {
        println!("TSC");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_frequency_info() {
        println!("Processor Frequency");
        println!("{:?}", info);
    }
    if let Some(dats) = cpuid.get_deterministic_address_translation_info() {
        println!("Deterministic Address Translation");
        for dat in dats {
            println!("{:?}", dat);
        }
    }
    if let Some(info) = cpuid.get_soc_vendor_info() {
        println!("SoC Vendor Info");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_processor_brand_string() {
        println!("Processor Brand String");
        println!("{:?}", info);
    }
    if let Some(info) = cpuid.get_memory_encryption_info() {
        println!("Memory Encryption Info");
        println!("{:?}", info);
    }
    */
}
<|endoftext|>