<commit_before>extern crate nalgebra;

use memoized_flat_time_steward as s;
use {TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, PredictorId, Mutator,
     TimeStewardStaticMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use collision_detection::inefficient as collisions;

use time_functions::QuadraticTrajectory;
use std::rc::Rc;
use rand::Rng;
use nalgebra::Vector2;
use std::thread::sleep;
use std::time::{Instant, Duration};
use glium;
use glium::{DisplayBuild, Surface};

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;
type SpaceCoordinate = i64;

const HOW_MANY_CIRCLES: i32 = 20;
const ARENA_SIZE: SpaceCoordinate = (1 << 20);
const TIME_SHIFT: i32 = 20;
const SECOND: Time = (1 << TIME_SHIFT);

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}
struct CollisionBasics {}
impl ::collision_detection::Basics for CollisionBasics {
  type StewardBasics = Basics;
  type DetectorId =();
  fn nearness_column_id() -> ColumnId {
    ColumnId(0x89ebc3ba9a24c286)
  }
}

type Nearness = ::collision_detection::Nearness<CollisionBasics>;

#[derive(Clone)]
struct Circle {
  position: QuadraticTrajectory,
  radius: SpaceCoordinate,
}
impl Column for Circle {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x6422505ce8c8ce8e)
  }
}
struct Intersection {
  induced_acceleration: Vector2<SpaceCoordinate>,
}
impl Column for Intersection {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x9357f021339198a1)
  }
}

type Steward = s::Steward<Basics>;

fn get_circle_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x86ccbeb2c140cc51u64, index))
}

fn collision_predictor <PA: PredictorAccessor <Basics, <s::Steward <Basics> as TimeStewardStaticMethods < Basics>>::EventFn >> (accessor: &mut PA, id: RowId) {
  printlnerr!("Planning {}", id);
  let ids = Nearness::get_ids(accessor, id).0;
  let time;
  {

    let us = (accessor.data_and_last_change::<Circle>(ids[0])
                      .expect("a nearness exists for a circle that doesn't"),
              accessor.data_and_last_change::<Circle>(ids[0])
                      .expect("a nearness exists for a circle that doesn't"));

    let relationship = accessor.get::<Intersection>(id);
    time = QuadraticTrajectory::approximately_when_distance_passes((us.0).0.radius +
                                                                   (us.1).0.radius,
                                                                   if relationship.is_none() {
                                                                     -1
                                                                   } else {
                                                                     1
                                                                   },
                                                                   ((us.0).1.clone(),
                                                                    &(us.0).0.position),
                                                                   ((us.1).1.clone(),
                                                                    &(us.1).0.position));
    printlnerr!("At {}, {}", (us.0).1, (us.1).1);
  }
  if let Some(yes) = time {
    accessor.predict_at_time(&yes,
                             Rc::new(move |mutator| {
                               let new_relationship;
                               let mut new;
                               {
                                 let relationship = mutator.get::<Intersection>(id).clone();
                                 let us = (mutator.data_and_last_change::<Circle>(ids[0])
                                                  .expect("a nearness exists for a circle that \
                                                           doesn't (event)"),
                                           mutator.data_and_last_change::<Circle>(ids[0])
                                                  .expect("a nearness exists for a circle that \
                                                           doesn't (event)"));
                                 new = ((us.0).0.clone(), (us.1).0.clone());
                                 new.0.position.update_by(mutator.now() - (us.0).1);
                                 new.1.position.update_by(mutator.now() - (us.1).1);
                                 if let Some(intersection) = relationship {
                                   new.0
                                      .position
                                      .add_acceleration(-intersection.induced_acceleration);
                                   new.1
                                      .position
                                      .add_acceleration(intersection.induced_acceleration);
                                   new_relationship = None;
                                 } else {
                                   let acceleration = Vector2::new(ARENA_SIZE, ARENA_SIZE);
                                   new.0.position.add_acceleration(acceleration);
                                   new.1.position.add_acceleration(-acceleration);
                                   new_relationship = Some(Intersection {
                                     induced_acceleration: acceleration,
                                   });

                                 }
                               }
                               mutator.set::<Intersection>(id, new_relationship);
                               mutator.set::<Circle>(ids[0], Some(new.0));
                               mutator.set::<Circle>(ids[1], Some(new.1));
                             }));
  }
}

#[derive(Copy, Clone)]

struct Vertex {
  direction: [f32; 2],
  center: [f32; 2],
  radius: f32,
}
implement_vertex!(Vertex, direction, center, radius);

pub fn testfunc() {

  let mut stew: Steward =
    ::TimeStewardStaticMethods::new_empty((),
                                          vec![s::Predictor {
                                                 predictor_id: PredictorId(0x5375592f4da8682c),
                                                 column_id: Nearness::column_id(),
                                                 function: Rc::new(|accessor, id| {
                                                   collision_predictor(accessor, id)
                                                 }),
                                               }]); /*{
      printlnerr!("Planning {}", id);
      let me = pa.get::<Circle>(id).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! @{}. {}={}; {}={}", now, whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);*/

  stew.insert_fiat_event(-1,
                         DeterministicRandomId::new(&0),
                         Rc::new(|mutator| {
                           for i in 0..HOW_MANY_CIRCLES {
                             let thingy = ARENA_SIZE / 20;
                             let radius = mutator.rng().gen_range(ARENA_SIZE / 30, ARENA_SIZE / 15);
                             let id = get_circle_id(i);

                             let position =
                               QuadraticTrajectory::new(TIME_SHIFT,
                                                        [mutator.rng().gen_range(0, ARENA_SIZE),
                                                         mutator.rng().gen_range(0, ARENA_SIZE),
                                                         mutator.rng().gen_range(-thingy, thingy),
                                                         mutator.rng().gen_range(-thingy, thingy),
                                                         0,
                                                         0]);
                             mutator.set::<Circle>(id,
                                                   Some(Circle {
                                                     position: position,
                                                     radius: radius,
                                                   }));
                             collisions::insert::<CollisionBasics, _>(mutator, id, ());
                           }
                         }));
  let vertex_shader_source = r#"
#version 140
in vec2 direction;
in vec2 center;
in float radius;
out vec2 direction_transfer;

void main() {
direction_transfer = direction*1.5;
gl_Position = vec4 ( center + direction*1.5*radius, 0.0, 0.0);
}

"#;

  let fragment_shader_source = r#"
#version 140
in vec2 direction_transfer;
out vec4 color;

void main() {
if (dot (direction_transfer,direction_transfer) <1.0) {
color = vec4 (1.0, 0.0, 0.0, 1.0);
} else {
color = vec4 (0.0, 0.0, 0.0, 0.0);

}
}

"#;

  return;
  let display = glium::glutin::WindowBuilder::new()
                  .with_dimensions(600, 6)
                  .build_glium()
                  .expect("failed to create window");
  let program = glium::Program::from_source(&display,
                                            vertex_shader_source,
                                            fragment_shader_source,
                                            None)
                  .unwrap();
  let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
  let mut snapshots = Vec::new();
  let start = Instant::now();
  loop {
    for ev in display.poll_events() {
      match ev {
        glium::glutin::Event::Closed => return,
        _ => (),
      }
    }

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 1.0);
    let mut vertices = Vec::<Vertex>::new();

    let snapshot = stew.snapshot_before(&(start.elapsed().subsec_nanos() as i64 * SECOND /
                                          1000000000i64))
                       .unwrap();
    for index in 0..HOW_MANY_CIRCLES {
      let (circle, time) = snapshot.data_and_last_change::<Circle>(get_circle_id(index))
                                   .expect("missing circle")
                                   .clone();
      let position = circle.position.updated_by(snapshot.now() - time).evaluate();
      let center = [position[0] as f32 / ARENA_SIZE as f32, position[1] as f32 / ARENA_SIZE as f32];
      vertices.extend(&[Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [-1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [0.0, 1.0],
                        },
                        Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [-1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: circle.radius as f32,
                          direction: [0.0, -1.0],
                        }]);

    }
    target.draw(&glium::VertexBuffer::new(&display, &vertices).unwrap(),
                &indices,
                &program,
                &glium::uniforms::EmptyUniforms,
                &Default::default())
          .unwrap();

    target.finish().expect("failed to finish drawing");

    sleep(Duration::from_millis(10));
  }

  for increment in 1..21 {
    snapshots.push(stew.snapshot_before(&(increment * SECOND * 2)));
  }
  for snapshot in snapshots.iter_mut().map(|option| {
    option.as_mut().expect("all these snapshots should have been valid")
  }) {
    printlnerr!("snapshot for {}", snapshot.now());
    for index in 0..HOW_MANY_CIRCLES {
      // printlnerr!("{}", snapshot.get::<Circle> (get_circle_id (index)).expect("missing circle").position);
    }
  }
  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<commit_msg>fixed some gl stuff<commit_after>extern crate nalgebra;

