use std;
use daggy;
use crate::graph::Graph;
pub type Id = daggy::NodeIndex<u32>;
pub struct Generator<'a> { widget_graph: &'a mut Graph }
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct List(Vec<Id>);
#[allow(missing_copy_implementations)]
pub struct ListWalk { i: usize }
impl<'a> Generator<'a> {
pub fn new(widget_graph: &'a mut Graph) -> Self {
Generator {
widget_graph: widget_graph,
}
}
pub fn next(&mut self) -> Id {
self.widget_graph.add_placeholder()
}
}
impl List {
pub fn new() -> Self {
List(Vec::new())
}
pub fn walk(&self) -> ListWalk {
ListWalk { i: 0 }
}
pub fn resize(&mut self, target_len: usize, id_generator: &mut Generator) {
if self.len() < target_len {
self.0.reserve(target_len);
while self.len() < target_len {
self.0.push(id_generator.next());
}
}
while self.len() > target_len {
self.0.pop();
}
}
}
impl std::ops::Deref for List {
type Target = [Id];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ListWalk {
pub fn next(&mut self, &mut List(ref mut ids): &mut List, id_gen: &mut Generator) -> Id {
while self.i >= ids.len() {
ids.push(id_gen.next());
}
let ix = ids[self.i];
self.i += 1;
ix
}
}
#[macro_export]
macro_rules! widget_ids {
($(#[$attr:meta])* struct $Ids:ident { $($id:tt)* }) => {
widget_ids! { implement $(#[$attr])* [] $Ids { $($id)* } }
};
($(#[$attr:meta])* pub struct $Ids:ident { $($id:tt)* }) => {
widget_ids! { implement $(#[$attr])* [pub] $Ids { $($id)* } }
};
(implement $(#[$attr:meta])* [$($public:tt)*] $Ids:ident { $($id:tt)* }) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { {} $($id)* }
}
impl $Ids {
#[allow(unused_mut, unused_variables)]
pub fn new(mut generator: $crate::widget::old::id::Generator) -> Self {
widget_ids! {
constructor $Ids, generator { {} $($id)* }
}
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident[], $($rest:tt)*
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids {
{
$($id_field: $T,)*
$id: $crate::widget::old::id::List,
}
$($rest)*
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident, $($rest:tt)*
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids {
{
$($id_field: $T,)*
$id: $crate::widget::Id,
}
$($rest)*
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident[]
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { { $($id_field: $T,)* } $id[], }
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { { $($id_field: $T,)* } $id, }
}
};
(define_struct $(#[$attr:meta])* [pub] $Ids:ident { { $($id:ident: $T:path,)* } }) => {
$(#[$attr])*
pub struct $Ids {
$(pub $id: $T,
)*
}
};
(define_struct $(#[$attr:meta])* [] $Ids:ident { { $($id:ident: $T:path,)* } }) => {
$(#[$attr])*
struct $Ids {
$(pub $id: $T,
)*
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident[], $($rest:tt)*
}) => {
widget_ids! {
constructor $Ids, $generator {
{
$($id_field: $new,)*
$id: $crate::widget::old::id::List::new(),
}
$($rest)*
}
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident, $($rest:tt)*
}) => {
widget_ids! {
constructor $Ids, $generator {
{
$($id_field: $new,)*
$id: $generator.next(),
}
$($rest)*
}
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident[]
}) => {
widget_ids! { constructor $Ids, $generator { { $($id_field: $new,)* } $id[], } }
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident
}) => {
widget_ids! { constructor $Ids, $generator { { $($id_field: $new,)* } $id, } }
};
(constructor $Ids:ident, $generator:ident { { $($id:ident: $new:expr,)* } }) => {
$Ids {
$(
$id: $new,
)*
}
};
}