From 07ba5b7aca2c63adab908f4735573781d66b8905 Mon Sep 17 00:00:00 2001 From: misson20000 Date: Sat, 25 Nov 2023 17:41:06 -0500 Subject: [PATCH] wip buckets 2 --- src/util.rs | 70 +++++++++++- src/view/listing.rs | 1 + src/view/listing/bucket.rs | 175 +++++++++++++++++++++++++++++ src/view/listing/line.rs | 146 +++++++++++------------- src/view/listing/token_view/mod.rs | 17 --- 5 files changed, 310 insertions(+), 99 deletions(-) create mode 100644 src/view/listing/bucket.rs diff --git a/src/util.rs b/src/util.rs index 9d45995..5f51692 100644 --- a/src/util.rs +++ b/src/util.rs @@ -63,14 +63,59 @@ impl Default for Notifier { } } -pub enum PhiIterator, I2: Iterator, I3: Iterator, I4: Iterator> { +pub enum Never { +} + +pub struct NeverIterator(Never, std::marker::PhantomData); + +impl Iterator for NeverIterator { + type Item = T; + + fn next(&mut self) -> Option { + match self.0 { + } + } +} + +impl DoubleEndedIterator for NeverIterator { + fn next_back(&mut self) -> Option { + match self.0 { + } + } +} +pub enum PhiIterator + = NeverIterator, + I2: Iterator = NeverIterator, + I3: Iterator = NeverIterator, + I4: Iterator = NeverIterator, + I5: Iterator = NeverIterator, + I6: Iterator = NeverIterator +> { I1(I1), I2(I2), I3(I3), I4(I4), + I5(I5), + I6(I6), } -impl, I2: Iterator, I3: Iterator, I4: Iterator> Iterator for PhiIterator { +impl, + I2: Iterator, + I3: Iterator, + I4: Iterator, + I5: Iterator, + I6: Iterator + > Iterator for PhiIterator + { type Item = Item; fn next(&mut self) -> Option { @@ -79,17 +124,36 @@ impl, I2: Iterator, I3: Iterator i.next(), Self::I3(i) => i.next(), Self::I4(i) => i.next(), + Self::I5(i) => i.next(), + Self::I6(i) => i.next(), } } } -impl, I2: DoubleEndedIterator, I3: DoubleEndedIterator, I4: DoubleEndedIterator> DoubleEndedIterator for PhiIterator { +impl, + I2: DoubleEndedIterator, + I3: DoubleEndedIterator, + I4: DoubleEndedIterator, + I5: DoubleEndedIterator, + I6: DoubleEndedIterator + > DoubleEndedIterator for PhiIterator + { fn next_back(&mut self) -> Option { match self { Self::I1(i) => i.next_back(), Self::I2(i) => i.next_back(), Self::I3(i) => i.next_back(), Self::I4(i) => i.next_back(), + Self::I5(i) => i.next_back(), + Self::I6(i) => i.next_back(), } } } diff --git a/src/view/listing.rs b/src/view/listing.rs index 1747e36..93e85b3 100644 --- a/src/view/listing.rs +++ b/src/view/listing.rs @@ -25,6 +25,7 @@ use gtk::pango; use gtk::subclass::prelude::*; use gtk::prelude::*; +mod bucket; pub mod facet; mod token_view; mod line; diff --git a/src/view/listing/bucket.rs b/src/view/listing/bucket.rs new file mode 100644 index 0000000..4b24847 --- /dev/null +++ b/src/view/listing/bucket.rs @@ -0,0 +1,175 @@ +use std::iter; +use std::sync; +use std::vec; + +use crate::model::addr; +use crate::model::document::structure; +use crate::model::listing::token; +use crate::model::selection; +use crate::view::listing; +use crate::view::listing::facet::cursor; +use crate::view::listing::token_view; + +use gtk::graphene; + +#[derive(Clone, Copy)] +pub struct RenderArgs<'a> { + snapshot: &'a gtk::Snapshot, + cursor: &'a cursor::CursorView, + selection: &'a selection::listing::Mode, + render: &'a listing::RenderDetail +} + +pub trait Bucket { + type TokenIterator; + type BorrowingTokenIterator<'a> where Self: 'a; + + //fn render(&mut self, ctx: RenderArgs<'_>); + fn iter_tokens(&self) -> Self::BorrowingTokenIterator<'_>; + fn to_tokens(self) -> Self::TokenIterator; +} + +pub struct BlankMarker; +pub struct TitleMarker; +pub struct HexstringMarker; +pub struct SummaryMarker; + +pub struct SingleTokenBucket { + begin: graphene::Point, + end: graphene::Point, + tv: token_view::TokenView, + marker: std::marker::PhantomData, +} + +pub struct MaybeTokenBucket { + begin: graphene::Point, + end: graphene::Point, + tv: Option, + marker: std::marker::PhantomData, +} + +pub struct MultiTokenBucket { + begin: graphene::Point, + end: graphene::Point, + tvs: Vec, + marker: std::marker::PhantomData, +} + +pub struct HexdumpBucket { + begin: graphene::Point, + end: graphene::Point, + node: sync::Arc, + line_extent: addr::Extent, + tvs: Vec +} + +impl SingleTokenBucket { +} + +impl From for SingleTokenBucket { + fn from(token: token::Token) -> Self { + SingleTokenBucket { + begin: graphene::Point::zero(), + end: graphene::Point::zero(), + tv: token_view::TokenView::from(token), + marker: std::marker::PhantomData + } + } +} + +impl Bucket for SingleTokenBucket { + type TokenIterator = iter::Once; + type BorrowingTokenIterator<'a> = iter::Once<&'a token::Token> where Marker: 'a; + + fn iter_tokens(&self) -> Self::BorrowingTokenIterator<'_> { + iter::once(self.tv.token()) + } + + fn to_tokens(self) -> Self::TokenIterator { + iter::once(self.tv.into_token()) + } +} + +impl MaybeTokenBucket { + fn from_token(token: Option) -> Self { + MaybeTokenBucket { + begin: graphene::Point::zero(), + end: graphene::Point::zero(), + tv: token.map(token_view::TokenView::from), + marker: std::marker::PhantomData + } + } +} + +impl From> for MaybeTokenBucket { + fn from(token: Option) -> Self { + MaybeTokenBucket { + begin: graphene::Point::zero(), + end: graphene::Point::zero(), + tv: token.map(token_view::TokenView::from), + marker: std::marker::PhantomData + } + } +} + +impl Bucket for MaybeTokenBucket { + type TokenIterator = std::option::IntoIter; + type BorrowingTokenIterator<'a> = std::option::IntoIter<&'a token::Token> where Marker: 'a; + + fn iter_tokens(&self) -> Self::BorrowingTokenIterator<'_> { + self.tv.as_ref().map(token_view::TokenView::token).into_iter() + } + + fn to_tokens(self) -> Self::TokenIterator { + self.tv.map(token_view::TokenView::into_token).into_iter() + } +} + +impl MultiTokenBucket { + pub fn from_tokens(tokens: impl Iterator) -> Self { + MultiTokenBucket { + begin: graphene::Point::zero(), + end: graphene::Point::zero(), + tvs: tokens.map(token_view::TokenView::from).collect(), + marker: std::marker::PhantomData + } + } +} + +impl Bucket for MultiTokenBucket { + type TokenIterator = iter::Map, fn(token_view::TokenView) -> token::Token>; + type BorrowingTokenIterator<'a> = iter::Map, fn(&'a token_view::TokenView) -> &'a token::Token> where Marker: 'a; + + fn iter_tokens(&self) -> Self::BorrowingTokenIterator<'_> { + self.tvs.iter().map(token_view::TokenView::token) + } + + fn to_tokens(self) -> Self::TokenIterator { + self.tvs.into_iter().map(token_view::TokenView::into_token) + } +} + +impl HexdumpBucket { + pub fn new(node: sync::Arc, line_extent: addr::Extent, tokens: impl Iterator) -> Self { + HexdumpBucket { + begin: graphene::Point::zero(), + end: graphene::Point::zero(), + node, + line_extent, + tvs: tokens.map(token_view::TokenView::from).collect(), + } + } +} + +impl Bucket for HexdumpBucket { + type TokenIterator = iter::Map, fn(token_view::TokenView) -> token::Token>; + type BorrowingTokenIterator<'a> = iter::Map, fn(&'a token_view::TokenView) -> &'a token::Token>; + + fn iter_tokens(&self) -> Self::BorrowingTokenIterator<'_> { + self.tvs.iter().map(token_view::TokenView::token) + } + + fn to_tokens(self) -> Self::TokenIterator { + self.tvs.into_iter().map(token_view::TokenView::into_token) + } +} diff --git a/src/view/listing/line.rs b/src/view/listing/line.rs index 5e89b77..a1c53dd 100644 --- a/src/view/listing/line.rs +++ b/src/view/listing/line.rs @@ -1,18 +1,17 @@ use std::iter; use std::sync; use std::task; -use std::vec; -use crate::model::addr; use crate::model::document; -use crate::model::document::structure; +use crate::model::listing::cursor; use crate::model::listing::layout; use crate::model::listing::token; use crate::model::selection; use crate::util; -use crate::view::gsc; use crate::view::helpers; use crate::view::listing; +use crate::view::listing::bucket; +use crate::view::listing::bucket::Bucket; use crate::view::listing::facet; use crate::view::listing::token_view; @@ -22,21 +21,19 @@ use gtk::gsk; enum LineViewType { Empty, - Blank(token_view::TokenView), - Title(token_view::TokenView), + Blank(bucket::SingleTokenBucket), + Title(bucket::SingleTokenBucket), Hexdump { - title: Option, - node: sync::Arc, - line_extent: addr::Extent, - tokens: Vec, + title: bucket::MaybeTokenBucket, + hexdump: bucket::HexdumpBucket, }, Hexstring { - title: Option, - token: token_view::TokenView, + title: bucket::MaybeTokenBucket, + hexstring: bucket::SingleTokenBucket, }, Summary { - title: Option, - tokens: Vec, + title: bucket::MaybeTokenBucket, + content: bucket::MultiTokenBucket, }, } @@ -81,43 +78,53 @@ impl layout::LineView for Line { } } -type LineViewBorrowingTokenIterator<'a> = iter::Map - , - iter::Once<&'a token_view::TokenView>, - iter::Chain, std::slice::Iter<'a, token_view::TokenView>>, - iter::Chain, iter::Once<&'a token_view::TokenView>>>, - fn(&'a token_view::TokenView) -> &'a token::Token>; - -type LineViewTokenIterator = iter::Map - , - iter::Once, - iter::Chain, vec::IntoIter>, - iter::Chain, iter::Once>>, - fn(token_view::TokenView) -> token::Token>; +type LineViewBorrowingTokenIterator<'a> = util::PhiIterator + <&'a token::Token, + iter::Empty<&'a token::Token>, + as Bucket>::BorrowingTokenIterator<'a>, + as Bucket>::BorrowingTokenIterator<'a>, + iter::Chain + < as Bucket>::BorrowingTokenIterator<'a>, + ::BorrowingTokenIterator<'a>>, + iter::Chain + < as Bucket>::BorrowingTokenIterator<'a>, + as Bucket>::BorrowingTokenIterator<'a>>, + iter::Chain + < as Bucket>::BorrowingTokenIterator<'a>, + as Bucket>::BorrowingTokenIterator<'a>>>; + +type LineViewTokenIterator = util::PhiIterator + , + as Bucket>::TokenIterator, + as Bucket>::TokenIterator, + iter::Chain + < as Bucket>::TokenIterator, + ::TokenIterator>, + iter::Chain + < as Bucket>::TokenIterator, + as Bucket>::TokenIterator>, + iter::Chain + < as Bucket>::TokenIterator, + as Bucket>::TokenIterator>>; impl LineViewType { fn from(line: layout::Line) -> Self { match line.ty { layout::LineType::Empty => Self::Empty, - layout::LineType::Blank(tok) => Self::Blank(token_view::TokenView::from(tok)), - layout::LineType::Title(tok) => Self::Title(token_view::TokenView::from(tok)), + layout::LineType::Blank(tok) => Self::Blank(tok.into()), + layout::LineType::Title(tok) => Self::Title(tok.into()), layout::LineType::Hexdump { title, node, line_extent, tokens } => Self::Hexdump { - title: title.map(token_view::TokenView::from), - node, - line_extent, - tokens: tokens.into_iter().map(token_view::TokenView::from).collect() + title: title.into(), + hexdump: bucket::HexdumpBucket::new(node, line_extent, tokens.into_iter()) }, layout::LineType::Hexstring { title, token } => Self::Hexstring { - title: title.map(token_view::TokenView::from), - token: token_view::TokenView::from(token), + title: title.into(), + hexstring: token.into() }, layout::LineType::Summary { title, tokens } => Self::Summary { - title: title.map(token_view::TokenView::from), - tokens: tokens.into_iter().map(token_view::TokenView::from).collect() + title: title.into(), + content: bucket::MultiTokenBucket::from_tokens(tokens.into_iter()) }, } } @@ -125,46 +132,31 @@ impl LineViewType { fn iter_tokens(&self) -> LineViewBorrowingTokenIterator<'_> { match &self { Self::Empty => util::PhiIterator::I1(iter::empty()), - Self::Blank(t) | Self::Title(t) => util::PhiIterator::I2(iter::once(t)), - Self::Hexdump { title, tokens, .. } => util::PhiIterator::I3(title.iter().chain(tokens.iter())), - Self::Hexstring { title, token, .. } => util::PhiIterator::I4(title.iter().chain(iter::once(token))), - Self::Summary { title, tokens, .. } => util::PhiIterator::I3(title.iter().chain(tokens.iter())), - }.map(token_view::TokenView::token) + Self::Blank(bucket) => util::PhiIterator::I2(bucket.iter_tokens()), + Self::Title(bucket) => util::PhiIterator::I3(bucket.iter_tokens()), + Self::Hexdump { title, hexdump } => util::PhiIterator::I4(title.iter_tokens().chain(hexdump.iter_tokens())), + Self::Hexstring { title, hexstring } => util::PhiIterator::I5(title.iter_tokens().chain(hexstring.iter_tokens())), + Self::Summary { title, content } => util::PhiIterator::I6(title.iter_tokens().chain(content.iter_tokens())), + } } fn to_tokens(self) -> LineViewTokenIterator { match self { Self::Empty => util::PhiIterator::I1(iter::empty()), - Self::Blank(t) | Self::Title(t) => util::PhiIterator::I2(iter::once(t)), - Self::Hexdump { title, tokens, .. } => util::PhiIterator::I3(title.into_iter().chain(tokens.into_iter())), - Self::Hexstring { title, token, .. } => util::PhiIterator::I4(title.into_iter().chain(iter::once(token))), - Self::Summary { title, tokens, .. } => util::PhiIterator::I3(title.into_iter().chain(tokens.into_iter())), - }.map(token_view::TokenView::into_token) + Self::Blank(bucket) => util::PhiIterator::I2(bucket.to_tokens()), + Self::Title(bucket) => util::PhiIterator::I3(bucket.to_tokens()), + Self::Hexdump { title, hexdump } => util::PhiIterator::I4(title.to_tokens().chain(hexdump.to_tokens())), + Self::Hexstring { title, hexstring } => util::PhiIterator::I5(title.to_tokens().chain(hexstring.to_tokens())), + Self::Summary { title, content } => util::PhiIterator::I6(title.to_tokens().chain(content.to_tokens())), + } } fn contains_cursor(&self, cursor: &cursor::Cursor) -> bool { - match self { - Self::Empty => false, - Self::Blank(t) | Self::Title(t) => cursor.is_over(t.token()), - Self::Hexdump { title, tokens, .. } => title.map_or(false, |tv| cursor.is_over(tv.token())) || tokens.iter().any(|tv| cursor.is_over(tv.token())), - Self::Hexstring { title, token, .. } => title.map_or(false, |tv| cursor.is_over(tv.token())) || cursor.is_over(token.token()), - Self::Summary { title, tokens, .. } => title.map_or(false, |tv| cursor.is_over(tv.token())) || tokens.iter().any(|tv| cursor.is_over(tv.token())), - } + self.iter_tokens().any(|t| cursor.is_over(t)) } fn indentation(&self) -> usize { - match self { - Self::Empty => 0, - Self::Blank(t) | Self::Title(t) => t.token().depth, - - Self::Hexdump { title: Some(t), .. } => t.token().depth, - Self::Hexstring { title: Some(t), .. } => t.token().depth, - Self::Summary { title: Some(t), .. } => t.token().depth, - - Self::Hexdump { tokens, .. } => tokens[0].token().depth, - Self::Hexstring { token, .. } => token.token().depth, - Self::SUmmary { tokens, .. } => tokens[0].token().depth, - } + self.iter_tokens().next().map_or(0, |t| t.depth) } } @@ -207,9 +199,6 @@ impl Line { self.ty.indentation() as f32 * render.config.indentation_width * helpers::pango_unscale(render.gsc_mono.space_width())); - } - - let mut visible_address = None; /* render tokens */ for token in &mut self.tokens { @@ -228,18 +217,17 @@ impl Line { main_position.set_x(main_position.x() + main_advance.x()); ascii_position.set_x(ascii_position.x() + ascii_advance.x()); - - /* pick the address from the first token that should display an address */ - if visible_address.is_none() { - visible_address = token.visible_address(); - } } + // TODO: address pane + /* if any of our tokens wanted to show an address, render the first one into the address pane */ + /* if let Some(addr) = visible_address { let mut pos = graphene::Point::new(render.addr_pane_width - render.config.padding as f32, helpers::pango_unscale(render.metrics.height())); gsc::begin_text(&render.pango, &render.font_mono, &render.config.addr_color, &format!("{}", addr), &mut pos).render_right_aligned(&snapshot); - } + } + */ if !has_cursor { self.selection_hash = selection_hash; diff --git a/src/view/listing/token_view/mod.rs b/src/view/listing/token_view/mod.rs index 2a6904b..f1f9099 100644 --- a/src/view/listing/token_view/mod.rs +++ b/src/view/listing/token_view/mod.rs @@ -31,17 +31,6 @@ pub struct TokenView { logical_bounds_asciidump: Option, } -struct CommonContext<'a> { - snapshot: &'a gtk::Snapshot, - cursor: &'a CursorView, - selection: &'a selection::listing::Mode, - render: &'a listing::RenderDetail -} - -trait RenderForBucket { - fn render(&mut self, ctx: &CommonContext<'_>, bucket: &mut Bucket); -} - impl TokenView { pub fn from(token: token::Token) -> TokenView { TokenView { @@ -103,12 +92,6 @@ impl TokenView { } } - pub fn render_for_blank(); - pub fn render_for_title(); - pub fn render_for_hexdump(); - pub fn render_for_hexstring(); - pub fn render_for_summary(); - pub fn render( &mut self, snapshot: >k::Snapshot,