use memoized_flat_time_steward as s;
use {TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, PredictorId, Mutator,
     TimeStewardStaticMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use collision_detection::inefficient as collisions;

use time_functions::QuadraticTrajectory;
use std::rc::Rc;
use rand::Rng;
use nalgebra::Vector2;
use std::thread::sleep;
use std::time::{Instant, Duration};
use glium;
use glium::{DisplayBuild, Surface};

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;
type SpaceCoordinate = i64;

const HOW_MANY_CIRCLES: i32 = 20;
const ARENA_SIZE: SpaceCoordinate = (1 << 20);
const TIME_SHIFT: i32 = 20;
const SECOND: Time = (1 << TIME_SHIFT);

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}
struct CollisionBasics {}
impl ::collision_detection::Basics for CollisionBasics {
  type StewardBasics = Basics;
  type DetectorId =();
  fn nearness_column_id() -> ColumnId {
    ColumnId(0x89ebc3ba9a24c286)
  }
}

type Nearness = ::collision_detection::Nearness<CollisionBasics>;

#[derive(Clone)]
struct Circle {
  position: QuadraticTrajectory,
  radius: SpaceCoordinate,
}
impl Column for Circle {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x6422505ce8c8ce8e)
  }
}
struct Intersection {
  induced_acceleration: Vector2<SpaceCoordinate>,
}
impl Column for Intersection {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x9357f021339198a1)
  }
}

type Steward = s::Steward<Basics>;

fn get_circle_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x86ccbeb2c140cc51u64, index))
}

fn collision_predictor <PA: PredictorAccessor <Basics, <s::Steward <Basics> as TimeStewardStaticMethods < Basics>>::EventFn >> (accessor: &mut PA, id: RowId) {
  printlnerr!("Planning {}", id);
  let ids = Nearness::get_ids(accessor, id).0;
  let time;
  {

    let us = (accessor.data_and_last_change::<Circle>(ids[0])
                      .expect("a nearness exists for a circle that doesn't"),
              accessor.data_and_last_change::<Circle>(ids[0])
                      .expect("a nearness exists for a circle that doesn't"));

    let relationship = accessor.get::<Intersection>(id);
    time = QuadraticTrajectory::approximately_when_distance_passes((us.0).0.radius +
                                                                   (us.1).0.radius,
                                                                   if relationship.is_none() {
                                                                     -1
                                                                   } else {
                                                                     1
                                                                   },
                                                                   ((us.0).1.clone(),
                                                                    &(us.0).0.position),
                                                                   ((us.1).1.clone(),
                                                                    &(us.1).0.position));
    printlnerr!("At {}, {}", (us.0).1, (us.1).1);
  }
  if let Some(yes) = time {
    accessor.predict_at_time(&yes,
                             Rc::new(move |mutator| {
                               let new_relationship;
                               let mut new;
                               {
                                 let relationship = mutator.get::<Intersection>(id).clone();
                                 let us = (mutator.data_and_last_change::<Circle>(ids[0])
                                                  .expect("a nearness exists for a circle that \
                                                           doesn't (event)"),
                                           mutator.data_and_last_change::<Circle>(ids[0])
                                                  .expect("a nearness exists for a circle that \
                                                           doesn't (event)"));
                                 new = ((us.0).0.clone(), (us.1).0.clone());
                                 new.0.position.update_by(mutator.now() - (us.0).1);
                                 new.1.position.update_by(mutator.now() - (us.1).1);
                                 if let Some(intersection) = relationship {
                                   new.0
                                      .position
                                      .add_acceleration(-intersection.induced_acceleration);
                                   new.1
                                      .position
                                      .add_acceleration(intersection.induced_acceleration);
                                   new_relationship = None;
                                 } else {
                                   let acceleration = Vector2::new(ARENA_SIZE, ARENA_SIZE);
                                   new.0.position.add_acceleration(acceleration);
                                   new.1.position.add_acceleration(-acceleration);
                                   new_relationship = Some(Intersection {
                                     induced_acceleration: acceleration,
                                   });

                                 }
                               }
                               mutator.set::<Intersection>(id, new_relationship);
                               mutator.set::<Circle>(ids[0], Some(new.0));
                               mutator.set::<Circle>(ids[1], Some(new.1));
                             }));
  }
}

#[derive(Copy, Clone)]

struct Vertex {
  direction: [f32; 2],
  center: [f32; 2],
  radius: f32,
}
implement_vertex!(Vertex, direction, center, radius);

