<commit_before>use crate::{
    backend::renderer::{Frame, ImportAll, Renderer, Texture},
    desktop::{space::*, utils::*},
    utils::{Logical, Point, Rectangle},
    wayland::output::Output,
};
use std::{
    any::{Any, TypeId},
    hash::{Hash, Hasher},
};
use wayland_server::protocol::wl_surface::WlSurface;

/// Trait for custom elements to be rendered during [`Space::render_output`].
pub trait RenderElement<R, F, E, T>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture + 'static,
    Self: Any + 'static,
{
    /// Returns an id unique to this element for the type of Self.
    fn id(&self) -> usize;
    #[doc(hidden)]
    fn type_of(&self) -> TypeId {
        std::any::Any::type_id(self)
    }
    /// Returns the bounding box of this element including its position in the space.
    fn geometry(&self) -> Rectangle<i32, Logical>;
    /// Returns the damage of the element since it's last update.
    /// It should be relative to the elements coordinates.
    ///
    /// If you receive `Some(_)` for `for_values` you may cache that you
    /// send the damage for this `Space` and `Output` combination once
    /// and return an empty vector for subsequent calls until the contents
    /// of this element actually change again for optimization reasons.
    ///
    /// Returning `vec![Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX))]` is always
    /// correct, but very inefficient.
    fn accumulated_damage(
        &self,
        for_values: Option<SpaceOutputTuple<'_, '_>>,
    ) -> Vec<Rectangle<i32, Logical>>;
    /// Draws the element using the provided `Frame` and `Renderer`.
    ///
    /// - `scale` provides the current fractional scale value to render as
    /// - `damage` provides the regions you need to re-draw and *may* not
    ///   be equivalent to the damage returned by `accumulated_damage`.
    ///   Redrawing other parts of the element is not valid and may cause rendering artifacts.
    fn draw(
        &self,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error>;
}

pub(crate) trait SpaceElement<R, F, E, T>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture,
{
    fn id(&self) -> usize;
    fn type_of(&self) -> TypeId;
    fn location(&self, space_id: usize) -> Point<i32, Logical> {
        self.geometry(space_id).loc
    }
    fn geometry(&self, space_id: usize) -> Rectangle<i32, Logical>;
    fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>>;
    #[allow(clippy::too_many_arguments)]
    fn draw(
        &self,
        space_id: usize,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error>;
}

impl<R, F, E, T> SpaceElement<R, F, E, T> for Box<dyn RenderElement<R, F, E, T>>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
    F: Frame<Error = E, TextureId = T> + 'static,
    E: std::error::Error + 'static,
    T: Texture + 'static,
{
    fn id(&self) -> usize {
        (&**self as &dyn RenderElement<R, F, E, T>).id()
    }
    fn type_of(&self) -> TypeId {
        (&**self as &dyn RenderElement<R, F, E, T>).type_of()
    }
    fn geometry(&self, _space_id: usize) -> Rectangle<i32, Logical> {
        (&**self as &dyn RenderElement<R, F, E, T>).geometry()
    }
    fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
        (&**self as &dyn RenderElement<R, F, E, T>).accumulated_damage(for_values.map(SpaceOutputTuple::from))
    }
    fn draw(
        &self,
        _space_id: usize,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        _location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error> {
        (&**self as &dyn RenderElement<R, F, E, T>).draw(renderer, frame, scale, damage, log)
    }
}

/// Generic helper for drawing [`WlSurface`]s and their subsurfaces
/// as custom elements via [`RenderElement`].
///
/// For example useful for cursor or drag-and-drop surfaces.
///
/// Note: This element will render nothing, if you are not using
/// [`crate::backend::renderer::utils::on_commit_buffer_handler`]
/// to let smithay handle buffer management.
#[derive(Debug)]
pub struct SurfaceTree {
    /// Surface to be drawn
    pub surface: WlSurface,
    /// Position to draw add
    pub position: Point<i32, Logical>,
}

impl<R, F, E, T> RenderElement<R, F, E, T> for SurfaceTree
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture + 'static,
{
    fn id(&self) -> usize {
        self.surface.as_ref().id() as usize
    }

    fn geometry(&self) -> Rectangle<i32, Logical> {
        let mut bbox = bbox_from_surface_tree(&self.surface, (0, 0));
        bbox.loc += self.position;
        bbox
    }

    fn accumulated_damage(
        &self,
        for_values: Option<SpaceOutputTuple<'_, '_>>,
    ) -> Vec<Rectangle<i32, Logical>> {
        damage_from_surface_tree(&self.surface, (0, 0), for_values.map(|x| (x.0, x.1)))
    }

    fn draw(
        &self,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error> {
        crate::backend::renderer::utils::draw_surface_tree(
            renderer,
            frame,
            &self.surface,
            scale,
            self.position,
            damage,
            log,
        )
    }
}

/// Newtype for (&Space, &Output) to provide a `Hash` implementation for damage tracking
#[derive(Debug, PartialEq)]
pub struct SpaceOutputTuple<'a, 'b>(pub &'a Space, pub &'b Output);

impl<'a, 'b> Hash for SpaceOutputTuple<'a, 'b> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.id.hash(state);
        (std::sync::Arc::as_ptr(&self.1.inner) as *const () as usize).hash(state);
    }
}

impl<'a, 'b> SpaceOutputTuple<'a, 'b> {
    /// Returns an owned version that produces and equivalent hash
    pub fn owned_hash(&self) -> SpaceOutputHash {
        SpaceOutputHash(
            self.0.id,
            std::sync::Arc::as_ptr(&self.1.inner) as *const () as usize,
        )
    }
}

impl<'a, 'b> From<(&'a Space, &'b Output)> for SpaceOutputTuple<'a, 'b> {
    fn from((space, output): (&'a Space, &'b Output)) -> SpaceOutputTuple<'a, 'b> {
        SpaceOutputTuple(space, output)
    }
}

/// Type to use as an owned hashable value equal to [`SpaceOutputTuple`]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct SpaceOutputHash(usize, usize);
<commit_msg>space: Pass a location to `RenderElement::draw`<commit_after>use crate::{
    backend::renderer::{Frame, ImportAll, Renderer, Texture},
    desktop::{space::*, utils::*},
    utils::{Logical, Point, Rectangle},
    wayland::output::Output,
};
use std::{
    any::{Any, TypeId},
    hash::{Hash, Hasher},
};
use wayland_server::protocol::wl_surface::WlSurface;

/// Trait for custom elements to be rendered during [`Space::render_output`].
pub trait RenderElement<R, F, E, T>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture + 'static,
    Self: Any + 'static,
{
    /// Returns an id unique to this element for the type of Self.
    fn id(&self) -> usize;
    #[doc(hidden)]
    fn type_of(&self) -> TypeId {
        std::any::Any::type_id(self)
    }
    /// Returns the bounding box of this element including its position in the space.
    fn geometry(&self) -> Rectangle<i32, Logical>;
    /// Returns the damage of the element since it's last update.
    /// It should be relative to the elements coordinates.
    ///
    /// If you receive `Some(_)` for `for_values` you may cache that you
    /// send the damage for this `Space` and `Output` combination once
    /// and return an empty vector for subsequent calls until the contents
    /// of this element actually change again for optimization reasons.
    ///
    /// Returning `vec![Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX))]` is always
    /// correct, but very inefficient.
    fn accumulated_damage(
        &self,
        for_values: Option<SpaceOutputTuple<'_, '_>>,
    ) -> Vec<Rectangle<i32, Logical>>;
    /// Draws the element using the provided `Frame` and `Renderer`.
    ///
    /// - `scale` provides the current fractional scale value to render as
    /// - `location` refers to the relative position in the bound buffer the element should be drawn at,
    ///    so that it matches with the space-relative coordinates returned by [`RenderElement::geometry`].
    /// - `damage` provides the regions you need to re-draw and *may* not
    ///   be equivalent to the damage returned by `accumulated_damage`.
    ///   Redrawing other parts of the element is not valid and may cause rendering artifacts.
    fn draw(
        &self,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error>;
}

pub(crate) trait SpaceElement<R, F, E, T>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture,
{
    fn id(&self) -> usize;
    fn type_of(&self) -> TypeId;
    fn location(&self, space_id: usize) -> Point<i32, Logical> {
        self.geometry(space_id).loc
    }
    fn geometry(&self, space_id: usize) -> Rectangle<i32, Logical>;
    fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>>;
    #[allow(clippy::too_many_arguments)]
    fn draw(
        &self,
        space_id: usize,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error>;
}

impl<R, F, E, T> SpaceElement<R, F, E, T> for Box<dyn RenderElement<R, F, E, T>>
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
    F: Frame<Error = E, TextureId = T> + 'static,
    E: std::error::Error + 'static,
    T: Texture + 'static,
{
    fn id(&self) -> usize {
        (&**self as &dyn RenderElement<R, F, E, T>).id()
    }
    fn type_of(&self) -> TypeId {
        (&**self as &dyn RenderElement<R, F, E, T>).type_of()
    }
    fn geometry(&self, _space_id: usize) -> Rectangle<i32, Logical> {
        (&**self as &dyn RenderElement<R, F, E, T>).geometry()
    }
    fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
        (&**self as &dyn RenderElement<R, F, E, T>).accumulated_damage(for_values.map(SpaceOutputTuple::from))
    }
    fn draw(
        &self,
        _space_id: usize,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error> {
        (&**self as &dyn RenderElement<R, F, E, T>).draw(renderer, frame, scale, location, damage, log)
    }
}

/// Generic helper for drawing [`WlSurface`]s and their subsurfaces
/// as custom elements via [`RenderElement`].
///
/// For example useful for cursor or drag-and-drop surfaces.
///
/// Note: This element will render nothing, if you are not using
/// [`crate::backend::renderer::utils::on_commit_buffer_handler`]
/// to let smithay handle buffer management.
#[derive(Debug)]
pub struct SurfaceTree {
    /// Surface to be drawn
    pub surface: WlSurface,
    /// Position to draw add
    pub position: Point<i32, Logical>,
}

impl<R, F, E, T> RenderElement<R, F, E, T> for SurfaceTree
where
    R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
    F: Frame<Error = E, TextureId = T>,
    E: std::error::Error,
    T: Texture + 'static,
{
    fn id(&self) -> usize {
        self.surface.as_ref().id() as usize
    }

    fn geometry(&self) -> Rectangle<i32, Logical> {
        let mut bbox = bbox_from_surface_tree(&self.surface, (0, 0));
        bbox.loc += self.position;
        bbox
    }

    fn accumulated_damage(
        &self,
        for_values: Option<SpaceOutputTuple<'_, '_>>,
    ) -> Vec<Rectangle<i32, Logical>> {
        damage_from_surface_tree(&self.surface, (0, 0), for_values.map(|x| (x.0, x.1)))
    }

    fn draw(
        &self,
        renderer: &mut R,
        frame: &mut F,
        scale: f64,
        location: Point<i32, Logical>,
        damage: &[Rectangle<i32, Logical>],
        log: &slog::Logger,
    ) -> Result<(), R::Error> {
        crate::backend::renderer::utils::draw_surface_tree(
            renderer,
            frame,
            &self.surface,
            scale,
            location,
            damage,
            log,
        )
    }
}

/// Newtype for (&Space, &Output) to provide a `Hash` implementation for damage tracking
#[derive(Debug, PartialEq)]
pub struct SpaceOutputTuple<'a, 'b>(pub &'a Space, pub &'b Output);

impl<'a, 'b> Hash for SpaceOutputTuple<'a, 'b> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.id.hash(state);
        (std::sync::Arc::as_ptr(&self.1.inner) as *const () as usize).hash(state);
    }
}

impl<'a, 'b> SpaceOutputTuple<'a, 'b> {
    /// Returns an owned version that produces and equivalent hash
    pub fn owned_hash(&self) -> SpaceOutputHash {
        SpaceOutputHash(
            self.0.id,
            std::sync::Arc::as_ptr(&self.1.inner) as *const () as usize,
        )
    }
}

impl<'a, 'b> From<(&'a Space, &'b Output)> for SpaceOutputTuple<'a, 'b> {
    fn from((space, output): (&'a Space, &'b Output)) -> SpaceOutputTuple<'a, 'b> {
        SpaceOutputTuple(space, output)
    }
}

/// Type to use as an owned hashable value equal to [`SpaceOutputTuple`]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct SpaceOutputHash(usize, usize);
<|endoftext|>


<commit_before>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, ListedType, SubListRepresentative, GlobalListConscious};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    impl <GlobalList: SubList> GlobalListConscious for Representative <GlobalList> {
      type GlobalList = GlobalList;
    }
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count()
      }
      fn count_before<T>()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count_before::<T>()
      }
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub trait GlobalListConscious {
  type GlobalList: List;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn count_before<T>()->usize;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

#[macro_export]
macro_rules! time_steward_visit_sublist {
  (&mut $object: ident: $Object: ty, <$GlobalList: ident as $mod: ident::SubList>, $($method: tt)*) => {
    impl $mod::Visitor for $Object {
      $($method)*
    }
    <$GlobalList as $mod::SubList>::visit_all (&mut $object);
  }
}
#[macro_export]
macro_rules! time_steward_with_sublist_table {
  (<$GlobalList: ident as $mod: ident::SubList>, Vec<$Entry: ty> [$T: ident => {$entry: expr} where $($where: tt)*], | $table: ident | $($closure: tt)*) => {{
    assert_unique_global_list::<$GlobalList>();
    use std::cell::RefCell;
    use std::mem;
    thread_local! {
      static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
    }
    TABLE.with (| table | {
      let mut guard = table.borrow_mut();
      if guard.is_empty() {
        mem::replace (&mut*guard, {
          let mut result = Vec::with_capacity($mod::Representative::<$GlobalList>::count());
          time_steward_visit_sublist! (
            &mut result: Vec<$Entry>,
            <$GlobalList as $mod::SubList>,
            fn visit<$T>(&mut self) where $($where)* {self.push ($entry);}
          );
          result
        });
      }
      let $table = &*guard;
      $($closure)*
    })
  }}
}

use std::any::Any ;

fn index_to_id <GlobalList: whatever::SubList> (index: usize)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  time_steward_with_sublist_table! (
    <GlobalList as whatever::SubList>,
    Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {T::ID} where T: DeterministicallyRandomlyIdentifiedType],
    | table | table.get (index).cloned()
  )
}