pub fn testfunc() {

  let mut stew: Steward =
    ::TimeStewardStaticMethods::new_empty((),
                                          vec![s::Predictor {
                                                 predictor_id: PredictorId(0x5375592f4da8682c),
                                                 column_id: Nearness::column_id(),
                                                 function: Rc::new(|accessor, id| {
                                                   collision_predictor(accessor, id)
                                                 }),
                                               }]); /*{
      printlnerr!("Planning {}", id);
      let me = pa.get::<Circle>(id).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! @{}. {}={}; {}={}", now, whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);*/

  stew.insert_fiat_event(-1,
                         DeterministicRandomId::new(&0),
                         Rc::new(|mutator| {
                           for i in 0..HOW_MANY_CIRCLES {
                             let thingy = ARENA_SIZE / 20;
                             let radius = mutator.rng().gen_range(ARENA_SIZE / 30, ARENA_SIZE / 15);
                             let id = get_circle_id(i);

                             let position =
                               QuadraticTrajectory::new(TIME_SHIFT,
                                                        [mutator.rng().gen_range(0, ARENA_SIZE),
                                                         mutator.rng().gen_range(0, ARENA_SIZE),
                                                         mutator.rng().gen_range(-thingy, thingy),
                                                         mutator.rng().gen_range(-thingy, thingy),
                                                         0,
                                                         0]);
                             mutator.set::<Circle>(id,
                                                   Some(Circle {
                                                     position: position,
                                                     radius: radius,
                                                   }));
                             collisions::insert::<CollisionBasics, _>(mutator, id, ());
                           }
                         }));
  let vertex_shader_source = r#"
#version 140
in vec2 direction;
in vec2 center;
in float radius;
out vec2 direction_transfer;

void main() {
direction_transfer = direction*1.5;
gl_Position = vec4 ( center + direction*1.5*radius, 0.0, 1.0);
}

"#;

  let fragment_shader_source = r#"
#version 140
in vec2 direction_transfer;
out vec4 color;

void main() {
if (dot (direction_transfer,direction_transfer) <1.0) {
color = vec4 (1.0, 0.0, 0.0, 1.0);
} else {
color = vec4 (0.0, 0.0, 0.0, 0.0);

}
}

"#;

  return;
  let display = glium::glutin::WindowBuilder::new()
                  .with_dimensions(600, 600)
                  .build_glium()
                  .expect("failed to create window");
  let program = glium::Program::from_source(&display,
                                            vertex_shader_source,
                                            fragment_shader_source,
                                            None)
                  .unwrap();
  let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);
  let mut snapshots = Vec::new();
  let start = Instant::now();
  loop {
    for ev in display.poll_events() {
      match ev {
        glium::glutin::Event::Closed => return,
        _ => (),
      }
    }

    let mut target = display.draw();
    target.clear_color(0.0, 0.0, 0.0, 1.0);
    let mut vertices = Vec::<Vertex>::new();

    let snapshot = stew.snapshot_before(&(start.elapsed().subsec_nanos() as i64 * SECOND /
                                          1000000000i64))
                       .unwrap();
    for index in 0..HOW_MANY_CIRCLES {
      let (circle, time) = snapshot.data_and_last_change::<Circle>(get_circle_id(index))
                                   .expect("missing circle")
                                   .clone();
      let position = circle.position.updated_by(snapshot.now() - time).evaluate();
      let center = [position[0] as f32 / ARENA_SIZE as f32, position[1] as f32 / ARENA_SIZE as f32];
      let radius = circle.radius as f32 / ARENA_SIZE as f32;
    printlnerr!("drawing circ at {}, {}", center[0],center[1]);
      vertices.extend(&[Vertex {
                          center: center,
                          radius: radius,
                          direction: [1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: radius,
                          direction: [-1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: radius,
                          direction: [0.0, 1.0],
                        },
                        Vertex {
                          center: center,
                          radius: radius,
                          direction: [1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: radius,
                          direction: [-1.0, 0.0],
                        },
                        Vertex {
                          center: center,
                          radius: radius,
                          direction: [0.0, -1.0],
                        }]);

    }
    target.draw(&glium::VertexBuffer::new(&display, &vertices).unwrap(),
                &indices,
                &program,
                &glium::uniforms::EmptyUniforms,
                &Default::default())
          .unwrap();

    target.finish().expect("failed to finish drawing");

    sleep(Duration::from_millis(10));
  }

  for increment in 1..21 {
    snapshots.push(stew.snapshot_before(&(increment * SECOND * 2)));
  }
  for snapshot in snapshots.iter_mut().map(|option| {
    option.as_mut().expect("all these snapshots should have been valid")
  }) {
    printlnerr!("snapshot for {}", snapshot.now());
    for index in 0..HOW_MANY_CIRCLES {
      // printlnerr!("{}", snapshot.get::<Circle> (get_circle_id (index)).expect("missing circle").position);
    }
  }
  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<|endoftext|>


<commit_before>extern crate rustbox;
extern crate time;
extern crate tiny;

use tiny::tui::{TUI, TUIRet, MsgTarget};

fn loop_()  {
    let mut tui = TUI::new();
    tui.new_server_tab("debug");

    loop {
        match tui.idle_loop() {
            TUIRet::Input { msg, from } => {
                tui.add_msg(&msg.into_iter().collect::<String>(),
                            &time::now(),
                            &MsgTarget::Server { serv_name: "debug" });
            },
            TUIRet::Abort => {
                break;
            },
            _ => {}
        }
    }
}

fn main() {
    loop_();
}
<commit_msg>Remove idle_loop example<commit_after><|endoftext|>


<commit_before>/* diosix abstracted hardware manager
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

use alloc::vec::Vec;
use super::lock::Mutex;
use platform::devices::Devices;
use platform::physmem::{PhysMemBase, PhysMemSize};
use platform::timer;
use super::error::Cause;

lazy_static!
{
    /* acquire HARDWARE before accessing any system hardware */
    static ref HARDWARE: Mutex<Option<Devices>> = Mutex::new("hardware management", None);
}

/* parse_and_init
   Parse a device tree structure to create a base set of hardware devices.
   also initialize the devices so they can be used.
   call before using acquire_hardware_lock() to access HARDWARE.
   => device_tree = byte slice containing the device tree in physical memory
   <= return Ok for success, or error code on failure
*/
pub fn parse_and_init(dtb: &[u8]) -> Result<(), Cause>
{
    if let Ok(dt) = Devices::new(dtb)
    {
        *(HARDWARE.lock()) = Some(dt);
        return Ok(())
    }
    else
    {
        return Err(Cause::DeviceTreeBad);
    }
}

/* routines to interact with the system's base devices */

/* write the string msg out to the debug logging console.
   if the system is busy, return
   => msg = string to write out
   <= true if able to write, false if not */
pub fn write_debug_string(msg: &str) -> bool
{
    /* avoid blocking if we can */
    if HARDWARE.is_locked() == true
    {
        return false;
    }

    match &*(HARDWARE.lock())
    {
        Some(d) =>
        {
            d.write_debug_string(msg);
            true
        },
        None => false
    }
}

/* return number of discovered logical CPU cores, or None if value unavailable */
pub fn get_nr_cpu_cores() -> Option<usize>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => Some(d.get_nr_cpu_cores()),
        None => None
    }
}

/* return a list of the physical RAM chunks present in the system,
or None if we can't read the available memory */
pub fn get_phys_ram_chunks() -> Option<Vec<platform::physmem::RAMArea>>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => Some(d.get_phys_ram_areas()),
        None => None
    }
}

/* return total amount of physical RAM present in the system */
pub fn get_phys_ram_total() -> Option<usize>
{
    if let Some(areas) = get_phys_ram_chunks()
    {
        let mut total = 0;
        for area in areas
        {
            total = total + area.size;
        }

        return Some(total);
    }

    None
}

/* for this CPU core, enable scheduler timer interrupt */
pub fn scheduler_timer_start()
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_start(),
        None => ()
    };
}

/* tell the scheduler to interrupt this core
when duration number of timer ticks or sub-seconds passes */
pub fn scheduler_timer_next_in(duration: timer::TimerValue)
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_next_in(duration),
        None => ()
    };
}

/* tell the scheduler to interrupt this core when the system clock equals
target value in ticks or sub-seconds as its current value */
pub fn scheduler_timer_at(target: timer::TimerValue)
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_at(target),
        None => ()
    };
}

/* get when the scheduler timer IRQ is next set to fire on this core.
this is a clock-on-the-wall value: it's a number of ticks or
sub-seconds since the timer started, not the duration to the next IRQ */
pub fn scheduler_get_timer_next_at() -> Option<timer::TimerValue>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_next_at(),
        None => None
    }
}

/* get the CPU's timer frequency in Hz */
pub fn scheduler_get_timer_frequency() -> Option<u64>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_frequency(),
        None => None
    }
}

/* return the timer's current value in microseconds, or None for no timer
this is a clock-on-the-wall value in that it always incremements and does
not reset. the underlying platform code can do what it needs to implement this */
pub fn scheduler_get_timer_now() -> Option<timer::TimerValue>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_now(),
        None => None
    }
}

/* clone the system's base device tree blob structure so it can be passed
to guest capsules. the platform code should customize the tree to ensure
peripherals are virtualized. the platform code therefore controls what
hardware is provided. the hypervisor sets how many CPUs and RAM are available.
the rest is decided by the platform code.
   => cpus = number of virtual CPU cores in this capsule
      boot_cpu_id = ID of system's boot CPU (typically 0)
      mem_base = base physical address of the contiguous system RAM
      mem_size = number of bytes available in the system RAM
   <= returns dtb as a byte array, or an error code
*/
pub fn clone_dtb_for_capsule(cpus: usize, boot_cpu_id: u32, mem_base: PhysMemBase, mem_size: PhysMemSize) -> Result<Vec<u8>, Cause>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => match d.spawn_virtual_environment(cpus, boot_cpu_id, mem_base, mem_size)
        {
            Some(v) => return Ok(v),
            None => return Err(Cause::DeviceTreeBad)
        },
        None => Err(Cause::CantCloneDevices)
    }
}<commit_msg>Minor comment edit<commit_after>/* diosix abstracted hardware manager
 *
 * (c) Chris Williams, 2019-2021.
 *
 * See LICENSE for usage and copying.
 */

use alloc::vec::Vec;
use super::lock::Mutex;
use platform::devices::Devices;
use platform::physmem::{PhysMemBase, PhysMemSize};
use platform::timer;
use super::error::Cause;

lazy_static!
{
    /* acquire HARDWARE before accessing any system hardware */
    static ref HARDWARE: Mutex<Option<Devices>> = Mutex::new("hardware management", None);
}

/* parse_and_init
   Parse a device tree structure to create a base set of hardware devices.
   also initialize the devices so they can be used.
   call before using acquire_hardware_lock() to access HARDWARE.
   => device_tree = byte slice containing the device tree in physical memory
   <= return Ok for success, or error code on failure
*/
pub fn parse_and_init(dtb: &[u8]) -> Result<(), Cause>
{
    if let Ok(dt) = Devices::new(dtb)
    {
        *(HARDWARE.lock()) = Some(dt);
        return Ok(())
    }
    else
    {
        return Err(Cause::DeviceTreeBad);
    }
}

/* routines to interact with the system's base devices */

/* write the string msg out to the debug logging console.
   if the system is busy, return
   => msg = string to write out (not necessarily zero term'd)
   <= true if able to write, false if not */
pub fn write_debug_string(msg: &str) -> bool
{
    /* avoid blocking if we can */
    if HARDWARE.is_locked() == true
    {
        return false;
    }

    match &*(HARDWARE.lock())
    {
        Some(d) =>
        {
            d.write_debug_string(msg);
            true
        },
        None => false
    }
}

/* read a single character from the debuging console, or None if none.
   this does not block */
pub fn read_debug_char() -> Option<char>
{
    /* avoid blocking on a lock if we can */
    if HARDWARE.is_locked() == true
    {
        return None;
    }

    match &*(HARDWARE.lock())
    {
        Some(d) => d.read_debug_char(),
        None => None
    }
}

/* return number of discovered logical CPU cores, or None if value unavailable */
pub fn get_nr_cpu_cores() -> Option<usize>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => Some(d.get_nr_cpu_cores()),
        None => None
    }
}

/* return a list of the physical RAM chunks present in the system,
or None if we can't read the available memory */
pub fn get_phys_ram_chunks() -> Option<Vec<platform::physmem::RAMArea>>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => Some(d.get_phys_ram_areas()),
        None => None
    }
}

/* return total amount of physical RAM present in the system */
pub fn get_phys_ram_total() -> Option<usize>
{
    if let Some(areas) = get_phys_ram_chunks()
    {
        let mut total = 0;
        for area in areas
        {
            total = total + area.size;
        }

        return Some(total);
    }

    None
}

/* for this CPU core, enable scheduler timer interrupt */
pub fn scheduler_timer_start()
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_start(),
        None => ()
    };
}

/* tell the scheduler to interrupt this core
when duration number of timer ticks or sub-seconds passes */
pub fn scheduler_timer_next_in(duration: timer::TimerValue)
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_next_in(duration),
        None => ()
    };
}

/* tell the scheduler to interrupt this core when the system clock equals
target value in ticks or sub-seconds as its current value */
pub fn scheduler_timer_at(target: timer::TimerValue)
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_timer_at(target),
        None => ()
    };
}

/* get when the scheduler timer IRQ is next set to fire on this core.
this is a clock-on-the-wall value: it's a number of ticks or
sub-seconds since the timer started, not the duration to the next IRQ */
pub fn scheduler_get_timer_next_at() -> Option<timer::TimerValue>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_next_at(),
        None => None
    }
}

/* get the CPU's timer frequency in Hz */
pub fn scheduler_get_timer_frequency() -> Option<u64>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_frequency(),
        None => None
    }
}