#[macro_export]
macro_rules! time_steward_dynamic_sublist_fn {
  (fn $function_name: ident <GlobalList as $mod: ident::SubList> (index: usize)->{$inner_function: ident::<Type(index)> ($($arguments: tt)*)->$Return:ty} where $($where: tt)*) => {
    fn $function_name <GlobalList: $mod::SubList> (index: usize)->fn ($($arguments)*)->$Return {
      time_steward_with_sublist_table! (
        <GlobalList as whatever::SubList>,
        Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {$inner_function::<T>} where $($where)*],
        | table | *table.get (index).expect("invoked dynamic sublist fn with an invalid index")
      )
    }
  }
}

<commit_msg>Started making listed type indexes a separate thing so that I can make them specific to the sublist type and support serialization<commit_after>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct ListedTypeIndex (usize);

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, ListedType, SubListRepresentative, GlobalListConscious};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    impl <GlobalList: SubList> GlobalListConscious for Representative <GlobalList> {
      type GlobalList = GlobalList;
    }
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count()
      }
      fn index<T>()->$crate::dynamic::list_of_types::ListedTypeIndex {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        $crate::dynamic::list_of_types::ListedTypeIndex(GlobalList::count_before::<T>())
      }
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        // note: visiting order must be the same as the order of count_before()
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        // note: visiting order must be the same as the order of count_before()
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub trait GlobalListConscious {
  type GlobalList: List;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn index<T>()->ListedTypeIndex;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

#[macro_export]
macro_rules! time_steward_visit_sublist {
  (&mut $object: ident: $Object: ty, <$GlobalList: ident as $mod: ident::SubList>, $($method: tt)*) => {
    impl $mod::Visitor for $Object {
      $($method)*
    }
    <$GlobalList as $mod::SubList>::visit_all (&mut $object);
  }
}
#[macro_export]
macro_rules! time_steward_with_sublist_table_entry {
  (<$GlobalList: ident as $mod: ident::SubList>, Vec<$Entry: ty> [$T: ident => {$entry: expr} where $($where: tt)*] [$index: expr], | $entry_variable: ident | $($closure: tt)*) => {{
    assert_unique_global_list::<$GlobalList>();
    use std::cell::RefCell;
    use std::mem;
    thread_local! {
      static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
    }
    TABLE.with (| table | {
      let mut guard = table.borrow_mut();
      if guard.is_empty() {
        mem::replace (&mut*guard, {
          let mut result = Vec::with_capacity($mod::Representative::<$GlobalList>::count());
          time_steward_visit_sublist! (
            &mut result: Vec<$Entry>,
            <$GlobalList as $mod::SubList>,
            fn visit<$T>(&mut self) where $($where)* {self.push ($entry);}
          );
          result
        });
      }
      let $entry_variable = guard.get ($index.0);
      $($closure)*
    })
  }}
}

use std::any::Any ;

fn index_to_id <GlobalList: whatever::SubList> (index: ListedTypeIndex)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  time_steward_with_sublist_table_entry! (
    <GlobalList as whatever::SubList>,
    Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {T::ID} where T: DeterministicallyRandomlyIdentifiedType] [index],
    | entry | entry.cloned()
  )
}