/* return the timer's current value in microseconds, or None for no timer
this is a clock-on-the-wall value in that it always incremements and does
not reset. the underlying platform code can do what it needs to implement this */
pub fn scheduler_get_timer_now() -> Option<timer::TimerValue>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => d.scheduler_get_timer_now(),
        None => None
    }
}

/* clone the system's base device tree blob structure so it can be passed
to guest capsules. the platform code should customize the tree to ensure
peripherals are virtualized. the platform code therefore controls what
hardware is provided. the hypervisor sets how many CPUs and RAM are available.
the rest is decided by the platform code.
   => cpus = number of virtual CPU cores in this capsule
      boot_cpu_id = ID of system's boot CPU (typically 0)
      mem_base = base physical address of the contiguous system RAM
      mem_size = number of bytes available in the system RAM
   <= returns dtb as a byte array, or an error code
*/
pub fn clone_dtb_for_capsule(cpus: usize, boot_cpu_id: u32, mem_base: PhysMemBase, mem_size: PhysMemSize) -> Result<Vec<u8>, Cause>
{
    match &*(HARDWARE.lock())
    {
        Some(d) => match d.spawn_virtual_environment(cpus, boot_cpu_id, mem_base, mem_size)
        {
            Some(v) => return Ok(v),
            None => return Err(Cause::DeviceTreeBad)
        },
        None => Err(Cause::CantCloneDevices)
    }
}<|endoftext|>


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

use app_units::Au;
use cssparser::RGBA;
use gecko_bindings::structs::{nsStyleCoord, nsStyleUnion, nsStyleUnit};
use std::cmp::max;
use style::values::computed::Angle;
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};

pub trait StyleCoordHelpers {
    fn copy_from(&mut self, other: &Self);
    fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T);

    fn set_auto(&mut self);
    fn is_auto(&self) -> bool;

    fn set_normal(&mut self);
    fn is_normal(&self) -> bool;

    fn set_coord(&mut self, val: Au);
    fn is_coord(&self) -> bool;
    fn get_coord(&self) -> Au;

    fn set_int(&mut self, val: i32);
    fn is_int(&self) -> bool;
    fn get_int(&self) -> i32;

    fn set_enum(&mut self, val: i32);
    fn is_enum(&self) -> bool;
    fn get_enum(&self) -> i32;

    fn set_percent(&mut self, val: f32);
    fn is_percent(&self) -> bool;
    fn get_percent(&self) -> f32;

    fn set_factor(&mut self, val: f32);
    fn is_factor(&self) -> bool;
    fn get_factor(&self) -> f32;
}

impl StyleCoordHelpers for nsStyleCoord {
    #[inline]
    fn copy_from(&mut self, other: &Self) {
        debug_assert_unit_is_safe_to_copy(self.mUnit);
        debug_assert_unit_is_safe_to_copy(other.mUnit);
        self.mUnit = other.mUnit;
        self.mValue = other.mValue;
    }

    #[inline]
    fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T) {
        val.to_gecko_style_coord(&mut self.mUnit, &mut self.mValue);
    }

    #[inline]
    fn set_auto(&mut self) {
        self.mUnit = nsStyleUnit::eStyleUnit_Auto;
        unsafe { *self.mValue.mInt.as_mut() = 0; }
    }
    #[inline]
    fn is_auto(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Auto
    }

    #[inline]
    fn set_normal(&mut self) {
        self.mUnit = nsStyleUnit::eStyleUnit_Normal;
        unsafe { *self.mValue.mInt.as_mut() = 0; }
    }
    #[inline]
    fn is_normal(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Normal
    }

    #[inline]
    fn set_coord(&mut self, val: Au) {
        self.mUnit = nsStyleUnit::eStyleUnit_Coord;
        unsafe { *self.mValue.mInt.as_mut() = val.0; }
    }
    #[inline]
    fn is_coord(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Coord
    }
    #[inline]
    fn get_coord(&self) -> Au {
        debug_assert!(self.is_coord());
        Au(unsafe { *self.mValue.mInt.as_ref() })
    }

    #[inline]
    fn set_int(&mut self, val: i32) {
        self.mUnit = nsStyleUnit::eStyleUnit_Integer;
        unsafe { *self.mValue.mInt.as_mut() = val; }
    }
    #[inline]
    fn is_int(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Integer
    }
    #[inline]
    fn get_int(&self) -> i32 {
        debug_assert!(self.is_int());
        unsafe { *self.mValue.mInt.as_ref() }
    }

    #[inline]
    fn set_enum(&mut self, val: i32) {
        self.mUnit = nsStyleUnit::eStyleUnit_Enumerated;
        unsafe { *self.mValue.mInt.as_mut() = val; }
    }
    #[inline]
    fn is_enum(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Enumerated
    }
    #[inline]
    fn get_enum(&self) -> i32 {
        debug_assert!(self.is_enum());
        unsafe { *self.mValue.mInt.as_ref() }
    }

    #[inline]
    fn set_percent(&mut self, val: f32) {
        self.mUnit = nsStyleUnit::eStyleUnit_Percent;
        unsafe { *self.mValue.mFloat.as_mut() = val; }
    }
    #[inline]
    fn is_percent(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Percent
    }
    #[inline]
    fn get_percent(&self) -> f32 {
        debug_assert!(self.is_percent());
        unsafe { *self.mValue.mFloat.as_ref() }
    }

    #[inline]
    fn set_factor(&mut self, val: f32) {
        self.mUnit = nsStyleUnit::eStyleUnit_Factor;
        unsafe { *self.mValue.mFloat.as_mut() = val; }
    }
    #[inline]
    fn is_factor(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Factor
    }
    #[inline]
    fn get_factor(&self) -> f32 {
        debug_assert!(self.is_factor());
        unsafe { *self.mValue.mFloat.as_ref() }
    }
}

pub trait GeckoStyleCoordConvertible : Sized {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion);
    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self>;
}

impl GeckoStyleCoordConvertible for LengthOrPercentage {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        match *self {
            LengthOrPercentage::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentage::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentage::Calc(_) => unimplemented!(),
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentage::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentage::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => unimplemented!(),
            _ => None,
        }
    }
}

impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        match *self {
            LengthOrPercentageOrAuto::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentageOrAuto::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentageOrAuto::Auto => {
                *unit = nsStyleUnit::eStyleUnit_Auto;
                unsafe { *union.mInt.as_mut() = 0; }
            },
            LengthOrPercentageOrAuto::Calc(_) => unimplemented!(),
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_Auto
                => Some(LengthOrPercentageOrAuto::Auto),
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentageOrAuto::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentageOrAuto::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => unimplemented!(),
            _ => None,
        }
    }
}

impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        match *self {
            LengthOrPercentageOrNone::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentageOrNone::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentageOrNone::None => {
                *unit = nsStyleUnit::eStyleUnit_None;
                unsafe { *union.mInt.as_mut() = 0; }
            },
            LengthOrPercentageOrNone::Calc(_) => unimplemented!(),
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_None
                => Some(LengthOrPercentageOrNone::None),
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentageOrNone::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentageOrNone::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => unimplemented!(),
            _ => None,
        }
    }
}

impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        if let Some(ref me) = *self {
            me.to_gecko_style_coord(unit, union);
        } else {
            *unit = nsStyleUnit::eStyleUnit_None;
            unsafe { *union.mInt.as_mut() = 0; }
        }
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        Some(T::from_gecko_style_coord(unit, union))
    }
}

impl GeckoStyleCoordConvertible for Angle {
    fn to_gecko_style_coord(&self,
                            unit: &mut nsStyleUnit,
                            union: &mut nsStyleUnion) {
        *unit = nsStyleUnit::eStyleUnit_Radian;
        unsafe { *union.mFloat.as_mut() = self.radians() };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        if *unit == nsStyleUnit::eStyleUnit_Radian {
            Some(Angle::from_radians(unsafe { *union.mFloat.as_ref() }))
        } else {
            None
        }
    }
}

pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
    (((rgba.alpha * 255.0).round() as u32) << 24) |
    (((rgba.blue  * 255.0).round() as u32) << 16) |
    (((rgba.green * 255.0).round() as u32) << 8) |
     ((rgba.red   * 255.0).round() as u32)
}

pub fn convert_nscolor_to_rgba(color: u32) -> RGBA {
    RGBA {
        red:    ((color        & 0xff) as f32) / 255.0,
        green: (((color >>  8) & 0xff) as f32) / 255.0,
        blue:  (((color >> 16) & 0xff) as f32) / 255.0,
        alpha: (((color >> 24) & 0xff) as f32) / 255.0,
    }
}

#[inline]
pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au {
    // Round width down to the nearest device pixel, but any non-zero value that
    // would round down to zero is clamped to 1 device pixel.  Used for storing
    // computed values of border-*-width and outline-width.
    if width == Au(0) {
        Au(0)
    } else {
        max(au_per_device_px, Au(width.0 / au_per_device_px.0 * au_per_device_px.0))
    }
}

pub fn debug_assert_unit_is_safe_to_copy(unit: nsStyleUnit) {
    debug_assert!(unit != nsStyleUnit::eStyleUnit_Calc, "stylo: Can't yet handle refcounted Calc");
}
<commit_msg>Allow calc() in GeckoStyleCoordConvertible<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use cssparser::RGBA;
use gecko_bindings::structs::{nsStyleCoord, nsStyleUnion, nsStyleUnit};
use std::cmp::max;
use style::values::computed::Angle;
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};

pub trait StyleCoordHelpers {
    fn copy_from(&mut self, other: &Self);
    fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T);

    fn set_auto(&mut self);
    fn is_auto(&self) -> bool;

    fn set_normal(&mut self);
    fn is_normal(&self) -> bool;

    fn set_coord(&mut self, val: Au);
    fn is_coord(&self) -> bool;
    fn get_coord(&self) -> Au;

    fn set_int(&mut self, val: i32);
    fn is_int(&self) -> bool;
    fn get_int(&self) -> i32;

    fn set_enum(&mut self, val: i32);
    fn is_enum(&self) -> bool;
    fn get_enum(&self) -> i32;

    fn set_percent(&mut self, val: f32);
    fn is_percent(&self) -> bool;
    fn get_percent(&self) -> f32;

    fn set_factor(&mut self, val: f32);
    fn is_factor(&self) -> bool;
    fn get_factor(&self) -> f32;
}

impl StyleCoordHelpers for nsStyleCoord {
    #[inline]
    fn copy_from(&mut self, other: &Self) {
        debug_assert_unit_is_safe_to_copy(self.mUnit);
        debug_assert_unit_is_safe_to_copy(other.mUnit);
        self.mUnit = other.mUnit;
        self.mValue = other.mValue;
    }

    #[inline]
    fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T) {
        val.to_gecko_style_coord(&mut self.mUnit, &mut self.mValue);
    }

    #[inline]
    fn set_auto(&mut self) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Auto;
        unsafe { *self.mValue.mInt.as_mut() = 0; }
    }
    #[inline]
    fn is_auto(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Auto
    }

    #[inline]
    fn set_normal(&mut self) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Normal;
        unsafe { *self.mValue.mInt.as_mut() = 0; }
    }
    #[inline]
    fn is_normal(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Normal
    }

    #[inline]
    fn set_coord(&mut self, val: Au) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Coord;
        unsafe { *self.mValue.mInt.as_mut() = val.0; }
    }
    #[inline]
    fn is_coord(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Coord
    }
    #[inline]
    fn get_coord(&self) -> Au {
        debug_assert!(self.is_coord());
        Au(unsafe { *self.mValue.mInt.as_ref() })
    }

    #[inline]
    fn set_int(&mut self, val: i32) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Integer;
        unsafe { *self.mValue.mInt.as_mut() = val; }
    }
    #[inline]
    fn is_int(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Integer
    }
    #[inline]
    fn get_int(&self) -> i32 {
        debug_assert!(self.is_int());
        unsafe { *self.mValue.mInt.as_ref() }
    }

    #[inline]
    fn set_enum(&mut self, val: i32) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Enumerated;
        unsafe { *self.mValue.mInt.as_mut() = val; }
    }
    #[inline]
    fn is_enum(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Enumerated
    }
    #[inline]
    fn get_enum(&self) -> i32 {
        debug_assert!(self.is_enum());
        unsafe { *self.mValue.mInt.as_ref() }
    }

    #[inline]
    fn set_percent(&mut self, val: f32) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Percent;
        unsafe { *self.mValue.mFloat.as_mut() = val; }
    }
    #[inline]
    fn is_percent(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Percent
    }
    #[inline]
    fn get_percent(&self) -> f32 {
        debug_assert!(self.is_percent());
        unsafe { *self.mValue.mFloat.as_ref() }
    }

    #[inline]
    fn set_factor(&mut self, val: f32) {
        unsafe { self.mValue.reset(&mut self.mUnit)};
        self.mUnit = nsStyleUnit::eStyleUnit_Factor;
        unsafe { *self.mValue.mFloat.as_mut() = val; }
    }
    #[inline]
    fn is_factor(&self) -> bool {
        self.mUnit == nsStyleUnit::eStyleUnit_Factor
    }
    #[inline]
    fn get_factor(&self) -> f32 {
        debug_assert!(self.is_factor());
        unsafe { *self.mValue.mFloat.as_ref() }
    }
}

pub trait GeckoStyleCoordConvertible : Sized {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion);
    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self>;
}