#[macro_export]
macro_rules! time_steward_dynamic_sublist_fn {
  (fn $function_name: ident <GlobalList as $mod: ident::SubList> (index: ListedTypeIndex)->{$inner_function: ident::<Type(index)> ($($arguments: tt)*)->$Return:ty} where $($where: tt)*) => {
    fn $function_name <GlobalList: $mod::SubList> (index: ListedTypeIndex)->fn ($($arguments)*)->$Return {
      time_steward_with_sublist_table_entry! (
        <GlobalList as whatever::SubList>,
        Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {$inner_function::<T>} where $($where)*] [index],
        | entry | *entry.expect("invoked dynamic sublist fn with an invalid index")
      )
    }
  }
}

<|endoftext|>


<commit_before>/// Compute the display width of `text`
///
/// # Examples
///
/// **Note:** When the `unicode` Cargo feature is disabled, all characters are presumed to take up
/// 1 width.  With the feature enabled, function will correctly deal with [combining characters] in
/// their decomposed form (see [Unicode equivalence]).
///
/// An example of a decomposed character is “é”, which can be decomposed into: “e” followed by a
/// combining acute accent: “◌́”.  Without the `unicode` Cargo feature, every `char` has a width of
/// 1. This includes the combining accent:
///
/// ## Emojis and CJK Characters
///
/// Characters such as emojis and [CJK characters] used in the
/// Chinese, Japanese, and Korean languages are seen as double-width,
/// even if the `unicode-width` feature is disabled:
///
/// # Limitations
///
/// The displayed width of a string cannot always be computed from the
/// string alone. This is because the width depends on the rendering
/// engine used. This is particularly visible with [emoji modifier
/// sequences] where a base emoji is modified with, e.g., skin tone or
/// hair color modifiers. It is up to the rendering engine to detect
/// this and to produce a suitable emoji.
///
/// A simple example is “❤”, which consists of “❤” (U+2764: Black
/// Heart Symbol) followed by U+FE0F (Variation Selector-16). By
/// itself, “❤” is a black heart, but if you follow it with the
/// variant selector, you may get a wider red heart.
///
/// A more complex example would be “👨🦰” which should depict a man
/// with red hair. Here the computed width is too large — and the
/// width differs depending on the use of the `unicode-width` feature:
///
/// This happens because the grapheme consists of three code points:
/// “👨” (U+1F468: Man), Zero Width Joiner (U+200D), and “🦰”
/// (U+1F9B0: Red Hair). You can see them above in the test. With
/// `unicode-width` enabled, the ZWJ is correctly seen as having zero
/// width, without it is counted as a double-width character.
///
/// ## Terminal Support
///
/// Modern browsers typically do a great job at combining characters
/// as shown above, but terminals often struggle more. As an example,
/// Gnome Terminal version 3.38.1, shows “❤” as a big red heart, but
/// shows "👨🦰" as “👨🦰”.
///
/// [combining characters]: https://en.wikipedia.org/wiki/Combining_character
/// [Unicode equivalence]: https://en.wikipedia.org/wiki/Unicode_equivalence
/// [CJK characters]: https://en.wikipedia.org/wiki/CJK_characters
/// [emoji modifier sequences]: https://unicode.org/emoji/charts/full-emoji-modifiers.html
#[inline(never)]
pub(crate) fn display_width(text: &str) -> usize {
    let mut width = 0;

    let mut control_sequence = false;
    let control_terminate: char = 'm';

    for ch in text.chars() {
        if ch.is_ascii_control() {
            control_sequence = true;
        } else if control_sequence && ch == control_terminate {
            control_sequence = false;
        }

        if !control_sequence {
            width += ch_width(ch);
        }
    }
    width
}

#[cfg(feature = "unicode")]
fn ch_width(ch: char) -> usize {
    unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
}

#[cfg(not(feature = "unicode"))]
fn ch_width(_: char) -> usize {
    1
}

#[cfg(test)]
mod tests {
    use super::*;

    #[cfg(feature = "unicode")]
    use unicode_width::UnicodeWidthChar;