impl GeckoStyleCoordConvertible for LengthOrPercentage {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        unsafe { union.reset(unit) };
        match *self {
            LengthOrPercentage::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentage::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentage::Calc(calc) => unsafe {union.set_calc_value(unit, calc.into()) },
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentage::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentage::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => Some(LengthOrPercentage::Calc(unsafe { union.get_calc().into()})),
            _ => None,
        }
    }
}

impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        unsafe { union.reset(unit) };
        match *self {
            LengthOrPercentageOrAuto::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentageOrAuto::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentageOrAuto::Auto => {
                *unit = nsStyleUnit::eStyleUnit_Auto;
                unsafe { *union.mInt.as_mut() = 0; }
            },
            LengthOrPercentageOrAuto::Calc(calc) => unsafe {union.set_calc_value(unit, calc.into()) },
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_Auto
                => Some(LengthOrPercentageOrAuto::Auto),
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentageOrAuto::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentageOrAuto::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => Some(LengthOrPercentageOrAuto::Calc(unsafe { union.get_calc().into()})),
            _ => None,
        }
    }
}

impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        unsafe { union.reset(unit) };
        match *self {
            LengthOrPercentageOrNone::Length(au) => {
                *unit = nsStyleUnit::eStyleUnit_Coord;
                unsafe { *union.mInt.as_mut() = au.0; }
            },
            LengthOrPercentageOrNone::Percentage(p) => {
                *unit = nsStyleUnit::eStyleUnit_Percent;
                unsafe { *union.mFloat.as_mut() = p; }
            },
            LengthOrPercentageOrNone::None => {
                *unit = nsStyleUnit::eStyleUnit_None;
                unsafe { *union.mInt.as_mut() = 0; }
            },
            LengthOrPercentageOrNone::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) },
        };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        match *unit {
            nsStyleUnit::eStyleUnit_None
                => Some(LengthOrPercentageOrNone::None),
            nsStyleUnit::eStyleUnit_Coord
                => Some(LengthOrPercentageOrNone::Length(Au(unsafe { *union.mInt.as_ref() }))),
            nsStyleUnit::eStyleUnit_Percent
                => Some(LengthOrPercentageOrNone::Percentage(unsafe { *union.mFloat.as_ref() })),
            nsStyleUnit::eStyleUnit_Calc
                => Some(LengthOrPercentageOrNone::Calc(unsafe { union.get_calc().into()})),
            _ => None,
        }
    }
}

impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> {
    fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
        if let Some(ref me) = *self {
            me.to_gecko_style_coord(unit, union);
        } else {
            *unit = nsStyleUnit::eStyleUnit_None;
            unsafe { *union.mInt.as_mut() = 0; }
        }
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        Some(T::from_gecko_style_coord(unit, union))
    }
}

impl GeckoStyleCoordConvertible for Angle {
    fn to_gecko_style_coord(&self,
                            unit: &mut nsStyleUnit,
                            union: &mut nsStyleUnion) {
        *unit = nsStyleUnit::eStyleUnit_Radian;
        unsafe { *union.mFloat.as_mut() = self.radians() };
    }

    fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
        if *unit == nsStyleUnit::eStyleUnit_Radian {
            Some(Angle::from_radians(unsafe { *union.mFloat.as_ref() }))
        } else {
            None
        }
    }
}

pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
    (((rgba.alpha * 255.0).round() as u32) << 24) |
    (((rgba.blue  * 255.0).round() as u32) << 16) |
    (((rgba.green * 255.0).round() as u32) << 8) |
     ((rgba.red   * 255.0).round() as u32)
}

pub fn convert_nscolor_to_rgba(color: u32) -> RGBA {
    RGBA {
        red:    ((color        & 0xff) as f32) / 255.0,
        green: (((color >>  8) & 0xff) as f32) / 255.0,
        blue:  (((color >> 16) & 0xff) as f32) / 255.0,
        alpha: (((color >> 24) & 0xff) as f32) / 255.0,
    }
}

#[inline]
pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au {
    // Round width down to the nearest device pixel, but any non-zero value that
    // would round down to zero is clamped to 1 device pixel.  Used for storing
    // computed values of border-*-width and outline-width.
    if width == Au(0) {
        Au(0)
    } else {
        max(au_per_device_px, Au(width.0 / au_per_device_px.0 * au_per_device_px.0))
    }
}

pub fn debug_assert_unit_is_safe_to_copy(unit: nsStyleUnit) {
    debug_assert!(unit != nsStyleUnit::eStyleUnit_Calc, "stylo: Can't yet handle refcounted Calc");
}
<|endoftext|>


<commit_before>// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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.

// A simple wrapper around a build_script execution to generate file to reuse
// by rust_library/rust_binary.
extern crate cargo_build_script_output_parser;

use cargo_build_script_output_parser::{BuildScriptOutput, CompileAndLinkFlags};
use std::env;
use std::ffi::OsString;
use std::fs::{create_dir_all, read_to_string, write};
use std::path::Path;
use std::process::Command;

fn main() -> Result<(), String> {
    // We use exec_root.join rather than std::fs::canonicalize, to avoid resolving symlinks, as
    // some execution strategies and remote execution environments may use symlinks in ways which
    // canonicalizing them may break them, e.g. by having input files be symlinks into a /cas
    // directory - resolving these may cause tools which inspect $0, or try to resolve files
    // relative to themselves, to fail.
    let exec_root = env::current_dir().expect("Failed to get current directory");

    let mut args = env::args().skip(1);
    let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set");
    let rustc_env = env::var("RUSTC").expect("RUSTC was not set");
    let manifest_dir = exec_root.join(&manifest_dir_env);
    let rustc = exec_root.join(&rustc_env);

    match (args.next(), args.next(), args.next(), args.next(), args.next(), args.next(), args.next()) {
        (Some(progname), Some(crate_name), Some(out_dir), Some(envfile), Some(flagfile), Some(linkflags), Some(depenvfile)) => {
            let out_dir_abs = exec_root.join(&out_dir);
            // For some reason Google's RBE does not create the output directory, force create it.
            create_dir_all(&out_dir_abs).expect(&format!("Failed to make output directory: {:?}", out_dir_abs));

            let mut command = Command::new(exec_root.join(&progname));
            command
                .current_dir(manifest_dir.clone())
                .env("OUT_DIR", out_dir_abs)
                .env("CARGO_MANIFEST_DIR", manifest_dir)
                .env("RUSTC", rustc)
                .env("RUST_BACKTRACE", "full");

            while let Some(dep_env_path) = args.next() {
                if let Ok(contents) = read_to_string(dep_env_path) {
                    for line in contents.split('\n') {
                        let mut key_val = line.splitn(2, '=');
                        match (key_val.next(), key_val.next()) {
                            (Some(key), Some(value)) => {
                                command.env(key, value);
                            }
                            _ => {
                                return Err("error: Wrong environment file format, should not happen".to_owned())
                            }
                        }
                    }
                } else {
                    return Err("error: Dependency environment file unreadable".to_owned())
                }
            }

            if let Some(cc_path) = env::var_os("CC") {
                command.env("CC", absolutify(&exec_root, cc_path));
            }

            if let Some(ar_path) = env::var_os("AR") {
                // The default OSX toolchain uses libtool as ar_executable not ar.
                // This doesn't work when used as $AR, so simply don't set it - tools will probably fall back to
                // /usr/bin/ar which is probably good enough.
                if Path::new(&ar_path).file_name() == Some("libtool".as_ref()) {
                    command.env_remove("AR");
                } else {
                    command.env("AR", absolutify(&exec_root, ar_path));
                }
            }

            let output = BuildScriptOutput::from_command(&mut command).map_err(|exit_code| {
                format!(
                    "Build script process failed{}",
                    if let Some(exit_code) = exit_code {
                        format!(" with exit code {}", exit_code)
                    } else {
                        String::new()
                    }
                )
            })?;

            write(&envfile, BuildScriptOutput::to_env(&output).as_bytes())
                .expect(&format!("Unable to write file {:?}", envfile));
            write(&depenvfile, BuildScriptOutput::to_dep_env(&output, &crate_name).as_bytes())
                .expect(&format!("Unable to write file {:?}", depenvfile));

            let CompileAndLinkFlags { compile_flags, link_flags } = BuildScriptOutput::to_flags(&output, &exec_root.to_string_lossy());

            write(&flagfile, compile_flags.as_bytes())
                .expect(&format!("Unable to write file {:?}", flagfile));
            write(&linkflags, link_flags.as_bytes())
                .expect(&format!("Unable to write file {:?}", linkflags));
            Ok(())
        }
        _ => {
            Err("Usage: $0 progname crate_name out_dir envfile flagfile linkflagfile depenvfile [arg1...argn]".to_owned())
        }
    }
}

fn absolutify(root: &Path, maybe_relative: OsString) -> OsString {
    let path = Path::new(&maybe_relative);
    if path.is_relative() {
        root.join(path).into_os_string()
    } else {
        maybe_relative
    }
}
<commit_msg>Fix .depenv file parsing after #329 (#367)<commit_after>// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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.

// A simple wrapper around a build_script execution to generate file to reuse
// by rust_library/rust_binary.
extern crate cargo_build_script_output_parser;

use cargo_build_script_output_parser::{BuildScriptOutput, CompileAndLinkFlags};
use std::env;
use std::ffi::OsString;
use std::fs::{create_dir_all, read_to_string, write};
use std::path::Path;
use std::process::Command;

fn main() -> Result<(), String> {
    // We use exec_root.join rather than std::fs::canonicalize, to avoid resolving symlinks, as
    // some execution strategies and remote execution environments may use symlinks in ways which
    // canonicalizing them may break them, e.g. by having input files be symlinks into a /cas
    // directory - resolving these may cause tools which inspect $0, or try to resolve files
    // relative to themselves, to fail.
    let exec_root = env::current_dir().expect("Failed to get current directory");

    let mut args = env::args().skip(1);
    let manifest_dir_env = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR was not set");
    let rustc_env = env::var("RUSTC").expect("RUSTC was not set");
    let manifest_dir = exec_root.join(&manifest_dir_env);
    let rustc = exec_root.join(&rustc_env);

    match (args.next(), args.next(), args.next(), args.next(), args.next(), args.next(), args.next()) {
        (Some(progname), Some(crate_name), Some(out_dir), Some(envfile), Some(flagfile), Some(linkflags), Some(depenvfile)) => {
            let out_dir_abs = exec_root.join(&out_dir);
            // For some reason Google's RBE does not create the output directory, force create it.
            create_dir_all(&out_dir_abs).expect(&format!("Failed to make output directory: {:?}", out_dir_abs));

            let mut command = Command::new(exec_root.join(&progname));
            command
                .current_dir(manifest_dir.clone())
                .env("OUT_DIR", out_dir_abs)
                .env("CARGO_MANIFEST_DIR", manifest_dir)
                .env("RUSTC", rustc)
                .env("RUST_BACKTRACE", "full");

            while let Some(dep_env_path) = args.next() {
                if let Ok(contents) = read_to_string(dep_env_path) {
                    for line in contents.split('\n') {
                        // split on empty contents will still produce a single empty string in iterable.
                        if line.is_empty() {
                            continue;
                        }
                        let mut key_val = line.splitn(2, '=');
                        match (key_val.next(), key_val.next()) {
                            (Some(key), Some(value)) => {
                                command.env(key, value);
                            }
                            _ => {
                                return Err("error: Wrong environment file format, should not happen".to_owned())
                            }
                        }
                    }
                } else {
                    return Err("error: Dependency environment file unreadable".to_owned())
                }
            }

            if let Some(cc_path) = env::var_os("CC") {
                command.env("CC", absolutify(&exec_root, cc_path));
            }

            if let Some(ar_path) = env::var_os("AR") {
                // The default OSX toolchain uses libtool as ar_executable not ar.
                // This doesn't work when used as $AR, so simply don't set it - tools will probably fall back to
                // /usr/bin/ar which is probably good enough.
                if Path::new(&ar_path).file_name() == Some("libtool".as_ref()) {
                    command.env_remove("AR");
                } else {
                    command.env("AR", absolutify(&exec_root, ar_path));
                }
            }

            let output = BuildScriptOutput::from_command(&mut command).map_err(|exit_code| {
                format!(
                    "Build script process failed{}",
                    if let Some(exit_code) = exit_code {
                        format!(" with exit code {}", exit_code)
                    } else {
                        String::new()
                    }
                )
            })?;

            write(&envfile, BuildScriptOutput::to_env(&output).as_bytes())
                .expect(&format!("Unable to write file {:?}", envfile));
            write(&depenvfile, BuildScriptOutput::to_dep_env(&output, &crate_name).as_bytes())
                .expect(&format!("Unable to write file {:?}", depenvfile));

            let CompileAndLinkFlags { compile_flags, link_flags } = BuildScriptOutput::to_flags(&output, &exec_root.to_string_lossy());

            write(&flagfile, compile_flags.as_bytes())
                .expect(&format!("Unable to write file {:?}", flagfile));
            write(&linkflags, link_flags.as_bytes())
                .expect(&format!("Unable to write file {:?}", linkflags));
            Ok(())
        }
        _ => {
            Err("Usage: $0 progname crate_name out_dir envfile flagfile linkflagfile depenvfile [arg1...argn]".to_owned())
        }
    }
}

fn absolutify(root: &Path, maybe_relative: OsString) -> OsString {
    let path = Path::new(&maybe_relative);
    if path.is_relative() {
        root.join(path).into_os_string()
    } else {
        maybe_relative
    }
}
<|endoftext|>