    #[test]
    fn emojis_have_correct_width() {
        use unic_emoji_char::is_emoji;

        // Emojis in the Basic Latin (ASCII) and Latin-1 Supplement
        // blocks all have a width of 1 column. This includes
        // characters such as '#' and '©'.
        for ch in '\u{1}'..'\u{FF}' {
            if is_emoji(ch) {
                let desc = format!("{:?} U+{:04X}", ch, ch as u32);

                #[cfg(feature = "unicode")]
                assert_eq!(ch.width().unwrap(), 1, "char: {}", desc);

                #[cfg(not(feature = "unicode"))]
                assert_eq!(ch_width(ch), 1, "char: {}", desc);
            }
        }

        // Emojis in the remaining blocks of the Basic Multilingual
        // Plane (BMP), in the Supplementary Multilingual Plane (SMP),
        // and in the Supplementary Ideographic Plane (SIP), are all 1
        // or 2 columns wide when unicode-width is used, and always 2
        // columns wide otherwise. This includes all of our favorite
        // emojis such as 😊.
        for ch in '\u{FF}'..'\u{2FFFF}' {
            if is_emoji(ch) {
                let desc = format!("{:?} U+{:04X}", ch, ch as u32);

                #[cfg(feature = "unicode")]
                assert!(ch.width().unwrap() <= 2, "char: {}", desc);

                #[cfg(not(feature = "unicode"))]
                assert_eq!(ch_width(ch), 1, "char: {}", desc);
            }
        }

        // The remaining planes contain almost no assigned code points
        // and thus also no emojis.
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_works() {
        assert_eq!("Café Plain".len(), 11); // “é” is two bytes
        assert_eq!(display_width("Café Plain"), 10);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_narrow_emojis() {
        assert_eq!(display_width("⁉"), 1);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_narrow_emojis_variant_selector() {
        assert_eq!(display_width("⁉\u{fe0f}"), 1);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_emojis() {
        assert_eq!(display_width("😂😭🥺🤣✨😍🙏🥰😊🔥"), 20);
    }
}
<commit_msg>fix(clap): Early line wrap ascii control chars<commit_after>/// Compute the display width of `text`
///
/// # Examples
///
/// **Note:** When the `unicode` Cargo feature is disabled, all characters are presumed to take up
/// 1 width.  With the feature enabled, function will correctly deal with [combining characters] in
/// their decomposed form (see [Unicode equivalence]).
///
/// An example of a decomposed character is “é”, which can be decomposed into: “e” followed by a
/// combining acute accent: “◌́”.  Without the `unicode` Cargo feature, every `char` has a width of
/// 1. This includes the combining accent:
///
/// ## Emojis and CJK Characters
///
/// Characters such as emojis and [CJK characters] used in the
/// Chinese, Japanese, and Korean languages are seen as double-width,
/// even if the `unicode-width` feature is disabled:
///
/// # Limitations
///
/// The displayed width of a string cannot always be computed from the
/// string alone. This is because the width depends on the rendering
/// engine used. This is particularly visible with [emoji modifier
/// sequences] where a base emoji is modified with, e.g., skin tone or
/// hair color modifiers. It is up to the rendering engine to detect
/// this and to produce a suitable emoji.
///
/// A simple example is “❤”, which consists of “❤” (U+2764: Black
/// Heart Symbol) followed by U+FE0F (Variation Selector-16). By
/// itself, “❤” is a black heart, but if you follow it with the
/// variant selector, you may get a wider red heart.
///
/// A more complex example would be “👨🦰” which should depict a man
/// with red hair. Here the computed width is too large — and the
/// width differs depending on the use of the `unicode-width` feature:
///
/// This happens because the grapheme consists of three code points:
/// “👨” (U+1F468: Man), Zero Width Joiner (U+200D), and “🦰”
/// (U+1F9B0: Red Hair). You can see them above in the test. With
/// `unicode-width` enabled, the ZWJ is correctly seen as having zero
/// width, without it is counted as a double-width character.
///
/// ## Terminal Support
///
/// Modern browsers typically do a great job at combining characters
/// as shown above, but terminals often struggle more. As an example,
/// Gnome Terminal version 3.38.1, shows “❤” as a big red heart, but
/// shows "👨🦰" as “👨🦰”.
///
/// [combining characters]: https://en.wikipedia.org/wiki/Combining_character
/// [Unicode equivalence]: https://en.wikipedia.org/wiki/Unicode_equivalence
/// [CJK characters]: https://en.wikipedia.org/wiki/CJK_characters
/// [emoji modifier sequences]: https://unicode.org/emoji/charts/full-emoji-modifiers.html
#[inline(never)]
pub(crate) fn display_width(text: &str) -> usize {
    let mut width = 0;

    let mut control_sequence = false;
    let control_terminate: char = 'm';

    for ch in text.chars() {
        if ch.is_ascii_control() {
            control_sequence = true;
        } else if control_sequence && ch == control_terminate {
            control_sequence = false;
            continue;
        }

        if !control_sequence {
            width += ch_width(ch);
        }
    }
    width
}

#[cfg(feature = "unicode")]
fn ch_width(ch: char) -> usize {
    unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
}

#[cfg(not(feature = "unicode"))]
fn ch_width(_: char) -> usize {
    1
}

#[cfg(test)]
mod tests {
    use super::*;

    #[cfg(feature = "unicode")]
    use unicode_width::UnicodeWidthChar;

    #[test]
    fn emojis_have_correct_width() {
        use unic_emoji_char::is_emoji;

        // Emojis in the Basic Latin (ASCII) and Latin-1 Supplement
        // blocks all have a width of 1 column. This includes
        // characters such as '#' and '©'.
        for ch in '\u{1}'..'\u{FF}' {
            if is_emoji(ch) {
                let desc = format!("{:?} U+{:04X}", ch, ch as u32);

                #[cfg(feature = "unicode")]
                assert_eq!(ch.width().unwrap(), 1, "char: {}", desc);

                #[cfg(not(feature = "unicode"))]
                assert_eq!(ch_width(ch), 1, "char: {}", desc);
            }
        }

        // Emojis in the remaining blocks of the Basic Multilingual
        // Plane (BMP), in the Supplementary Multilingual Plane (SMP),
        // and in the Supplementary Ideographic Plane (SIP), are all 1
        // or 2 columns wide when unicode-width is used, and always 2
        // columns wide otherwise. This includes all of our favorite
        // emojis such as 😊.
        for ch in '\u{FF}'..'\u{2FFFF}' {
            if is_emoji(ch) {
                let desc = format!("{:?} U+{:04X}", ch, ch as u32);

                #[cfg(feature = "unicode")]
                assert!(ch.width().unwrap() <= 2, "char: {}", desc);

                #[cfg(not(feature = "unicode"))]
                assert_eq!(ch_width(ch), 1, "char: {}", desc);
            }
        }

        // The remaining planes contain almost no assigned code points
        // and thus also no emojis.
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_works() {
        assert_eq!("Café Plain".len(), 11); // “é” is two bytes
        assert_eq!(display_width("Café Plain"), 10);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_narrow_emojis() {
        assert_eq!(display_width("⁉"), 1);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_narrow_emojis_variant_selector() {
        assert_eq!(display_width("⁉\u{fe0f}"), 1);
    }

    #[test]
    #[cfg(feature = "unicode")]
    fn display_width_emojis() {
        assert_eq!(display_width("😂😭🥺🤣✨😍🙏🥰😊🔥"), 20);
    }
}
<|endoftext|>


<commit_before>
extern crate image;
extern crate texture_packer;

use std::io::File;

use texture_packer::{
    ColorType,
    ImageBuffer,
    Packer,
    ShelfPacker,
    GuillotinePacker,
    MaxrectPacker,
    SkylinePacker,
};

static OUTPUT_IMAGE_WIDTH: u32 = 400;
static OUTPUT_IMAGE_HEIGHT: u32 = 400;

fn pack(packer: &mut Packer<ImageBuffer>, output_filename: &str) {
    for i in range(1u32, 11) {
        let mut filename = String::from_str("./assets/");
        filename.push_str(format!("{}.png", i).as_slice());
        let image = ImageBuffer::open(&Path::new(filename)).unwrap();

        packer.set_margin(1);
        packer.pack(&image);
    }

    let fout = File::create(&Path::new(output_filename)).unwrap();
    let _ = packer.buf().image().save(fout, image::PNG);
}

fn main() {
    pack(&mut ShelfPacker::new(ImageBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "shelf-packer-output.png");
    pack(&mut GuillotinePacker::new(ImageBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "guillotine-packer-output.png");
    pack(&mut MaxrectPacker::new(ImageBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "maxrect-packer-output.png");
    pack(&mut SkylinePacker::new(ImageBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "skyline-packer-output.png");
}

<commit_msg>Upgraded examples<commit_after>
extern crate image;
extern crate texture_packer;

use std::io::File;

use texture_packer::{
    ColorType,
    ImgBuffer,
    Packer,
    ShelfPacker,
    GuillotinePacker,
    MaxrectPacker,
    SkylinePacker,
};

static OUTPUT_IMAGE_WIDTH: u32 = 400;
static OUTPUT_IMAGE_HEIGHT: u32 = 400;

fn pack(packer: &mut Packer<ImgBuffer>, output_filename: &str) {
    for i in range(1u32, 11) {
        let mut filename = String::from_str("./assets/");
        filename.push_str(format!("{}.png", i).as_slice());
        let image = ImgBuffer::open(&Path::new(filename)).unwrap();

        packer.set_margin(1);
        packer.pack(&image);
    }

    let fout = File::create(&Path::new(output_filename)).unwrap();
    let _ = packer.buf().image().save(fout, image::PNG);
}

fn main() {
    pack(&mut ShelfPacker::new(ImgBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "shelf-packer-output.png");
    pack(&mut GuillotinePacker::new(ImgBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "guillotine-packer-output.png");
    pack(&mut MaxrectPacker::new(ImgBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "maxrect-packer-output.png");
    pack(&mut SkylinePacker::new(ImgBuffer::new(OUTPUT_IMAGE_WIDTH, OUTPUT_IMAGE_HEIGHT, ColorType::RGBA)), "skyline-packer-output.png");
}

<|endoftext|>


<commit_before>use std::ops::Mul;

#[derive(Clone, Copy, Debug)]
pub enum Span {
    Null,
    Finite(usize),
    Infinite,
}

impl Mul for Span {
    type Output = Span;

    fn mul(self, rhs: Span) -> Span {
        match self {
            Span::Null => rhs,
            Span::Infinite => self,
            Span::Finite(ls) => {
                match rhs {
                    Span::Null => self,
                    Span::Infinite => rhs,
                    Span::Finite(rs) => Span::Finite(ls * rs),
                }
            }
        }
    }
}

impl Into<usize> for Span {
    fn into(self) -> usize {
        match self {
            Span::Finite(e) => e,
            _ => panic!("Span type has no integer representation.")
        }
    }
}
<commit_msg>Added tests for Span enum<commit_after>use std::ops::Mul;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Span {
    Null,
    Finite(usize),
    Infinite,
}

impl Mul for Span {
    type Output = Span;

    fn mul(self, rhs: Span) -> Span {
        match self {
            Span::Null => rhs,
            Span::Infinite => self,
            Span::Finite(ls) => {
                match rhs {
                    Span::Null => self,
                    Span::Infinite => rhs,
                    Span::Finite(rs) => Span::Finite(ls * rs),
                }
            }
        }
    }
}

impl Into<usize> for Span {
    fn into(self) -> usize {
        match self {
            Span::Finite(e) => e,
            _ => panic!("Span type has no integer representation.")
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Span;

    #[test]
    fn test_equality() {
        assert_eq!(Span::Null, Span::Null);
        assert_eq!(Span::Infinite, Span::Infinite);

        assert_eq!(Span::Finite(1), Span::Finite(1));
        assert_eq!(Span::Finite(5), Span::Finite(5));
        assert_eq!(Span::Finite(10), Span::Finite(10));
    }

    #[test]
    fn test_inequality() {
        assert_ne!(Span::Null, Span::Infinite);
        assert_ne!(Span::Null, Span::Finite(1));

        assert_ne!(Span::Infinite, Span::Null);
        assert_ne!(Span::Infinite, Span::Finite(1));

        assert_ne!(Span::Finite(1), Span::Null);
        assert_ne!(Span::Finite(1), Span::Infinite);
        assert_ne!(Span::Finite(1), Span::Finite(10));
    }

    #[test]
    fn test_mul() {
        assert_eq!(Span::Null * Span::Null, Span::Null);
        assert_eq!(Span::Infinite * Span::Infinite, Span::Infinite);

        assert_eq!(Span::Null * Span::Infinite, Span::Infinite);
        assert_eq!(Span::Infinite * Span::Null, Span::Infinite);

        assert_eq!(Span::Finite(1) * Span::Finite(1), Span::Finite(1));
        assert_eq!(Span::Finite(1) * Span::Finite(5), Span::Finite(5));
        assert_eq!(Span::Finite(5) * Span::Finite(1), Span::Finite(5));
        assert_eq!(Span::Finite(5) * Span::Finite(5), Span::Finite(25));
    }

    #[test]
    #[should_panic]
    fn test_into_null() {
        let s = Span::Null;
        let v: usize = s.into();
    }

    #[test]
    #[should_panic]
    fn test_into_infinite() {
        let s = Span::Infinite;
        let v: usize = s.into();
    }

    #[test]
    fn test_into_finite() {
        for i in vec![1, 5, 10] {
            let d = Span::Finite(i);
            let v: usize = d.into();

            assert_eq!(v, i);
        }
    }
}
<|endoftext|>


<commit_before>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use std::collections::BTreeSet;

use graph::vertex::Vertex;
use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    VertexNotFound,
    FormatError,
    Unexpected,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, false, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    vertex_id: Id,
    field_id: u64
}

fn empty_list_segment(vertex_id: &Id, level: usize) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", vertex_id.higher, vertex_id.lower, 1);
    let list_id = Id::new(vertex_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

fn count_cell_list(seg: &Cell) -> Result<usize, IdListError> {
    if let &Value::Map(ref map) = &seg.data {
        if let &Value::Array(ref array) = map.get_by_key_id(*LIST_KEY_ID) {
            Ok(array.len())
        } else {
            Err(IdListError::FormatError)
        }
    } else {
        Err(IdListError::FormatError)
    }
}

fn val_is_id(val: &Value, id: &Id) -> bool {
    if let &Value::Id(ref val_id) = val {
        return val_id != id;
    } else {
        return true;
    }
}

impl<'a> IdList <'a> {
    pub fn from_txn_vertex(txn: &'a mut Transaction, vertex_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            vertex_id: *vertex_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_vertex: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.vertex_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    Ok(id)
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                if ensure_vertex {
                    let (list_id, list_value) = empty_list_segment(&self.vertex_id, 0);
                    let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                    match self.txn.write(&list_cell) {
                        Ok(()) => {},
                        Err(e) => return Err(IdListError::TxnError(e))
                    }
                    set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(list_id));
                    Ok(list_id)
                } else {
                    Err(IdListError::VertexNotFound)
                }
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let first_cell = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: first_cell,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self, id: Id) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut list_level = 0;
        let mut last_seg = {
            let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
            let mut last_seg = None;
            for seg in segments {
                list_level += 1;
                last_seg = Some(seg);
            }
            if let Some(seg) = last_seg { seg } else { return Err(IdListError::Unexpected); }
        };
        if count_cell_list(&mut last_seg)? >= *LIST_CAPACITY { // create new segment to prevent cell overflow
            list_level += 1;
            let (next_seg_id, next_seg_value) = empty_list_segment(&self.vertex_id, list_level);
            let next_seg_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &next_seg_id, next_seg_value);
            match self.txn.write(&next_seg_cell) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
            set_map_by_key_id(&mut self.txn, &last_seg.id(), *NEXT_KEY_ID, Value::Id(next_seg_id));
            last_seg = next_seg_cell;
        }
        if let &mut Value::Map(ref mut map) = &mut last_seg.data {
            if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                array.push(Value::Id(id));
            } else {
                return Err(IdListError::FormatError);
            }
        } else {
            return Err(IdListError::FormatError);
        }
        match self.txn.update(&last_seg) {
            Ok(()) => Ok(()),
            Err(e) => Err(IdListError::TxnError(e))
        }
    }
    pub fn remove(&mut self, id: Id, all: bool) -> Result<(), IdListError> {
        let id_value = Value::Id(id);
        let mut contained_segs = { // collect affected segment cell ids
            let mut iter = self.iter()?;
            let mut seg_ids = BTreeSet::new();
            while true {
                if let Some(iter_id) = iter.next() {
                    if iter_id == id {
                        if let Some(ref seg) = iter.current_seg {
                            seg_ids.insert(seg.id());
                        } else {
                            return Err(IdListError::Unexpected);
                        }
                    }
                } else {
                    break;
                }
            }
            seg_ids
        };
        for seg_id in &contained_segs { // mutate cell array
            match self.txn.read(seg_id) {
                Ok(Some(mut seg)) => {
                    if let &mut Value::Map(ref mut map) = &mut seg.data {
                        if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                            if all {
                                array.retain(|v| { !val_is_id(v, &id) });
                            } else {
                                let index = match array.iter().position(|v| { val_is_id(v, &id) }) {
                                    Some(pos) => pos, None => return Err(IdListError::Unexpected)
                                };
                                array.remove(index);
                            }
                        } else {
                            return Err(IdListError::FormatError);
                        }
                    } else {
                        return Err(IdListError::FormatError);
                    }
                    self.txn.update(&seg);
                    if !all { break; }
                },
                Ok(None) => return Err(IdListError::Unexpected),
                Err(e) => return Err(IdListError::TxnError(e)),
            }
        }
        return Ok(());
    }
}

pub struct IdListSegmentIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator<'a> {

    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let mut id_set = false;
        if !self.next.is_unit_id() {
            match self.txn.read(&self.next) {
                Ok(Some(cell)) => {
                    if let Value::Map(ref map) = cell.data {
                        if let &Value::Id(ref id) = map.get_by_key_id(*NEXT_KEY_ID) {
                            self.next = *id;
                            id_set = true;
                        }
                    }
                    if id_set {
                        self.level += 1;
                        return Some(cell)
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<commit_msg>clear id list, optimize iterator for add and clear by select related cell field instead of whole cell<commit_after>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use std::collections::BTreeSet;

use graph::vertex::Vertex;
use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    VertexNotFound,
    FormatError,
    Unexpected,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, false, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
    pub static ref NEXT_KEY_ID_VEC: Vec<u64> = vec![*NEXT_KEY_ID];
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    vertex_id: Id,
    field_id: u64
}

fn empty_list_segment(vertex_id: &Id, level: usize) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", vertex_id.higher, vertex_id.lower, 1);
    let list_id = Id::new(vertex_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

fn count_cell_list(seg: &Cell) -> Result<usize, IdListError> {
    if let &Value::Map(ref map) = &seg.data {
        if let &Value::Array(ref array) = map.get_by_key_id(*LIST_KEY_ID) {
            Ok(array.len())
        } else {
            Err(IdListError::FormatError)
        }
    } else {
        Err(IdListError::FormatError)
    }
}

fn val_is_id(val: &Value, id: &Id) -> bool {
    if let &Value::Id(ref val_id) = val {
        return val_id != id;
    } else {
        return true;
    }
}

fn seg_cell_by_id(txn: &mut Transaction, id: Option<Id>) -> Result<Option<Cell>, IdListError> {
    match id {
        Some(id) => match txn.read(&id) {
            Ok(cell) => Ok(cell),
            Err(e) => Err(IdListError::TxnError(e))
        },
        None => Ok(None)
    }
}

impl<'a> IdList <'a> {
    pub fn from_txn_vertex(txn: &'a mut Transaction, vertex_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            vertex_id: *vertex_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_vertex: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.vertex_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    if id == Id::unit_id() && ensure_vertex {
                        let (list_id, list_value) = empty_list_segment(&self.vertex_id, 0);
                        let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                        match self.txn.write(&list_cell) {
                            Ok(()) => {},
                            Err(e) => return Err(IdListError::TxnError(e))
                        }
                        set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(list_id));
                        Ok(list_id)
                    } else {
                        Ok(id)
                    }
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                Err(IdListError::VertexNotFound)
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let current_seg = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: current_seg,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self, id: Id) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut list_level = 0;
        let mut last_seg = {
            let last_seg_id = {
                let mut segments = IdListSegmentIdIterator::new(&mut self.txn, list_root_id);
                let mut last_seg_id = None;
                for seg in segments {
                    list_level += 1;
                    last_seg_id = Some(seg);
                }
                last_seg_id
            };
            let last_seg = seg_cell_by_id(&mut self.txn, last_seg_id)?;
            if let Some(seg) = last_seg { seg } else { return Err(IdListError::Unexpected); }
        };
        if count_cell_list(&mut last_seg)? >= *LIST_CAPACITY { // create new segment to prevent cell overflow
            list_level += 1;
            let (next_seg_id, next_seg_value) = empty_list_segment(&self.vertex_id, list_level);
            let next_seg_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &next_seg_id, next_seg_value);
            match self.txn.write(&next_seg_cell) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
            set_map_by_key_id(&mut self.txn, &last_seg.id(), *NEXT_KEY_ID, Value::Id(next_seg_id));
            last_seg = next_seg_cell;
        }
        if let &mut Value::Map(ref mut map) = &mut last_seg.data {
            if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                array.push(Value::Id(id));
            } else {
                return Err(IdListError::FormatError);
            }
        } else {
            return Err(IdListError::FormatError);
        }
        match self.txn.update(&last_seg) {
            Ok(()) => Ok(()),
            Err(e) => Err(IdListError::TxnError(e))
        }
    }
    pub fn remove(&mut self, id: Id, all: bool) -> Result<(), IdListError> {
        let id_value = Value::Id(id);
        let mut contained_segs = { // collect affected segment cell ids
            let mut iter = self.iter()?;
            let mut seg_ids = BTreeSet::new();
            while true {
                if let Some(iter_id) = iter.next() {
                    if iter_id == id {
                        if let Some(ref seg) = iter.current_seg {
                            seg_ids.insert(seg.id());
                        } else {
                            return Err(IdListError::Unexpected);
                        }
                    }
                } else {
                    break;
                }
            }
            seg_ids
        };
        for seg_id in &contained_segs { // mutate cell array
            match self.txn.read(seg_id) {
                Ok(Some(mut seg)) => {
                    if let &mut Value::Map(ref mut map) = &mut seg.data {
                        if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                            if all {
                                array.retain(|v| { !val_is_id(v, &id) });
                            } else {
                                let index = match array.iter().position(|v| { val_is_id(v, &id) }) {
                                    Some(pos) => pos, None => return Err(IdListError::Unexpected)
                                };
                                array.remove(index);
                            }
                        } else {
                            return Err(IdListError::FormatError);
                        }
                    } else {
                        return Err(IdListError::FormatError);
                    }
                    self.txn.update(&seg);
                    if !all { break; }
                },
                Ok(None) => return Err(IdListError::Unexpected),
                Err(e) => return Err(IdListError::TxnError(e)),
            }
        }
        return Ok(());
    }
    pub fn clear(&mut self) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let segments: Vec<_> = IdListSegmentIdIterator::new(&mut self.txn, list_root_id).collect();
        for seg_id in segments {
            match self.txn.remove(&seg_id) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
        }
        set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(Id::unit_id()));
        return Ok(())
    }
}

pub struct IdListSegmentIdIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIdIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIdIterator<'a> {
        IdListSegmentIdIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIdIterator<'a> {

    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        if !self.next.is_unit_id() {
            match self.txn.read_selected(&self.next, &*NEXT_KEY_ID_VEC) {
                Ok(Some(fields)) => {
                    let current_id = self.next;
                    if let Some(&Value::Id(ref id)) = fields.get(0) {
                        self.next = *id;
                        self.level += 1;
                        return Some(current_id);
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListSegmentIterator<'a> {
    id_iter: IdListSegmentIdIterator<'a>
}

impl <'a>IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            id_iter: IdListSegmentIdIterator::new(txn, head_id)
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator <'a> {
    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let next_id = self.id_iter.next();
        if let Ok(Some(cell)) = seg_cell_by_id(self.id_iter.txn, next_id) {
            Some(cell)
        } else {
            None
        }
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<|endoftext|>


<commit_before>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use graph::vertex::Vertex;
use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    VertexNotFound,
    FormatError,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, true, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    vertex_id: Id,
    field_id: u64
}

fn empty_list_segment(vertex_id: &Id, level: u32) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", vertex_id.higher, vertex_id.lower, 1);
    let list_id = Id::new(vertex_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

impl<'a> IdList <'a> {
    pub fn from_txn_vertex(txn: &'a mut Transaction, vertex_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            vertex_id: *vertex_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_vertex: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.vertex_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    Ok(id)
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                if ensure_vertex {
                    let (list_id, list_value) = empty_list_segment(&self.vertex_id, 0);
                    let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                    self.txn.write(&list_cell);
                    set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(list_id));
                    Ok(list_id)
                } else {
                    Err(IdListError::VertexNotFound)
                }
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let first_cell = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: first_cell,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let last_seg = segments.last();
        Ok(())
    }
}

pub struct IdListSegmentIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator<'a> {

    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let mut id_set = false;
        if !self.next.is_unit_id() {
            match self.txn.read(&self.next) {
                Ok(Some(cell)) => {
                    if let Value::Map(ref map) = cell.data {
                        if let &Value::Id(ref id) = map.get_by_key_id(*NEXT_KEY_ID) {
                            self.next = *id;
                            id_set = true;
                        }
                    }
                    if id_set {
                        self.level += 1;
                        return Some(cell)
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<commit_msg>complete id list add<commit_after>use neb::ram::schema::Field;
use neb::ram::cell::{MAX_CELL_SIZE, Cell};
use neb::ram::types::{TypeId, Id, Map, Value, id_io, u32_io, key_hash};
use neb::client::transaction::{Transaction, TxnError};

use graph::vertex::Vertex;
use utils::transaction::set_map_by_key_id;

pub const NEXT_KEY: &'static str = "_next";
pub const LIST_KEY: &'static str = "_list";

pub enum IdListError {
    VertexNotFound,
    FormatError,
    TxnError(TxnError)
}

pub static ID_LIST_SCHEMA_ID: u32 = 100;

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from(NEXT_KEY), TypeId::Id as u32, true, false, None),
            Field::new(&String::from(LIST_KEY), TypeId::Id as u32, false, true, None)
          ];
    pub static ref LIST_CAPACITY: usize =
        ((MAX_CELL_SIZE - u32_io::size(0) - id_io::size(0)) / id_io::size(0));
    pub static ref NEXT_KEY_ID: u64 = key_hash(&String::from(NEXT_KEY));
    pub static ref LIST_KEY_ID: u64 = key_hash(&String::from(LIST_KEY));
}

pub struct IdList<'a> {
    txn: &'a mut Transaction,
    vertex_id: Id,
    field_id: u64
}

fn empty_list_segment(vertex_id: &Id, level: usize) -> (Id, Value) {
    let str_id = format!("IDLIST-{},{}-{}", vertex_id.higher, vertex_id.lower, 1);
    let list_id = Id::new(vertex_id.higher, key_hash(&str_id));
    let mut list_map = Map::new();
    list_map.insert_key_id(*NEXT_KEY_ID, Value::Id(Id::unit_id()));
    list_map.insert_key_id(*LIST_KEY_ID, Value::Array(Vec::<Value>::new()));
    return (list_id, Value::Map(list_map));
}

fn count_cell_list(seg: &Cell) -> Result<usize, IdListError> {
    if let &Value::Map(ref map) = &seg.data {
        if let &Value::Array(ref array) = map.get_by_key_id(*LIST_KEY_ID) {
            Ok(array.len())
        } else {
            Err(IdListError::FormatError)
        }
    } else {
        Err(IdListError::FormatError)
    }
}

impl<'a> IdList <'a> {
    pub fn from_txn_vertex(txn: &'a mut Transaction, vertex_id: &Id, field_id: u64) -> IdList<'a> {
        IdList {
            txn: txn,
            vertex_id: *vertex_id,
            field_id: field_id,
        }
    }
    fn get_root_list_id(&mut self, ensure_vertex: bool) -> Result<Id, IdListError> {
        match self.txn.read_selected(&self.vertex_id, &vec![self.field_id]) {
            Err(e) => Err(IdListError::TxnError(e)),
            Ok(Some(fields)) => {
                if let Some(&Value::Id(id)) = fields.get(0) {
                    Ok(id)
                } else {
                    Err(IdListError::FormatError)
                }
            },
            Ok(None) => {
                if ensure_vertex {
                    let (list_id, list_value) = empty_list_segment(&self.vertex_id, 0);
                    let list_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &list_id, list_value);
                    match self.txn.write(&list_cell) {
                        Ok(()) => {},
                        Err(e) => return Err(IdListError::TxnError(e))
                    }
                    set_map_by_key_id(self.txn, &self.vertex_id, self.field_id, Value::Id(list_id));
                    Ok(list_id)
                } else {
                    Err(IdListError::VertexNotFound)
                }
            }
        }
    }
    pub fn iter(&mut self) -> Result<IdListIterator, IdListError> {
        let list_root_id = self.get_root_list_id(false)?;
        let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
        let first_cell = segments.next();
        Ok(IdListIterator {
            segments: segments,
            current_seg: first_cell,
            current_pos: 0,
        })
    }
    pub fn all(&mut self) -> Result<Vec<Id>, IdListError> {
        Ok(self.iter()?.collect())
    }
    pub fn count(&mut self) -> Result<usize, IdListError> {
        Ok(self.iter()?.count())
    }
    pub fn add(&mut self, id: Id) -> Result<(), IdListError> {
        let list_root_id = self.get_root_list_id(true)?;
        let mut last_seg = {
            let mut segments = IdListSegmentIterator::new(&mut self.txn, list_root_id);
            if let Some(cell) = segments.last() { cell } else {
                return Err(IdListError::FormatError);
            }
        };
        if count_cell_list(&mut last_seg)? >= *LIST_CAPACITY { // create new segment to prevent cell overflow
            let list_level = IdListSegmentIterator::new(&mut self.txn, list_root_id).count();
            let (next_seg_id, next_seg_value) = empty_list_segment(&self.vertex_id, list_level);
            let next_seg_cell = Cell::new_with_id(ID_LIST_SCHEMA_ID, &next_seg_id, next_seg_value);
            match self.txn.write(&next_seg_cell) {
                Ok(()) => {},
                Err(e) => return Err(IdListError::TxnError(e))
            }
            set_map_by_key_id(&mut self.txn, &last_seg.id(), *NEXT_KEY_ID, Value::Id(next_seg_id));
            last_seg = next_seg_cell;
        }
        if let &mut Value::Map(ref mut map) = &mut last_seg.data {
            if let Some(&mut Value::Array(ref mut array)) = map.get_mut_by_key_id(*LIST_KEY_ID) {
                array.push(Value::Id(id));
            } else {
                return Err(IdListError::FormatError);
            }
        } else {
            return Err(IdListError::FormatError);
        }
        match self.txn.update(&last_seg) {
            Ok(()) => Ok(()),
            Err(e) => Err(IdListError::TxnError(e))
        }
    }
}

pub struct IdListSegmentIterator<'a> {
    txn: &'a mut Transaction,
    next: Id,
    level: u32
}

impl <'a> IdListSegmentIterator<'a> {
    pub fn new(txn: &'a mut Transaction, head_id: Id) -> IdListSegmentIterator<'a> {
        IdListSegmentIterator {
            txn: txn,
            next: head_id,
            level: 1
        }
    }
}

impl <'a> Iterator for IdListSegmentIterator<'a> {

    type Item = Cell;

    fn next(&mut self) -> Option<Self::Item> {
        let mut id_set = false;
        if !self.next.is_unit_id() {
            match self.txn.read(&self.next) {
                Ok(Some(cell)) => {
                    if let Value::Map(ref map) = cell.data {
                        if let &Value::Id(ref id) = map.get_by_key_id(*NEXT_KEY_ID) {
                            self.next = *id;
                            id_set = true;
                        }
                    }
                    if id_set {
                        self.level += 1;
                        return Some(cell)
                    }
                },
                _ => {}
            }
        }
        None
    }
}

pub struct IdListIterator<'a> {
    segments: IdListSegmentIterator<'a>,
    current_seg: Option<Cell>,
    current_pos: u32
}

impl <'a> IdListIterator <'a> {
    pub fn next_seg(&mut self) {
        self.current_seg = self.segments.next();
        self.current_pos = 0;
    }
}

impl <'a> Iterator for IdListIterator<'a> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        let mut need_next_seg = false;
        if let Some(ref cell) = self.current_seg {
            let pos = self.current_pos;
            self.current_pos += 1;
            if let &Value::Map(ref map) = &cell.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.get(pos as usize) {
                        return Some(id);
                    } else {
                        need_next_seg = true
                    }
                }
            }
        };
        if need_next_seg {
            self.next_seg();
            self.next()
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> where Self: Sized {
        if let Some(last_seg) = self.segments.last() {
            if let &Value::Map(ref map) = &last_seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    if let Some(&Value::Id(id)) = list.last() {
                        return Some(id);
                    }
                }
            }
        }
        return None;
    }
    fn count(self) -> usize where Self: Sized {
        let mut count = 0;
        for seg in self.segments {
            if let &Value::Map(ref map) = &seg.data {
                if let &Value::Array(ref list) = map.get_by_key_id(*LIST_KEY_ID) {
                    count += list.len();
                }
            }
        }
        return count;
    }
}

<|endoftext|>


<commit_before>use super::*;

#[cfg(unix)]
use std::os::unix::fs::FileExt;

/// Multithreaded IO support for Files
pub(crate) trait Pio {
    /// Read from a specific offset without changing
    /// the underlying file offset.
    fn pread_exact(&self, to_buf: &mut [u8], offset: LogId) -> io::Result<()>;

    /// Write to a specific offset without changing
    /// the underlying file offset.
    fn pwrite_all(&self, from_buf: &[u8], offset: LogId) -> io::Result<()>;
}

// On systems that support pread/pwrite, use them underneath.
#[cfg(unix)]
impl Pio for std::fs::File {
    fn pread_exact(&self, buf: &mut [u8], offset: LogId) -> io::Result<()> {
        self.read_exact_at(buf, offset)
    }

    fn pwrite_all(&self, buf: &[u8], offset: LogId) -> io::Result<()> {
        self.write_all_at(buf, offset)
    }
}

#[cfg(not(unix))]
use {
    parking_lot::Mutex,
    std::io::{Read, Seek, Write},
};

#[cfg(not(unix))]
fn init_mu() -> Mutex<()> {
    Mutex::new(())
}

#[cfg(not(unix))]
type MutexInit = fn() -> Mutex<()>;

#[cfg(not(unix))]
static MAX_GLOBAL_FILE_LOCK: Lazy<Mutex<()>, MutexInit> = Lazy::new(init_mu);

#[cfg(not(unix))]
impl Pio for std::fs::File {
    fn pread_exact(&self, mut buf: &mut [u8], offset: LogId) -> io::Result<()> {
        let _lock = GLOBAL_FILE_LOCK.lock();

        let mut f = self.try_clone()?;

        f.seek(std::io::SeekFrom::Start(offset))?;

        while !buf.is_empty() {
            match f.read(buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &mut tmp[n..];
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof,
                "failed to fill whole buffer",
            ))
        } else {
            Ok(())
        }
    }

    fn pwrite_all(&self, mut buf: &[u8], offset: LogId) -> io::Result<()> {
        let _lock = GLOBAL_FILE_LOCK.lock();

        let mut f = self.try_clone()?;

        f.seek(std::io::SeekFrom::Start(offset))?;

        while !buf.is_empty() {
            match f.write(buf) {
                Ok(0) => {
                    return Err(io::Error::new(
                        io::ErrorKind::WriteZero,
                        "failed to write whole buffer",
                    ));
                }
                Ok(n) => buf = &buf[n..],
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }
}
<commit_msg>fix file lock name<commit_after>use super::*;

#[cfg(unix)]
use std::os::unix::fs::FileExt;

/// Multithreaded IO support for Files
pub(crate) trait Pio {
    /// Read from a specific offset without changing
    /// the underlying file offset.
    fn pread_exact(&self, to_buf: &mut [u8], offset: LogId) -> io::Result<()>;

    /// Write to a specific offset without changing
    /// the underlying file offset.
    fn pwrite_all(&self, from_buf: &[u8], offset: LogId) -> io::Result<()>;
}

// On systems that support pread/pwrite, use them underneath.
#[cfg(unix)]
impl Pio for std::fs::File {
    fn pread_exact(&self, buf: &mut [u8], offset: LogId) -> io::Result<()> {
        self.read_exact_at(buf, offset)
    }

    fn pwrite_all(&self, buf: &[u8], offset: LogId) -> io::Result<()> {
        self.write_all_at(buf, offset)
    }
}

#[cfg(not(unix))]
use {
    parking_lot::Mutex,
    std::io::{Read, Seek, Write},
};

#[cfg(not(unix))]
fn init_mu() -> Mutex<()> {
    Mutex::new(())
}

#[cfg(not(unix))]
type MutexInit = fn() -> Mutex<()>;

#[cfg(not(unix))]
static GLOBAL_FILE_LOCK: Lazy<Mutex<()>, MutexInit> = Lazy::new(init_mu);

#[cfg(not(unix))]
impl Pio for std::fs::File {
    fn pread_exact(&self, mut buf: &mut [u8], offset: LogId) -> io::Result<()> {
        let _lock = GLOBAL_FILE_LOCK.lock();

        let mut f = self.try_clone()?;

        f.seek(std::io::SeekFrom::Start(offset))?;

        while !buf.is_empty() {
            match f.read(buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &mut tmp[n..];
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(io::Error::new(
                io::ErrorKind::UnexpectedEof,
                "failed to fill whole buffer",
            ))
        } else {
            Ok(())
        }
    }

    fn pwrite_all(&self, mut buf: &[u8], offset: LogId) -> io::Result<()> {
        let _lock = GLOBAL_FILE_LOCK.lock();

        let mut f = self.try_clone()?;

        f.seek(std::io::SeekFrom::Start(offset))?;

        while !buf.is_empty() {
            match f.write(buf) {
                Ok(0) => {
                    return Err(io::Error::new(
                        io::ErrorKind::WriteZero,
                        "failed to write whole buffer",
                    ));
                }
                Ok(n) => buf = &buf[n..],
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }
}
<|endoftext|>