diff --git a/.gitignore b/.gitignore index 5a7b25df7..1563ef835 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ flamegraph.svg # AI .claude/settings* + +# Expand +expand.rs diff --git a/Cargo.lock b/Cargo.lock index 2f650fe60..b05061041 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -619,7 +619,7 @@ dependencies = [ "brk_parser", "brk_store", "brk_structs", - "brk_vecs", + "brk_traversable", "derive_deref", "log", "pco", @@ -667,7 +667,7 @@ dependencies = [ "brk_parser", "brk_store", "brk_structs", - "brk_vecs", + "brk_traversable", "fjall", "log", "rayon", @@ -684,6 +684,7 @@ dependencies = [ "brk_indexer", "brk_parser", "brk_structs", + "brk_traversable", "derive_deref", "nucleo-matcher", "quick_cache", @@ -1184,7 +1185,7 @@ dependencies = [ "bitcoin", "bitcoincore-rpc", "brk_error", - "brk_vecs", + "brk_traversable", "byteview", "derive_deref", "itoa", @@ -1201,16 +1202,16 @@ dependencies = [ ] [[package]] -name = "brk_vecs" +name = "brk_traversable" version = "0.0.111" dependencies = [ - "brk_vecs_derive", + "brk_traversable_derive", "serde", "vecdb", ] [[package]] -name = "brk_vecs_derive" +name = "brk_traversable_derive" version = "0.0.111" dependencies = [ "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index d6bfbf4f0..884454c29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,8 +59,8 @@ brk_parser = { version = "0.0.111", path = "crates/brk_parser" } brk_server = { version = "0.0.111", path = "crates/brk_server" } brk_store = { version = "0.0.111", path = "crates/brk_store" } brk_structs = { version = "0.0.111", path = "crates/brk_structs" } -brk_vecs = { version = "0.0.111", path = "crates/brk_vecs", features = ["derive"] } -brk_vecs_derive = { version = "0.0.111", path = "crates/brk_vecs_derive" } +brk_traversable = { version = "0.0.111", path = "crates/brk_traversable", features = ["derive"] } +brk_traversable_derive = { version = "0.0.111", path = "crates/brk_traversable_derive" } byteview = "=0.6.1" derive_deref = "1.1.1" fjall = "2.11.2" diff --git a/crates/brk_computer/Cargo.toml b/crates/brk_computer/Cargo.toml index c589d54f5..0434de858 100644 --- a/crates/brk_computer/Cargo.toml +++ b/crates/brk_computer/Cargo.toml @@ -20,7 +20,7 @@ brk_indexer = { workspace = true } brk_logger = { workspace = true } brk_store = { workspace = true } brk_parser = { workspace = true } -brk_vecs = { workspace = true } +brk_traversable = { workspace = true } vecdb = { workspace = true } derive_deref = { workspace = true } log = { workspace = true } diff --git a/crates/brk_computer/examples/computer.rs b/crates/brk_computer/examples/computer.rs index 27ab2fb07..48325a32c 100644 --- a/crates/brk_computer/examples/computer.rs +++ b/crates/brk_computer/examples/computer.rs @@ -9,6 +9,7 @@ use brk_error::Result; use brk_fetcher::Fetcher; use brk_indexer::Indexer; use brk_parser::Parser; +use brk_traversable::Traversable; use vecdb::Exit; pub fn main() -> Result<()> { @@ -42,11 +43,6 @@ pub fn main() -> Result<()> { let mut computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?; - // should be: 205937 - dbg!(computer.iter_any_collectable().collect::>().len()); - - std::process::exit(0); - loop { let i = Instant::now(); let starting_indexes = indexer.index(&parser, rpc, &exit, true)?; diff --git a/crates/brk_computer/src/blks.rs b/crates/brk_computer/src/blks.rs index 5d295e81e..15979dd4d 100644 --- a/crates/brk_computer/src/blks.rs +++ b/crates/brk_computer/src/blks.rs @@ -4,7 +4,7 @@ use brk_error::Result; use brk_indexer::Indexer; use brk_parser::Parser; use brk_structs::{BlkPosition, Height, TxIndex, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, CompressedVec, Database, Exit, GenericStoredVec, PAGE_SIZE, VecIterator, @@ -12,7 +12,7 @@ use vecdb::{ use super::{Indexes, indexes}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -42,8 +42,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/chain.rs b/crates/brk_computer/src/chain.rs index 5bd86cfaf..e20ea1193 100644 --- a/crates/brk_computer/src/chain.rs +++ b/crates/brk_computer/src/chain.rs @@ -9,7 +9,7 @@ use brk_structs::{ SemesterIndex, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex, Weight, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyCloneableIterableVec, AnyIterableVec, Database, EagerVec, Exit, LazyVecFrom1, LazyVecFrom2, LazyVecFrom3, PAGE_SIZE, StoredIndex, VecIterator, @@ -33,7 +33,7 @@ const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER; const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR; const ONE_TERA_HASH: f64 = 1_000_000_000_000.0; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct Vecs { db: Database, @@ -1152,8 +1152,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/cointime.rs b/crates/brk_computer/src/cointime.rs index 4cc32c816..2dd38db98 100644 --- a/crates/brk_computer/src/cointime.rs +++ b/crates/brk_computer/src/cointime.rs @@ -2,7 +2,7 @@ use std::path::Path; use brk_error::Result; use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF32, StoredF64, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{Database, Exit, PAGE_SIZE, VecIterator}; use crate::grouped::ComputedVecsFromDateIndex; @@ -16,7 +16,7 @@ use super::{ indexes, price, stateful, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -278,8 +278,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/constants.rs b/crates/brk_computer/src/constants.rs index 27d37ceaa..9ac3a050e 100644 --- a/crates/brk_computer/src/constants.rs +++ b/crates/brk_computer/src/constants.rs @@ -2,7 +2,7 @@ use std::path::Path; use brk_error::Result; use brk_structs::{StoredF32, StoredI16, StoredU16, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{AnyVec, Database, Exit}; use crate::grouped::Source; @@ -13,7 +13,7 @@ use super::{ indexes, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -160,8 +160,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/fetched.rs b/crates/brk_computer/src/fetched.rs index 0b9f4416b..7a6f54425 100644 --- a/crates/brk_computer/src/fetched.rs +++ b/crates/brk_computer/src/fetched.rs @@ -4,7 +4,7 @@ use brk_error::Result; use brk_fetcher::Fetcher; use brk_indexer::Indexer; use brk_structs::{DateIndex, Height, OHLCCents, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, RawVec, StoredIndex, VecIterator, @@ -12,7 +12,7 @@ use vecdb::{ use super::{Indexes, indexes}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, fetcher: Fetcher, @@ -42,8 +42,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/grouped/builder_eager.rs b/crates/brk_computer/src/grouped/builder_eager.rs index d23852d11..77ffb018b 100644 --- a/crates/brk_computer/src/grouped/builder_eager.rs +++ b/crates/brk_computer/src/grouped/builder_eager.rs @@ -1,17 +1,17 @@ use allocative::Allocative; use brk_error::{Error, Result}; use brk_structs::{CheckedSub, StoredU64, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ - AnyCollectableVec, AnyIterableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, Format, - GenericStoredVec, StoredIndex, StoredRaw, + AnyIterableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, Format, GenericStoredVec, + StoredIndex, StoredRaw, }; use crate::utils::get_percentile; use super::ComputedType; -#[derive(Clone, Debug, IVecs, Allocative)] +#[derive(Clone, Debug, Traversable, Allocative)] pub struct EagerVecsBuilder where I: StoredIndex, @@ -541,7 +541,9 @@ where } pub fn starting_index(&self, max_from: I) -> I { - max_from.min(I::from(self.iter().map(|v| v.len()).min().unwrap())) + max_from.min(I::from( + self.iter_any_collectable().map(|v| v.len()).min().unwrap(), + )) } pub fn unwrap_first(&self) -> &EagerVec { diff --git a/crates/brk_computer/src/grouped/builder_lazy.rs b/crates/brk_computer/src/grouped/builder_lazy.rs index 5c33b5133..8e53f6b20 100644 --- a/crates/brk_computer/src/grouped/builder_lazy.rs +++ b/crates/brk_computer/src/grouped/builder_lazy.rs @@ -1,9 +1,8 @@ use allocative::Allocative; use brk_structs::Version; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ - AnyBoxedIterableVec, AnyCloneableIterableVec, AnyCollectableVec, FromCoarserIndex, - LazyVecFrom2, StoredIndex, + AnyBoxedIterableVec, AnyCloneableIterableVec, FromCoarserIndex, LazyVecFrom2, StoredIndex, }; use crate::grouped::{EagerVecsBuilder, VecBuilderOptions}; @@ -11,7 +10,7 @@ use crate::grouped::{EagerVecsBuilder, VecBuilderOptions}; use super::ComputedType; #[allow(clippy::type_complexity)] -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct LazyVecsBuilder where I: StoredIndex, @@ -218,7 +217,9 @@ where } pub fn starting_index(&self, max_from: I) -> I { - max_from.min(I::from(self.iter().map(|v| v.len()).min().unwrap())) + max_from.min(I::from( + self.iter_any_collectable().map(|v| v.len()).min().unwrap(), + )) } pub fn unwrap_first(&self) -> &LazyVecFrom2 { diff --git a/crates/brk_computer/src/grouped/from_dateindex.rs b/crates/brk_computer/src/grouped/from_dateindex.rs index de3ce7571..148eac949 100644 --- a/crates/brk_computer/src/grouped/from_dateindex.rs +++ b/crates/brk_computer/src/grouped/from_dateindex.rs @@ -4,14 +4,14 @@ use brk_error::Result; use brk_structs::{ DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{AnyCloneableIterableVec, AnyIterableVec, Database, EagerVec, Exit}; use crate::{Indexes, grouped::LazyVecsBuilder, indexes}; use super::{ComputedType, EagerVecsBuilder, Source, VecBuilderOptions}; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct ComputedVecsFromDateIndex where T: ComputedType + PartialOrd, diff --git a/crates/brk_computer/src/grouped/from_height.rs b/crates/brk_computer/src/grouped/from_height.rs index 3b8803f33..3dd3983c6 100644 --- a/crates/brk_computer/src/grouped/from_height.rs +++ b/crates/brk_computer/src/grouped/from_height.rs @@ -5,7 +5,7 @@ use brk_structs::{ DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{AnyCloneableIterableVec, AnyIterableVec, Database, EagerVec, Exit}; use crate::{ @@ -16,7 +16,7 @@ use crate::{ use super::{ComputedType, EagerVecsBuilder, VecBuilderOptions}; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct ComputedVecsFromHeight where T: ComputedType + PartialOrd, diff --git a/crates/brk_computer/src/grouped/from_height_strict.rs b/crates/brk_computer/src/grouped/from_height_strict.rs index 7b0eadc9c..5c0078f28 100644 --- a/crates/brk_computer/src/grouped/from_height_strict.rs +++ b/crates/brk_computer/src/grouped/from_height_strict.rs @@ -1,14 +1,14 @@ use brk_error::Result; use brk_structs::{DifficultyEpoch, Height, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{Database, EagerVec, Exit}; use crate::{Indexes, indexes}; use super::{ComputedType, EagerVecsBuilder, VecBuilderOptions}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct ComputedVecsFromHeightStrict where T: ComputedType + PartialOrd, diff --git a/crates/brk_computer/src/grouped/from_txindex.rs b/crates/brk_computer/src/grouped/from_txindex.rs index a84e299d6..3fa6ab673 100644 --- a/crates/brk_computer/src/grouped/from_txindex.rs +++ b/crates/brk_computer/src/grouped/from_txindex.rs @@ -5,7 +5,7 @@ use brk_structs::{ Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex, Sats, SemesterIndex, TxIndex, Version, WeekIndex, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyCloneableIterableVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, StoredIndex, VecIterator, @@ -19,7 +19,7 @@ use crate::{ use super::{ComputedType, EagerVecsBuilder, VecBuilderOptions}; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct ComputedVecsFromTxindex where T: ComputedType + PartialOrd, diff --git a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs index 84f7b8892..34ed30a94 100644 --- a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs +++ b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_structs::{Date, DateIndex, Dollars, StoredF32, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, StoredIndex, VecIterator, @@ -17,7 +17,7 @@ use crate::{ use super::{ComputedVecsFromDateIndex, VecBuilderOptions}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct ComputedRatioVecsFromDateIndex { pub price: Option>, diff --git a/crates/brk_computer/src/grouped/sd_from_dateindex.rs b/crates/brk_computer/src/grouped/sd_from_dateindex.rs index 5e87737b8..24bfc6480 100644 --- a/crates/brk_computer/src/grouped/sd_from_dateindex.rs +++ b/crates/brk_computer/src/grouped/sd_from_dateindex.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_structs::{CheckedSub, Date, DateIndex, Dollars, StoredF32, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, BoxedVecIterator, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, StoredIndex, @@ -10,7 +10,7 @@ use crate::{Indexes, grouped::source::Source, indexes}; use super::{ComputedVecsFromDateIndex, VecBuilderOptions}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct ComputedStandardDeviationVecsFromDateIndex { days: usize, diff --git a/crates/brk_computer/src/grouped/value_from_dateindex.rs b/crates/brk_computer/src/grouped/value_from_dateindex.rs index 6179c7de3..23744b9a9 100644 --- a/crates/brk_computer/src/grouped/value_from_dateindex.rs +++ b/crates/brk_computer/src/grouped/value_from_dateindex.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_structs::{Bitcoin, DateIndex, Dollars, Sats, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{CollectableVec, Database, EagerVec, Exit, StoredVec}; use crate::{ @@ -12,7 +12,7 @@ use crate::{ use super::{Source, VecBuilderOptions}; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct ComputedValueVecsFromDateIndex { pub sats: ComputedVecsFromDateIndex, pub bitcoin: ComputedVecsFromDateIndex, diff --git a/crates/brk_computer/src/grouped/value_from_height.rs b/crates/brk_computer/src/grouped/value_from_height.rs index 95039300c..f7fee7d95 100644 --- a/crates/brk_computer/src/grouped/value_from_height.rs +++ b/crates/brk_computer/src/grouped/value_from_height.rs @@ -1,7 +1,7 @@ use allocative::Allocative; use brk_error::Result; use brk_structs::{Bitcoin, Dollars, Height, Sats, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{CollectableVec, Database, EagerVec, Exit, StoredVec}; use crate::{ @@ -13,7 +13,7 @@ use crate::{ use super::{ComputedVecsFromHeight, VecBuilderOptions}; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct ComputedValueVecsFromHeight { pub sats: ComputedVecsFromHeight, pub bitcoin: ComputedVecsFromHeight, diff --git a/crates/brk_computer/src/grouped/value_from_txindex.rs b/crates/brk_computer/src/grouped/value_from_txindex.rs index e39c3b80e..2c577c092 100644 --- a/crates/brk_computer/src/grouped/value_from_txindex.rs +++ b/crates/brk_computer/src/grouped/value_from_txindex.rs @@ -2,7 +2,7 @@ use allocative::Allocative; use brk_error::Result; use brk_indexer::Indexer; use brk_structs::{Bitcoin, Close, Dollars, Height, Sats, TxIndex, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyCloneableIterableVec, CollectableVec, Database, Exit, LazyVecFrom1, LazyVecFrom3, StoredIndex, StoredVec, @@ -12,7 +12,7 @@ use crate::{Indexes, grouped::Source, indexes, price}; use super::{ComputedVecsFromTxindex, VecBuilderOptions}; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct ComputedValueVecsFromTxindex { pub sats: ComputedVecsFromTxindex, pub bitcoin_txindex: LazyVecFrom1, diff --git a/crates/brk_computer/src/grouped/value_height.rs b/crates/brk_computer/src/grouped/value_height.rs index 9a6012b84..f46eb400a 100644 --- a/crates/brk_computer/src/grouped/value_height.rs +++ b/crates/brk_computer/src/grouped/value_height.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_structs::{Bitcoin, Dollars, Height, Sats, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{CollectableVec, Database, EagerVec, Exit, Format, StoredVec}; use crate::{ @@ -10,7 +10,7 @@ use crate::{ traits::{ComputeFromBitcoin, ComputeFromSats}, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct ComputedHeightValueVecs { pub sats: Option>, pub bitcoin: EagerVec, diff --git a/crates/brk_computer/src/indexes.rs b/crates/brk_computer/src/indexes.rs index 33e9664ac..91c205694 100644 --- a/crates/brk_computer/src/indexes.rs +++ b/crates/brk_computer/src/indexes.rs @@ -10,15 +10,15 @@ use brk_structs::{ P2WPKHBytes, P2WSHAddressIndex, P2WSHBytes, QuarterIndex, Sats, SemesterIndex, StoredU64, Timestamp, TxIndex, Txid, UnknownOutputIndex, Version, WeekIndex, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ - AnyCloneableIterableVec, AnyCollectableVec, Database, EagerVec, Exit, LazyVecFrom1, - LazyVecFrom2, PAGE_SIZE, StoredIndex, VecIterator, + AnyCloneableIterableVec, Database, EagerVec, Exit, LazyVecFrom1, LazyVecFrom2, PAGE_SIZE, + StoredIndex, VecIterator, }; const VERSION: Version = Version::ZERO; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -475,8 +475,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/lib.rs b/crates/brk_computer/src/lib.rs index e221f5da8..e353d954a 100644 --- a/crates/brk_computer/src/lib.rs +++ b/crates/brk_computer/src/lib.rs @@ -7,7 +7,7 @@ use brk_fetcher::Fetcher; use brk_indexer::Indexer; use brk_parser::Parser; use brk_structs::Version; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use log::info; use vecdb::{Exit, Format}; @@ -32,7 +32,7 @@ pub use pools::*; pub use states::PriceToAmount; use states::*; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Computer { pub chain: chain::Vecs, pub cointime: cointime::Vecs, diff --git a/crates/brk_computer/src/market.rs b/crates/brk_computer/src/market.rs index 3fc51c2a6..540e21830 100644 --- a/crates/brk_computer/src/market.rs +++ b/crates/brk_computer/src/market.rs @@ -2,7 +2,7 @@ use std::{path::Path, thread}; use brk_error::Result; use brk_structs::{Date, DateIndex, Dollars, Height, Sats, StoredF32, StoredU16, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{Database, EagerVec, Exit, PAGE_SIZE, StoredIndex, VecIterator}; use crate::{ @@ -17,7 +17,7 @@ use super::{ indexes, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -1516,8 +1516,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/pools/mod.rs b/crates/brk_computer/src/pools/mod.rs index 9df500894..508d11dae 100644 --- a/crates/brk_computer/src/pools/mod.rs +++ b/crates/brk_computer/src/pools/mod.rs @@ -5,7 +5,7 @@ use brk_error::Result; use brk_indexer::Indexer; use brk_store::AnyStore; use brk_structs::{AddressBytes, Height, OutputIndex, OutputType, PoolId, Pools, pools}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use rayon::prelude::*; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, PAGE_SIZE, RawVec, @@ -20,13 +20,13 @@ use crate::{ price, }; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct Vecs { db: Database, pools: &'static Pools, - height_to_pool: RawVec, - vecs: BTreeMap, + pub height_to_pool: RawVec, + pub vecs: BTreeMap, } impl Vecs { @@ -62,8 +62,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/pools/vecs.rs b/crates/brk_computer/src/pools/vecs.rs index c1a95ef70..553f60866 100644 --- a/crates/brk_computer/src/pools/vecs.rs +++ b/crates/brk_computer/src/pools/vecs.rs @@ -1,7 +1,7 @@ use allocative::Allocative; use brk_error::Result; use brk_structs::{Height, PoolId, Pools, Sats, StoredF32, StoredU16, StoredU32}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{AnyIterableVec, Database, Exit, StoredIndex, VecIterator, Version}; use crate::{ @@ -14,23 +14,23 @@ use crate::{ price, }; -#[derive(Clone, IVecs, Allocative)] +#[derive(Clone, Traversable, Allocative)] pub struct Vecs { id: PoolId, - indexes_to_blocks_mined: ComputedVecsFromHeight, - indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex, - indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex, - indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex, - indexes_to_subsidy: ComputedValueVecsFromHeight, - indexes_to_fee: ComputedValueVecsFromHeight, - indexes_to_coinbase: ComputedValueVecsFromHeight, - indexes_to_dominance: ComputedVecsFromDateIndex, - indexes_to_1d_dominance: ComputedVecsFromDateIndex, - indexes_to_1w_dominance: ComputedVecsFromDateIndex, - indexes_to_1m_dominance: ComputedVecsFromDateIndex, - indexes_to_1y_dominance: ComputedVecsFromDateIndex, - indexes_to_days_since_block: ComputedVecsFromDateIndex, + pub indexes_to_blocks_mined: ComputedVecsFromHeight, + pub indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex, + pub indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex, + pub indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex, + pub indexes_to_subsidy: ComputedValueVecsFromHeight, + pub indexes_to_fee: ComputedValueVecsFromHeight, + pub indexes_to_coinbase: ComputedValueVecsFromHeight, + pub indexes_to_dominance: ComputedVecsFromDateIndex, + pub indexes_to_1d_dominance: ComputedVecsFromDateIndex, + pub indexes_to_1w_dominance: ComputedVecsFromDateIndex, + pub indexes_to_1m_dominance: ComputedVecsFromDateIndex, + pub indexes_to_1y_dominance: ComputedVecsFromDateIndex, + pub indexes_to_days_since_block: ComputedVecsFromDateIndex, } impl Vecs { diff --git a/crates/brk_computer/src/price.rs b/crates/brk_computer/src/price.rs index 16cab0c17..1b1acab38 100644 --- a/crates/brk_computer/src/price.rs +++ b/crates/brk_computer/src/price.rs @@ -5,7 +5,7 @@ use brk_structs::{ Cents, Close, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, High, Low, MonthIndex, OHLCDollars, OHLCSats, Open, QuarterIndex, Sats, SemesterIndex, Version, WeekIndex, YearIndex, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, PAGE_SIZE, RawVec, @@ -19,7 +19,7 @@ use super::{ indexes, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -326,8 +326,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } diff --git a/crates/brk_computer/src/stateful/address_cohort.rs b/crates/brk_computer/src/stateful/address_cohort.rs index ca8734b5c..b5ba67333 100644 --- a/crates/brk_computer/src/stateful/address_cohort.rs +++ b/crates/brk_computer/src/stateful/address_cohort.rs @@ -2,7 +2,7 @@ use std::path::Path; use brk_error::Result; use brk_structs::{Bitcoin, DateIndex, Dollars, Height, StoredU64, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyIterableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, Format, GenericStoredVec, VecIterator, @@ -21,7 +21,7 @@ use crate::{ const VERSION: Version = Version::ZERO; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { starting_height: Option, diff --git a/crates/brk_computer/src/stateful/address_cohorts.rs b/crates/brk_computer/src/stateful/address_cohorts.rs index a762eb8e2..78e567bf8 100644 --- a/crates/brk_computer/src/stateful/address_cohorts.rs +++ b/crates/brk_computer/src/stateful/address_cohorts.rs @@ -3,9 +3,9 @@ use std::path::Path; use brk_error::Result; use brk_structs::{ AddressGroups, Bitcoin, ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount, DateIndex, - Dollars, GroupFilter, Height, Version, + Dollars, Filtered, Height, Version, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use derive_deref::{Deref, DerefMut}; use vecdb::{AnyIterableVec, Database, Exit, Format}; @@ -19,8 +19,8 @@ use crate::{ const VERSION: Version = Version::new(0); -#[derive(Clone, Deref, DerefMut, IVecs)] -pub struct Vecs(AddressGroups<(GroupFilter, address_cohort::Vecs)>); +#[derive(Clone, Deref, DerefMut, Traversable)] +pub struct Vecs(AddressGroups>); impl Vecs { pub fn forced_import( @@ -465,13 +465,13 @@ impl Vecs { self.0 .ge_amount .iter_mut() - .map(|(filter, vecs)| { + .map(|Filtered(filter, vecs)| { ( vecs, by_size_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) }) @@ -479,13 +479,13 @@ impl Vecs { self.0 .lt_amount .iter_mut() - .map(|(filter, vecs)| { + .map(|Filtered(filter, vecs)| { ( vecs, by_size_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) }) @@ -506,8 +506,8 @@ impl Vecs { exit: &Exit, ) -> Result<()> { self.iter_mut() - .into_iter() - .try_for_each(|(_, v)| v.compute_rest_part1(indexes, price, starting_indexes, exit)) + .map(Filtered::mut_t) + .try_for_each(|v| v.compute_rest_part1(indexes, price, starting_indexes, exit)) } #[allow(clippy::too_many_arguments)] @@ -524,7 +524,7 @@ impl Vecs { dateindex_to_realized_cap: Option<&impl AnyIterableVec>, exit: &Exit, ) -> Result<()> { - self.0.iter_mut().try_for_each(|(_, v)| { + self.0.iter_mut().map(Filtered::mut_t).try_for_each(|v| { v.compute_rest_part2( indexes, price, @@ -542,7 +542,7 @@ impl Vecs { pub fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> { self.iter_separate_mut() - .into_iter() - .try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit)) + .map(Filtered::mut_t) + .try_for_each(|v| v.safe_flush_stateful_vecs(height, exit)) } } diff --git a/crates/brk_computer/src/stateful/addresstype/height_to_addresscount.rs b/crates/brk_computer/src/stateful/addresstype/height_to_addresscount.rs index e2b7a0e05..1eb65c605 100644 --- a/crates/brk_computer/src/stateful/addresstype/height_to_addresscount.rs +++ b/crates/brk_computer/src/stateful/addresstype/height_to_addresscount.rs @@ -1,12 +1,12 @@ use brk_error::Result; use brk_structs::{ByAddressType, Height, StoredU64}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use derive_deref::{Deref, DerefMut}; use vecdb::{EagerVec, Exit, GenericStoredVec}; use super::AddressTypeToAddressCount; -#[derive(Debug, Clone, Deref, DerefMut, IVecs)] +#[derive(Debug, Clone, Deref, DerefMut, Traversable)] pub struct AddressTypeToHeightToAddressCount(ByAddressType>); impl From>> for AddressTypeToHeightToAddressCount { diff --git a/crates/brk_computer/src/stateful/addresstype/indexes_to_addresscount.rs b/crates/brk_computer/src/stateful/addresstype/indexes_to_addresscount.rs index dca26b0b2..256141c31 100644 --- a/crates/brk_computer/src/stateful/addresstype/indexes_to_addresscount.rs +++ b/crates/brk_computer/src/stateful/addresstype/indexes_to_addresscount.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_structs::{ByAddressType, StoredU64}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use derive_deref::{Deref, DerefMut}; use vecdb::Exit; @@ -8,7 +8,7 @@ use crate::{Indexes, grouped::ComputedVecsFromHeight, indexes}; use super::AddressTypeToHeightToAddressCount; -#[derive(Clone, Deref, DerefMut, IVecs)] +#[derive(Clone, Deref, DerefMut, Traversable)] pub struct AddressTypeToIndexesToAddressCount(ByAddressType>); impl From>> for AddressTypeToIndexesToAddressCount { diff --git a/crates/brk_computer/src/stateful/common.rs b/crates/brk_computer/src/stateful/common.rs index ac5692fdd..d34ae50c2 100644 --- a/crates/brk_computer/src/stateful/common.rs +++ b/crates/brk_computer/src/stateful/common.rs @@ -2,7 +2,7 @@ use brk_error::{Error, Result}; use brk_structs::{ Bitcoin, DateIndex, Dollars, Height, Sats, StoredF32, StoredF64, StoredU64, Version, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{ AnyCloneableIterableVec, AnyIterableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, Format, GenericStoredVec, VecIterator, @@ -18,7 +18,7 @@ use crate::{ states::CohortState, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { // Cumulative pub height_to_realized_cap: Option>, diff --git a/crates/brk_computer/src/stateful/mod.rs b/crates/brk_computer/src/stateful/mod.rs index f290b7d24..9d654089b 100644 --- a/crates/brk_computer/src/stateful/mod.rs +++ b/crates/brk_computer/src/stateful/mod.rs @@ -10,12 +10,12 @@ use brk_error::Result; use brk_indexer::Indexer; use brk_structs::{ AnyAddressDataIndexEnum, AnyAddressIndex, ByAddressType, ByAnyAddress, CheckedSub, DateIndex, - Dollars, EmptyAddressData, EmptyAddressIndex, Height, InputIndex, LoadedAddressData, + Dollars, EmptyAddressData, EmptyAddressIndex, Filtered, Height, InputIndex, LoadedAddressData, LoadedAddressIndex, OutputIndex, OutputType, P2AAddressIndex, P2PK33AddressIndex, P2PK65AddressIndex, P2PKHAddressIndex, P2SHAddressIndex, P2TRAddressIndex, P2WPKHAddressIndex, P2WSHAddressIndex, Sats, StoredU64, Timestamp, TypeIndex, Version, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use log::info; use rayon::prelude::*; use vecdb::{ @@ -50,7 +50,7 @@ use withaddressdatasource::*; const VERSION: Version = Version::new(21); -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, @@ -493,8 +493,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } @@ -601,10 +604,10 @@ impl Vecs { separate_utxo_vecs .par_iter_mut() - .try_for_each(|(_, v)| v.validate_computed_versions(base_version))?; + .try_for_each(|Filtered(_, v)| v.validate_computed_versions(base_version))?; separate_address_vecs .par_iter_mut() - .try_for_each(|(_, v)| v.validate_computed_versions(base_version))?; + .try_for_each(|Filtered(_, v)| v.validate_computed_versions(base_version))?; self.height_to_unspendable_supply .validate_computed_version_or_reset( base_version + self.height_to_unspendable_supply.inner_version(), @@ -617,13 +620,13 @@ impl Vecs { let mut chain_state_starting_height = Height::from(self.chain_state.len()); let stateful_starting_height = match separate_utxo_vecs .par_iter_mut() - .map(|(_, v)| Height::from(v.min_height_vecs_len())) + .map(|Filtered(_, v)| Height::from(v.min_height_vecs_len())) .min() .unwrap_or_default() .min( separate_address_vecs .par_iter_mut() - .map(|(_, v)| Height::from(v.min_height_vecs_len())) + .map(|Filtered(_, v)| Height::from(v.min_height_vecs_len())) .min() .unwrap_or_default(), ) @@ -707,7 +710,7 @@ impl Vecs { let starting_height = if starting_height.is_not_zero() && separate_utxo_vecs .iter_mut() - .map(|(_, v)| v.import_state(starting_height).unwrap_or_default()) + .map(|Filtered(_, v)| v.import_state(starting_height).unwrap_or_default()) .all(|h| h == starting_height) { starting_height @@ -719,7 +722,7 @@ impl Vecs { let starting_height = if starting_height.is_not_zero() && separate_address_vecs .iter_mut() - .map(|(_, v)| v.import_state(starting_height).unwrap_or_default()) + .map(|Filtered(_, v)| v.import_state(starting_height).unwrap_or_default()) .all(|h| h == starting_height) { starting_height @@ -767,14 +770,16 @@ impl Vecs { self.loadedaddressindex_to_loadedaddressdata.reset()?; self.emptyaddressindex_to_emptyaddressdata.reset()?; - separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| { - v.reset_state_starting_height(); - v.state.as_mut().unwrap().reset_price_to_amount_if_needed() - })?; + separate_utxo_vecs + .par_iter_mut() + .try_for_each(|Filtered(_, v)| { + v.reset_state_starting_height(); + v.state.as_mut().unwrap().reset_price_to_amount_if_needed() + })?; separate_address_vecs .par_iter_mut() - .try_for_each(|(_, v)| { + .try_for_each(|Filtered(_, v)| { v.reset_state_starting_height(); v.state.as_mut().unwrap().reset_price_to_amount_if_needed() })?; @@ -877,11 +882,11 @@ impl Vecs { self.utxo_cohorts .iter_separate_mut() - .for_each(|(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values()); + .for_each(|Filtered(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values()); self.address_cohorts .iter_separate_mut() - .for_each(|(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values()); + .for_each(|Filtered(_, v)| v.state.as_mut().unwrap().reset_single_iteration_values()); let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height); let price = height_to_price_close_iter @@ -1249,11 +1254,11 @@ impl Vecs { let dateindex = is_date_last_height.then_some(dateindex); self.utxo_cohorts.iter_separate_mut().par_bridge() - .map(|(_, v)| v as &mut dyn DynCohortVecs) + .map(|Filtered(_, v)| v as &mut dyn DynCohortVecs) .chain( self.address_cohorts.iter_separate_mut() .par_bridge() - .map(|(_, v)| v as &mut dyn DynCohortVecs), + .map(|Filtered(_, v)| v as &mut dyn DynCohortVecs), ) .try_for_each(|v| { v.forced_pushed_at(height, exit)?; @@ -1642,11 +1647,11 @@ impl Vecs { self.utxo_cohorts .iter_separate_mut() .par_bridge() - .try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?; + .try_for_each(|Filtered(_, v)| v.safe_flush_stateful_vecs(height, exit))?; self.address_cohorts .iter_separate_mut() .par_bridge() - .try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?; + .try_for_each(|Filtered(_, v)| v.safe_flush_stateful_vecs(height, exit))?; self.height_to_unspendable_supply.safe_flush(exit)?; self.height_to_opreturn_supply.safe_flush(exit)?; self.addresstype_to_height_to_addr_count diff --git a/crates/brk_computer/src/stateful/utxo_cohort.rs b/crates/brk_computer/src/stateful/utxo_cohort.rs index 491a600e2..f0ed7fd49 100644 --- a/crates/brk_computer/src/stateful/utxo_cohort.rs +++ b/crates/brk_computer/src/stateful/utxo_cohort.rs @@ -2,7 +2,7 @@ use std::{ops::Deref, path::Path}; use brk_error::Result; use brk_structs::{Bitcoin, DateIndex, Dollars, Height, Version}; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use vecdb::{AnyIterableVec, Database, Exit, Format}; use crate::{ @@ -13,14 +13,14 @@ use crate::{ }, }; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { state_starting_height: Option, #[vecs(skip)] pub state: Option, - inner: common::Vecs, + pub inner: common::Vecs, } impl Vecs { diff --git a/crates/brk_computer/src/stateful/utxo_cohorts.rs b/crates/brk_computer/src/stateful/utxo_cohorts.rs index 3a44b7f71..e55896f24 100644 --- a/crates/brk_computer/src/stateful/utxo_cohorts.rs +++ b/crates/brk_computer/src/stateful/utxo_cohorts.rs @@ -3,10 +3,10 @@ use std::{collections::BTreeMap, ops::ControlFlow, path::Path}; use brk_error::Result; use brk_structs::{ Bitcoin, ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, - ByMinAge, BySpendableType, ByTerm, CheckedSub, DateIndex, Dollars, GroupFilter, HalvingEpoch, - Height, Timestamp, UTXOGroups, Version, + ByMinAge, BySpendableType, ByTerm, CheckedSub, DateIndex, Dollars, Filter, Filtered, + HalvingEpoch, Height, Timestamp, UTXOGroups, Version, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use derive_deref::{Deref, DerefMut}; use vecdb::{AnyIterableVec, Database, Exit, Format, StoredIndex}; @@ -20,8 +20,8 @@ use super::{r#trait::CohortVecs, utxo_cohort}; const VERSION: Version = Version::new(0); -#[derive(Clone, Deref, DerefMut, IVecs)] -pub struct Vecs(UTXOGroups<(GroupFilter, utxo_cohort::Vecs)>); +#[derive(Clone, Deref, DerefMut, Traversable)] +pub struct Vecs(UTXOGroups>); impl Vecs { pub fn forced_import( @@ -1459,7 +1459,7 @@ impl Vecs { let mut vecs = self .age_range .iter_mut() - .map(|(filter, v)| (filter, &mut v.state)) + .map(|Filtered(filter, v)| (filter, &mut v.state)) .collect::>(); let _ = chain_state @@ -1531,14 +1531,14 @@ impl Vecs { time_based_vecs .iter_mut() - .filter(|(filter, _)| match filter { - GroupFilter::GreaterOrEqual(from) => *from <= days_old, - GroupFilter::LowerThan(to) => *to > days_old, - GroupFilter::Range(range) => range.contains(&days_old), - GroupFilter::Epoch(epoch) => *epoch == HalvingEpoch::from(height), + .filter(|Filtered(filter, _)| match filter { + Filter::GreaterOrEqual(from) => *from <= days_old, + Filter::LowerThan(to) => *to > days_old, + Filter::Range(range) => range.contains(&days_old), + Filter::Epoch(epoch) => *epoch == HalvingEpoch::from(height), _ => unreachable!(), }) - .for_each(|(_, vecs)| { + .for_each(|Filtered(_, vecs)| { vecs.state.as_mut().unwrap().send( &sent.spendable_supply, current_price, @@ -1604,9 +1604,9 @@ impl Vecs { v.state.as_mut().unwrap().receive(&supply_state, price); }); - self._type.iter_mut().for_each(|(filter, vecs)| { + self._type.iter_mut().for_each(|Filtered(filter, vecs)| { let output_type = match filter { - GroupFilter::Type(output_type) => *output_type, + Filter::Type(output_type) => *output_type, _ => unreachable!(), }; vecs.state @@ -1639,56 +1639,56 @@ impl Vecs { [( &mut self.0.all.1, - by_date_range.iter().map(|(_, v)| v).collect::>(), + by_date_range.iter().map(Filtered::t).collect::>(), )] .into_iter() - .chain(self.0.min_age.iter_mut().map(|(filter, vecs)| { + .chain(self.0.min_age.iter_mut().map(|Filtered(filter, vecs)| { ( vecs, by_date_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) })) - .chain(self.0.max_age.iter_mut().map(|(filter, vecs)| { + .chain(self.0.max_age.iter_mut().map(|Filtered(filter, vecs)| { ( vecs, by_date_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) })) - .chain(self.0.term.iter_mut().map(|(filter, vecs)| { + .chain(self.0.term.iter_mut().map(|Filtered(filter, vecs)| { ( vecs, by_date_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) })) - .chain(self.0.ge_amount.iter_mut().map(|(filter, vecs)| { + .chain(self.0.ge_amount.iter_mut().map(|Filtered(filter, vecs)| { ( vecs, by_size_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) })) - .chain(self.0.lt_amount.iter_mut().map(|(filter, vecs)| { + .chain(self.0.lt_amount.iter_mut().map(|Filtered(filter, vecs)| { ( vecs, by_size_range .iter() - .filter(|(other, _)| filter.includes(other)) - .map(|(_, v)| v) + .filter(|other| other.includes(filter)) + .map(Filtered::t) .collect::>(), ) })) @@ -1705,8 +1705,8 @@ impl Vecs { exit: &Exit, ) -> Result<()> { self.iter_mut() - .into_iter() - .try_for_each(|(_, v)| v.compute_rest_part1(indexes, price, starting_indexes, exit)) + .map(Filtered::mut_t) + .try_for_each(|v| v.compute_rest_part1(indexes, price, starting_indexes, exit)) } #[allow(clippy::too_many_arguments)] @@ -1723,7 +1723,7 @@ impl Vecs { dateindex_to_realized_cap: Option<&impl AnyIterableVec>, exit: &Exit, ) -> Result<()> { - self.iter_mut().into_iter().try_for_each(|(_, v)| { + self.iter_mut().map(Filtered::mut_t).try_for_each(|v| { v.compute_rest_part2( indexes, price, @@ -1741,6 +1741,7 @@ impl Vecs { pub fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> { self.iter_separate_mut() - .try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit)) + .map(Filtered::mut_t) + .try_for_each(|v| v.safe_flush_stateful_vecs(height, exit)) } } diff --git a/crates/brk_indexer/Cargo.toml b/crates/brk_indexer/Cargo.toml index a7b643c74..5df0c3a1b 100644 --- a/crates/brk_indexer/Cargo.toml +++ b/crates/brk_indexer/Cargo.toml @@ -17,7 +17,7 @@ brk_error = { workspace = true } brk_logger = { workspace = true } brk_parser = { workspace = true } brk_store = { workspace = true } -brk_vecs = { workspace = true } +brk_traversable = { workspace = true } vecdb = { workspace = true } fjall = { workspace = true } log = { workspace = true } diff --git a/crates/brk_indexer/examples/indexer.rs b/crates/brk_indexer/examples/indexer.rs index ea30f8156..f2ab4072c 100644 --- a/crates/brk_indexer/examples/indexer.rs +++ b/crates/brk_indexer/examples/indexer.rs @@ -8,7 +8,6 @@ use std::{ use brk_error::Result; use brk_indexer::Indexer; use brk_parser::Parser; -// use brk_vecs::IVecs; use vecdb::Exit; fn main() -> Result<()> { @@ -40,7 +39,8 @@ fn main() -> Result<()> { let mut indexer = Indexer::forced_import(&outputs_dir)?; - // let vecs = indexer.vecs.iter().collect::>(); + // 44 + // let vecs = indexer.vecs.iter_any_collectable().collect::>(); // dbg!(indexer.vecs.to_tree_node()); // dbg!(vecs.len()); // std::process::exit(0); diff --git a/crates/brk_indexer/src/vecs.rs b/crates/brk_indexer/src/vecs.rs index 2b38748f7..9159427f4 100644 --- a/crates/brk_indexer/src/vecs.rs +++ b/crates/brk_indexer/src/vecs.rs @@ -9,16 +9,13 @@ use brk_structs::{ RawLockTime, Sats, StoredBool, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Txid, TypeIndex, UnknownOutputIndex, Version, Weight, }; -use brk_vecs::IVecs; +use brk_traversable::Traversable; use rayon::prelude::*; -use vecdb::{ - AnyCollectableVec, AnyStoredVec, CompressedVec, Database, GenericStoredVec, PAGE_SIZE, RawVec, - Stamp, -}; +use vecdb::{AnyStoredVec, CompressedVec, Database, GenericStoredVec, PAGE_SIZE, RawVec, Stamp}; use crate::Indexes; -#[derive(Clone, IVecs)] +#[derive(Clone, Traversable)] pub struct Vecs { db: Database, pub emptyoutputindex_to_txindex: CompressedVec, @@ -194,8 +191,11 @@ impl Vecs { db, }; - this.db - .retain_regions(this.iter().flat_map(|v| v.region_names()).collect())?; + this.db.retain_regions( + this.iter_any_collectable() + .flat_map(|v| v.region_names()) + .collect(), + )?; Ok(this) } @@ -369,7 +369,7 @@ impl Vecs { Ok(()) } - // pub fn iter(&self) -> impl Iterator { + // pub fn iter_any_collectable(&self) -> impl Iterator { // [ // &self.emptyoutputindex_to_txindex as &dyn AnyCollectableVec, // &self.height_to_blockhash, diff --git a/crates/brk_interface/Cargo.toml b/crates/brk_interface/Cargo.toml index 57d79a355..79a402de4 100644 --- a/crates/brk_interface/Cargo.toml +++ b/crates/brk_interface/Cargo.toml @@ -16,6 +16,7 @@ brk_error = { workspace = true } brk_indexer = { workspace = true } brk_parser = { workspace = true } brk_structs = { workspace = true } +brk_traversable = { workspace = true } vecdb = { workspace = true } derive_deref = { workspace = true } quick_cache = { workspace = true } diff --git a/crates/brk_interface/src/lib.rs b/crates/brk_interface/src/lib.rs index 8a612b0e0..75c91d074 100644 --- a/crates/brk_interface/src/lib.rs +++ b/crates/brk_interface/src/lib.rs @@ -7,6 +7,7 @@ use brk_error::{Error, Result}; use brk_indexer::Indexer; use brk_parser::Parser; use brk_structs::Height; +use brk_traversable::TreeNode; use nucleo_matcher::{ Config, Matcher, pattern::{AtomKind, CaseMatching, Normalization, Pattern}, @@ -243,6 +244,10 @@ impl<'a> Interface<'a> { self.vecs.metrics(pagination) } + pub fn get_metrics_catalog(&self) -> &TreeNode { + self.vecs.catalog.as_ref().unwrap() + } + pub fn get_index_to_vecids(&self, paginated_index: PaginatedIndexParam) -> Vec<&str> { self.vecs.index_to_ids(paginated_index) } diff --git a/crates/brk_interface/src/vecs.rs b/crates/brk_interface/src/vecs.rs index 05aecbeff..b3873a1c0 100644 --- a/crates/brk_interface/src/vecs.rs +++ b/crates/brk_interface/src/vecs.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use brk_computer::Computer; use brk_indexer::Indexer; +use brk_traversable::{Traversable, TreeNode}; use derive_deref::{Deref, DerefMut}; use vecdb::AnyCollectableVec; @@ -17,6 +18,7 @@ pub struct Vecs<'a> { pub indexes: BTreeMap<&'static str, &'static [&'static str]>, pub distinct_metric_count: usize, pub total_metric_count: usize, + pub catalog: Option, metric_to_indexes: BTreeMap<&'a str, Vec<&'static str>>, index_to_metrics: BTreeMap>, } @@ -25,7 +27,10 @@ impl<'a> Vecs<'a> { pub fn build(indexer: &'a Indexer, computer: &'a Computer) -> Self { let mut this = Vecs::default(); - indexer.vecs.iter().for_each(|vec| this.insert(vec)); + indexer + .vecs + .iter_any_collectable() + .for_each(|vec| this.insert(vec)); computer .iter_any_collectable() @@ -83,6 +88,14 @@ impl<'a> Vecs<'a> { this.index_to_metrics .values_mut() .for_each(|ids| sort_ids(ids)); + this.catalog.replace(TreeNode::Branch( + [ + ("indexer".to_string(), indexer.vecs.to_tree_node()), + ("computer".to_string(), computer.to_tree_node()), + ] + .into_iter() + .collect(), + )); this } diff --git a/crates/brk_server/src/api/metrics/mod.rs b/crates/brk_server/src/api/metrics/mod.rs index d060ad582..377ada6c4 100644 --- a/crates/brk_server/src/api/metrics/mod.rs +++ b/crates/brk_server/src/api/metrics/mod.rs @@ -5,7 +5,7 @@ use axum::{ response::{IntoResponse, Response}, routing::get, }; -use brk_interface::{Index, PaginatedIndexParam, PaginationParam, Params, ParamsDeprec, ParamsOpt}; +use brk_interface::{Index, PaginationParam, Params, ParamsDeprec, ParamsOpt}; use super::AppState; @@ -35,6 +35,12 @@ impl ApiMetricsRoutes for Router { Json(app_state.interface.get_indexes()).into_response() }), ) + .route( + "/api/metrics/catalog", + get(async |State(app_state): State| -> Response { + Json(app_state.interface.get_metrics_catalog()).into_response() + }), + ) .route( "/api/metrics/list", get( diff --git a/crates/brk_structs/Cargo.toml b/crates/brk_structs/Cargo.toml index a518eaab6..c52514ce9 100644 --- a/crates/brk_structs/Cargo.toml +++ b/crates/brk_structs/Cargo.toml @@ -14,7 +14,7 @@ allocative = { workspace = true } bitcoin = { workspace = true } bitcoincore-rpc = { workspace = true } brk_error = { workspace = true } -brk_vecs = { workspace = true } +brk_traversable = { workspace = true } byteview = { workspace = true } derive_deref = { workspace = true } itoa = "1.0.15" diff --git a/crates/brk_structs/src/groups/address.rs b/crates/brk_structs/src/groups/address.rs index 7edde0664..258fda992 100644 --- a/crates/brk_structs/src/groups/address.rs +++ b/crates/brk_structs/src/groups/address.rs @@ -1,9 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use super::{ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount, GroupFilter}; +use crate::Filtered; -#[derive(Default, Clone)] +use super::{ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount}; + +#[derive(Default, Clone, Traversable)] pub struct AddressGroups { pub ge_amount: ByGreatEqualAmount, pub amount_range: ByAmountRange, @@ -27,7 +28,7 @@ impl AddressGroups { } } -impl AddressGroups<(GroupFilter, T)> { +impl AddressGroups> { pub fn iter_right(&self) -> impl Iterator { self.amount_range .iter_right() @@ -36,7 +37,7 @@ impl AddressGroups<(GroupFilter, T)> { } } -impl From> for AddressGroups<(GroupFilter, T)> { +impl From> for AddressGroups> { fn from(value: AddressGroups) -> Self { Self { amount_range: ByAmountRange::from(value.amount_range), @@ -45,26 +46,3 @@ impl From> for AddressGroups<(GroupFilter, T)> { } } } - -impl IVecs for AddressGroups<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("ge_amount", self.ge_amount.to_tree_node()), - ("amount_range", self.amount_range.to_tree_node()), - ("lt_amount", self.lt_amount.to_tree_node()), - ] - .into_iter() - .map(|(name, node)| (name.to_string(), node)) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.ge_amount.iter()); - iter = Box::new(iter.chain(IVecs::iter(&self.amount_range))); - iter = Box::new(iter.chain(self.lt_amount.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_address_type.rs b/crates/brk_structs/src/groups/by_address_type.rs index c7ccd41c7..a4df4b049 100644 --- a/crates/brk_structs/src/groups/by_address_type.rs +++ b/crates/brk_structs/src/groups/by_address_type.rs @@ -1,10 +1,10 @@ use std::ops::{Add, AddAssign}; -use brk_vecs::{IVecs, TreeNode}; +use brk_traversable::{Traversable, TreeNode}; use vecdb::AnyCollectableVec; -use super::GroupFilter; -use crate::OutputType; +use super::Filter; +use crate::{Filtered, OutputType}; #[derive(Default, Clone, Debug)] pub struct ByAddressType { @@ -122,7 +122,7 @@ impl ByAddressType { } } -impl ByAddressType<(GroupFilter, T)> { +impl ByAddressType> { pub fn iter_right(&self) -> impl Iterator { [ &self.p2pk65.1, @@ -138,17 +138,17 @@ impl ByAddressType<(GroupFilter, T)> { } } -impl From> for ByAddressType<(GroupFilter, T)> { +impl From> for ByAddressType> { fn from(value: ByAddressType) -> Self { Self { - p2pk65: (GroupFilter::Type(OutputType::P2PK65), value.p2pk65), - p2pk33: (GroupFilter::Type(OutputType::P2PK33), value.p2pk33), - p2pkh: (GroupFilter::Type(OutputType::P2PKH), value.p2pkh), - p2sh: (GroupFilter::Type(OutputType::P2SH), value.p2sh), - p2wpkh: (GroupFilter::Type(OutputType::P2WPKH), value.p2wpkh), - p2wsh: (GroupFilter::Type(OutputType::P2WSH), value.p2wsh), - p2tr: (GroupFilter::Type(OutputType::P2TR), value.p2tr), - p2a: (GroupFilter::Type(OutputType::P2A), value.p2a), + p2pk65: (Filter::Type(OutputType::P2PK65), value.p2pk65).into(), + p2pk33: (Filter::Type(OutputType::P2PK33), value.p2pk33).into(), + p2pkh: (Filter::Type(OutputType::P2PKH), value.p2pkh).into(), + p2sh: (Filter::Type(OutputType::P2SH), value.p2sh).into(), + p2wpkh: (Filter::Type(OutputType::P2WPKH), value.p2wpkh).into(), + p2wsh: (Filter::Type(OutputType::P2WSH), value.p2wsh).into(), + p2tr: (Filter::Type(OutputType::P2TR), value.p2tr).into(), + p2a: (Filter::Type(OutputType::P2A), value.p2a).into(), } } } @@ -196,41 +196,7 @@ impl ByAddressType> { } } -impl IVecs for ByAddressType { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("p2pk65", &self.p2pk65), - ("p2pk33", &self.p2pk33), - ("p2pkh", &self.p2pkh), - ("p2sh", &self.p2sh), - ("p2wpkh", &self.p2wpkh), - ("p2wsh", &self.p2wsh), - ("p2tr", &self.p2tr), - ("p2a", &self.p2a), - ] - .into_iter() - .map(|(name, field)| (name.to_string(), TreeNode::Leaf(field.name().to_string()))) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - [ - &self.p2pk65 as &dyn AnyCollectableVec, - &self.p2pk33, - &self.p2pkh, - &self.p2sh, - &self.p2wpkh, - &self.p2wsh, - &self.p2tr, - &self.p2a, - ] - .into_iter() - } -} - -impl IVecs for ByAddressType { +impl Traversable for ByAddressType { fn to_tree_node(&self) -> TreeNode { TreeNode::Branch( [ @@ -249,16 +215,16 @@ impl IVecs for ByAddressType { ) } - fn iter(&self) -> impl Iterator { + fn iter_any_collectable(&self) -> impl Iterator { let mut iter: Box> = - Box::new(self.p2pk65.iter()); - iter = Box::new(iter.chain(self.p2pk33.iter())); - iter = Box::new(iter.chain(self.p2pkh.iter())); - iter = Box::new(iter.chain(self.p2sh.iter())); - iter = Box::new(iter.chain(self.p2wpkh.iter())); - iter = Box::new(iter.chain(self.p2wsh.iter())); - iter = Box::new(iter.chain(self.p2tr.iter())); - iter = Box::new(iter.chain(self.p2a.iter())); + Box::new(self.p2pk65.iter_any_collectable()); + iter = Box::new(iter.chain(self.p2pk33.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2pkh.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2sh.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2wpkh.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2wsh.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2tr.iter_any_collectable())); + iter = Box::new(iter.chain(self.p2a.iter_any_collectable())); iter } } diff --git a/crates/brk_structs/src/groups/by_age_range.rs b/crates/brk_structs/src/groups/by_age_range.rs index bbc003e88..d3b1fb069 100644 --- a/crates/brk_structs/src/groups/by_age_range.rs +++ b/crates/brk_structs/src/groups/by_age_range.rs @@ -1,9 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use super::GroupFilter; +use crate::Filtered; -#[derive(Default, Clone)] +use super::Filter; + +#[derive(Default, Clone, Traversable)] pub struct ByAgeRange { pub up_to_1d: T, pub _1d_to_1w: T, @@ -27,29 +28,29 @@ pub struct ByAgeRange { pub from_15y: T, } -impl From> for ByAgeRange<(GroupFilter, T)> { +impl From> for ByAgeRange> { fn from(value: ByAgeRange) -> Self { Self { - up_to_1d: (GroupFilter::LowerThan(1), value.up_to_1d), - _1d_to_1w: (GroupFilter::Range(1..7), value._1d_to_1w), - _1w_to_1m: (GroupFilter::Range(7..30), value._1w_to_1m), - _1m_to_2m: (GroupFilter::Range(30..2 * 30), value._1m_to_2m), - _2m_to_3m: (GroupFilter::Range(2 * 30..3 * 30), value._2m_to_3m), - _3m_to_4m: (GroupFilter::Range(3 * 30..4 * 30), value._3m_to_4m), - _4m_to_5m: (GroupFilter::Range(4 * 30..5 * 30), value._4m_to_5m), - _5m_to_6m: (GroupFilter::Range(5 * 30..6 * 30), value._5m_to_6m), - _6m_to_1y: (GroupFilter::Range(6 * 30..365), value._6m_to_1y), - _1y_to_2y: (GroupFilter::Range(365..2 * 365), value._1y_to_2y), - _2y_to_3y: (GroupFilter::Range(2 * 365..3 * 365), value._2y_to_3y), - _3y_to_4y: (GroupFilter::Range(3 * 365..4 * 365), value._3y_to_4y), - _4y_to_5y: (GroupFilter::Range(4 * 365..5 * 365), value._4y_to_5y), - _5y_to_6y: (GroupFilter::Range(5 * 365..6 * 365), value._5y_to_6y), - _6y_to_7y: (GroupFilter::Range(6 * 365..7 * 365), value._6y_to_7y), - _7y_to_8y: (GroupFilter::Range(7 * 365..8 * 365), value._7y_to_8y), - _8y_to_10y: (GroupFilter::Range(8 * 365..10 * 365), value._8y_to_10y), - _10y_to_12y: (GroupFilter::Range(10 * 365..12 * 365), value._10y_to_12y), - _12y_to_15y: (GroupFilter::Range(12 * 365..15 * 365), value._12y_to_15y), - from_15y: (GroupFilter::GreaterOrEqual(15 * 365), value.from_15y), + up_to_1d: (Filter::LowerThan(1), value.up_to_1d).into(), + _1d_to_1w: (Filter::Range(1..7), value._1d_to_1w).into(), + _1w_to_1m: (Filter::Range(7..30), value._1w_to_1m).into(), + _1m_to_2m: (Filter::Range(30..2 * 30), value._1m_to_2m).into(), + _2m_to_3m: (Filter::Range(2 * 30..3 * 30), value._2m_to_3m).into(), + _3m_to_4m: (Filter::Range(3 * 30..4 * 30), value._3m_to_4m).into(), + _4m_to_5m: (Filter::Range(4 * 30..5 * 30), value._4m_to_5m).into(), + _5m_to_6m: (Filter::Range(5 * 30..6 * 30), value._5m_to_6m).into(), + _6m_to_1y: (Filter::Range(6 * 30..365), value._6m_to_1y).into(), + _1y_to_2y: (Filter::Range(365..2 * 365), value._1y_to_2y).into(), + _2y_to_3y: (Filter::Range(2 * 365..3 * 365), value._2y_to_3y).into(), + _3y_to_4y: (Filter::Range(3 * 365..4 * 365), value._3y_to_4y).into(), + _4y_to_5y: (Filter::Range(4 * 365..5 * 365), value._4y_to_5y).into(), + _5y_to_6y: (Filter::Range(5 * 365..6 * 365), value._5y_to_6y).into(), + _6y_to_7y: (Filter::Range(6 * 365..7 * 365), value._6y_to_7y).into(), + _7y_to_8y: (Filter::Range(7 * 365..8 * 365), value._7y_to_8y).into(), + _8y_to_10y: (Filter::Range(8 * 365..10 * 365), value._8y_to_10y).into(), + _10y_to_12y: (Filter::Range(10 * 365..12 * 365), value._10y_to_12y).into(), + _12y_to_15y: (Filter::Range(12 * 365..15 * 365), value._12y_to_15y).into(), + from_15y: (Filter::GreaterOrEqual(15 * 365), value.from_15y).into(), } } } @@ -108,7 +109,7 @@ impl ByAgeRange { } } -impl ByAgeRange<(GroupFilter, T)> { +impl ByAgeRange> { pub fn iter_right(&self) -> impl Iterator { [ &self.up_to_1d.1, @@ -135,60 +136,3 @@ impl ByAgeRange<(GroupFilter, T)> { .into_iter() } } - -impl IVecs for ByAgeRange<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("up_to_1d", &self.up_to_1d), - ("1d_to_1w", &self._1d_to_1w), - ("1w_to_1m", &self._1w_to_1m), - ("1m_to_2m", &self._1m_to_2m), - ("2m_to_3m", &self._2m_to_3m), - ("3m_to_4m", &self._3m_to_4m), - ("4m_to_5m", &self._4m_to_5m), - ("5m_to_6m", &self._5m_to_6m), - ("6m_to_1y", &self._6m_to_1y), - ("1y_to_2y", &self._1y_to_2y), - ("2y_to_3y", &self._2y_to_3y), - ("3y_to_4y", &self._3y_to_4y), - ("4y_to_5y", &self._4y_to_5y), - ("5y_to_6y", &self._5y_to_6y), - ("6y_to_7y", &self._6y_to_7y), - ("7y_to_8y", &self._7y_to_8y), - ("8y_to_10y", &self._8y_to_10y), - ("10y_to_12y", &self._10y_to_12y), - ("12y_to_15y", &self._12y_to_15y), - ("from_15y", &self.from_15y), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.up_to_1d.1.iter()); - iter = Box::new(iter.chain(self._1d_to_1w.1.iter())); - iter = Box::new(iter.chain(self._1w_to_1m.1.iter())); - iter = Box::new(iter.chain(self._1m_to_2m.1.iter())); - iter = Box::new(iter.chain(self._2m_to_3m.1.iter())); - iter = Box::new(iter.chain(self._3m_to_4m.1.iter())); - iter = Box::new(iter.chain(self._4m_to_5m.1.iter())); - iter = Box::new(iter.chain(self._5m_to_6m.1.iter())); - iter = Box::new(iter.chain(self._6m_to_1y.1.iter())); - iter = Box::new(iter.chain(self._1y_to_2y.1.iter())); - iter = Box::new(iter.chain(self._2y_to_3y.1.iter())); - iter = Box::new(iter.chain(self._3y_to_4y.1.iter())); - iter = Box::new(iter.chain(self._4y_to_5y.1.iter())); - iter = Box::new(iter.chain(self._5y_to_6y.1.iter())); - iter = Box::new(iter.chain(self._6y_to_7y.1.iter())); - iter = Box::new(iter.chain(self._7y_to_8y.1.iter())); - iter = Box::new(iter.chain(self._8y_to_10y.1.iter())); - iter = Box::new(iter.chain(self._10y_to_12y.1.iter())); - iter = Box::new(iter.chain(self._12y_to_15y.1.iter())); - iter = Box::new(iter.chain(self.from_15y.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_amount_range.rs b/crates/brk_structs/src/groups/by_amount_range.rs index b24866c41..5068d33ae 100644 --- a/crates/brk_structs/src/groups/by_amount_range.rs +++ b/crates/brk_structs/src/groups/by_amount_range.rs @@ -1,13 +1,12 @@ use std::ops::{Add, AddAssign}; -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use crate::Sats; +use crate::{Filtered, Sats}; -use super::GroupFilter; +use super::Filter; -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default, Clone, Traversable)] pub struct ByAmountRange { pub _0sats: T, pub _1sat_to_10sats: T, @@ -26,67 +25,81 @@ pub struct ByAmountRange { pub _100k_btc_or_more: T, } -impl From> for ByAmountRange<(GroupFilter, T)> { +impl From> for ByAmountRange> { fn from(value: ByAmountRange) -> Self { #[allow(clippy::inconsistent_digit_grouping)] Self { - _0sats: (GroupFilter::LowerThan(Sats::_1.into()), value._0sats), + _0sats: (Filter::LowerThan(Sats::_1.into()), value._0sats).into(), _1sat_to_10sats: ( - GroupFilter::Range(Sats::_1.into()..Sats::_10.into()), + Filter::Range(Sats::_1.into()..Sats::_10.into()), value._1sat_to_10sats, - ), + ) + .into(), _10sats_to_100sats: ( - GroupFilter::Range(Sats::_10.into()..Sats::_100.into()), + Filter::Range(Sats::_10.into()..Sats::_100.into()), value._10sats_to_100sats, - ), + ) + .into(), _100sats_to_1k_sats: ( - GroupFilter::Range(Sats::_100.into()..Sats::_1K.into()), + Filter::Range(Sats::_100.into()..Sats::_1K.into()), value._100sats_to_1k_sats, - ), + ) + .into(), _1k_sats_to_10k_sats: ( - GroupFilter::Range(Sats::_1K.into()..Sats::_10K.into()), + Filter::Range(Sats::_1K.into()..Sats::_10K.into()), value._1k_sats_to_10k_sats, - ), + ) + .into(), _10k_sats_to_100k_sats: ( - GroupFilter::Range(Sats::_10K.into()..Sats::_100K.into()), + Filter::Range(Sats::_10K.into()..Sats::_100K.into()), value._10k_sats_to_100k_sats, - ), + ) + .into(), _100k_sats_to_1m_sats: ( - GroupFilter::Range(Sats::_100K.into()..Sats::_1M.into()), + Filter::Range(Sats::_100K.into()..Sats::_1M.into()), value._100k_sats_to_1m_sats, - ), + ) + .into(), _1m_sats_to_10m_sats: ( - GroupFilter::Range(Sats::_1M.into()..Sats::_10M.into()), + Filter::Range(Sats::_1M.into()..Sats::_10M.into()), value._1m_sats_to_10m_sats, - ), + ) + .into(), _10m_sats_to_1btc: ( - GroupFilter::Range(Sats::_10M.into()..Sats::_1BTC.into()), + Filter::Range(Sats::_10M.into()..Sats::_1BTC.into()), value._10m_sats_to_1btc, - ), + ) + .into(), _1btc_to_10btc: ( - GroupFilter::Range(Sats::_1BTC.into()..Sats::_10BTC.into()), + Filter::Range(Sats::_1BTC.into()..Sats::_10BTC.into()), value._1btc_to_10btc, - ), + ) + .into(), _10btc_to_100btc: ( - GroupFilter::Range(Sats::_10BTC.into()..Sats::_100BTC.into()), + Filter::Range(Sats::_10BTC.into()..Sats::_100BTC.into()), value._10btc_to_100btc, - ), + ) + .into(), _100btc_to_1k_btc: ( - GroupFilter::Range(Sats::_100BTC.into()..Sats::_1K_BTC.into()), + Filter::Range(Sats::_100BTC.into()..Sats::_1K_BTC.into()), value._100btc_to_1k_btc, - ), + ) + .into(), _1k_btc_to_10k_btc: ( - GroupFilter::Range(Sats::_1K_BTC.into()..Sats::_10K_BTC.into()), + Filter::Range(Sats::_1K_BTC.into()..Sats::_10K_BTC.into()), value._1k_btc_to_10k_btc, - ), + ) + .into(), _10k_btc_to_100k_btc: ( - GroupFilter::Range(Sats::_10K_BTC.into()..Sats::_100K_BTC.into()), + Filter::Range(Sats::_10K_BTC.into()..Sats::_100K_BTC.into()), value._10k_btc_to_100k_btc, - ), + ) + .into(), _100k_btc_or_more: ( - GroupFilter::GreaterOrEqual(Sats::_100K_BTC.into()), + Filter::GreaterOrEqual(Sats::_100K_BTC.into()), value._100k_btc_or_more, - ), + ) + .into(), } } } @@ -191,7 +204,7 @@ impl ByAmountRange { } } -impl ByAmountRange<(GroupFilter, T)> { +impl ByAmountRange> { pub fn iter_right(&self) -> impl Iterator { [ &self._0sats.1, @@ -262,50 +275,3 @@ where self._100k_btc_or_more += rhs._100k_btc_or_more; } } - -impl IVecs for ByAmountRange<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("0sats", &self._0sats), - ("1sat_to_10sats", &self._1sat_to_10sats), - ("10sats_to_100sats", &self._10sats_to_100sats), - ("100sats_to_1k_sats", &self._100sats_to_1k_sats), - ("1k_sats_to_10k_sats", &self._1k_sats_to_10k_sats), - ("10k_sats_to_100k_sats", &self._10k_sats_to_100k_sats), - ("100k_sats_to_1m_sats", &self._100k_sats_to_1m_sats), - ("1m_sats_to_10m_sats", &self._1m_sats_to_10m_sats), - ("10m_sats_to_1btc", &self._10m_sats_to_1btc), - ("1btc_to_10btc", &self._1btc_to_10btc), - ("10btc_to_100btc", &self._10btc_to_100btc), - ("100btc_to_1k_btc", &self._100btc_to_1k_btc), - ("1k_btc_to_10k_btc", &self._1k_btc_to_10k_btc), - ("10k_btc_to_100k_btc", &self._10k_btc_to_100k_btc), - ("100k_btc_or_more", &self._100k_btc_or_more), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self._0sats.1.iter()); - iter = Box::new(iter.chain(self._1sat_to_10sats.1.iter())); - iter = Box::new(iter.chain(self._10sats_to_100sats.1.iter())); - iter = Box::new(iter.chain(self._100sats_to_1k_sats.1.iter())); - iter = Box::new(iter.chain(self._1k_sats_to_10k_sats.1.iter())); - iter = Box::new(iter.chain(self._10k_sats_to_100k_sats.1.iter())); - iter = Box::new(iter.chain(self._100k_sats_to_1m_sats.1.iter())); - iter = Box::new(iter.chain(self._1m_sats_to_10m_sats.1.iter())); - iter = Box::new(iter.chain(self._10m_sats_to_1btc.1.iter())); - iter = Box::new(iter.chain(self._1btc_to_10btc.1.iter())); - iter = Box::new(iter.chain(self._10btc_to_100btc.1.iter())); - iter = Box::new(iter.chain(self._100btc_to_1k_btc.1.iter())); - iter = Box::new(iter.chain(self._1k_btc_to_10k_btc.1.iter())); - iter = Box::new(iter.chain(self._10k_btc_to_100k_btc.1.iter())); - iter = Box::new(iter.chain(self._100k_btc_or_more.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_any_address.rs b/crates/brk_structs/src/groups/by_any_address.rs index 0035c55b9..46607e3e2 100644 --- a/crates/brk_structs/src/groups/by_any_address.rs +++ b/crates/brk_structs/src/groups/by_any_address.rs @@ -1,7 +1,6 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -#[derive(Debug, Default)] +#[derive(Debug, Default, Traversable)] pub struct ByAnyAddress { pub loaded: T, pub empty: T, @@ -13,21 +12,3 @@ impl ByAnyAddress> { self.empty.take(); } } - -impl IVecs for ByAnyAddress { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [("loaded", &self.loaded), ("empty", &self.empty)] - .into_iter() - .map(|(name, field)| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.loaded.iter()); - iter = Box::new(iter.chain(self.empty.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_epoch.rs b/crates/brk_structs/src/groups/by_epoch.rs index 688c3b702..a352026fc 100644 --- a/crates/brk_structs/src/groups/by_epoch.rs +++ b/crates/brk_structs/src/groups/by_epoch.rs @@ -1,11 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use crate::{HalvingEpoch, Height}; +use crate::{Filtered, HalvingEpoch, Height}; -use super::GroupFilter; +use super::Filter; -#[derive(Default, Clone)] +#[derive(Default, Clone, Traversable)] pub struct ByEpoch { pub _0: T, pub _1: T, @@ -14,14 +13,14 @@ pub struct ByEpoch { pub _4: T, } -impl From> for ByEpoch<(GroupFilter, T)> { +impl From> for ByEpoch> { fn from(value: ByEpoch) -> Self { Self { - _0: (GroupFilter::Epoch(HalvingEpoch::new(0)), value._0), - _1: (GroupFilter::Epoch(HalvingEpoch::new(1)), value._1), - _2: (GroupFilter::Epoch(HalvingEpoch::new(2)), value._2), - _3: (GroupFilter::Epoch(HalvingEpoch::new(3)), value._3), - _4: (GroupFilter::Epoch(HalvingEpoch::new(4)), value._4), + _0: (Filter::Epoch(HalvingEpoch::new(0)), value._0).into(), + _1: (Filter::Epoch(HalvingEpoch::new(1)), value._1).into(), + _2: (Filter::Epoch(HalvingEpoch::new(2)), value._2).into(), + _3: (Filter::Epoch(HalvingEpoch::new(3)), value._3).into(), + _4: (Filter::Epoch(HalvingEpoch::new(4)), value._4).into(), } } } @@ -56,34 +55,8 @@ impl ByEpoch { } } -impl ByEpoch<(GroupFilter, T)> { +impl ByEpoch> { pub fn iter_right(&self) -> impl Iterator { [&self._0.1, &self._1.1, &self._2.1, &self._3.1, &self._4.1].into_iter() } } - -impl IVecs for ByEpoch<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("0", &self._0), - ("1", &self._1), - ("2", &self._2), - ("3", &self._3), - ("4", &self._4), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = Box::new(self._0.1.iter()); - iter = Box::new(iter.chain(self._1.1.iter())); - iter = Box::new(iter.chain(self._2.1.iter())); - iter = Box::new(iter.chain(self._3.1.iter())); - iter = Box::new(iter.chain(self._4.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_ge_amount.rs b/crates/brk_structs/src/groups/by_ge_amount.rs index 0e144d819..653e3c315 100644 --- a/crates/brk_structs/src/groups/by_ge_amount.rs +++ b/crates/brk_structs/src/groups/by_ge_amount.rs @@ -1,11 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use crate::Sats; +use crate::{Filtered, Sats}; -use super::GroupFilter; +use super::Filter; -#[derive(Default, Clone)] +#[derive(Default, Clone, Traversable)] pub struct ByGreatEqualAmount { pub _1sat: T, pub _10sats: T, @@ -43,7 +42,7 @@ impl ByGreatEqualAmount { } } -impl ByGreatEqualAmount<(GroupFilter, T)> { +impl ByGreatEqualAmount> { pub fn iter_right(&self) -> impl Iterator { [ &self._1sat.1, @@ -64,95 +63,26 @@ impl ByGreatEqualAmount<(GroupFilter, T)> { } } -impl From> for ByGreatEqualAmount<(GroupFilter, T)> { +impl From> for ByGreatEqualAmount> { fn from(value: ByGreatEqualAmount) -> Self { Self { - _1sat: (GroupFilter::GreaterOrEqual(Sats::_1.into()), value._1sat), - _10sats: (GroupFilter::GreaterOrEqual(Sats::_10.into()), value._10sats), - _100sats: ( - GroupFilter::GreaterOrEqual(Sats::_100.into()), - value._100sats, - ), - _1k_sats: ( - GroupFilter::GreaterOrEqual(Sats::_1K.into()), - value._1k_sats, - ), - _10k_sats: ( - GroupFilter::GreaterOrEqual(Sats::_10K.into()), - value._10k_sats, - ), - _100k_sats: ( - GroupFilter::GreaterOrEqual(Sats::_100K.into()), - value._100k_sats, - ), - _1m_sats: ( - GroupFilter::GreaterOrEqual(Sats::_1M.into()), - value._1m_sats, - ), - _10m_sats: ( - GroupFilter::GreaterOrEqual(Sats::_10M.into()), - value._10m_sats, - ), - _1btc: (GroupFilter::GreaterOrEqual(Sats::_1BTC.into()), value._1btc), - _10btc: ( - GroupFilter::GreaterOrEqual(Sats::_10BTC.into()), - value._10btc, - ), - _100btc: ( - GroupFilter::GreaterOrEqual(Sats::_100BTC.into()), - value._100btc, - ), - _1k_btc: ( - GroupFilter::GreaterOrEqual(Sats::_1K_BTC.into()), - value._1k_btc, - ), + _1sat: (Filter::GreaterOrEqual(Sats::_1.into()), value._1sat).into(), + _10sats: (Filter::GreaterOrEqual(Sats::_10.into()), value._10sats).into(), + _100sats: (Filter::GreaterOrEqual(Sats::_100.into()), value._100sats).into(), + _1k_sats: (Filter::GreaterOrEqual(Sats::_1K.into()), value._1k_sats).into(), + _10k_sats: (Filter::GreaterOrEqual(Sats::_10K.into()), value._10k_sats).into(), + _100k_sats: (Filter::GreaterOrEqual(Sats::_100K.into()), value._100k_sats).into(), + _1m_sats: (Filter::GreaterOrEqual(Sats::_1M.into()), value._1m_sats).into(), + _10m_sats: (Filter::GreaterOrEqual(Sats::_10M.into()), value._10m_sats).into(), + _1btc: (Filter::GreaterOrEqual(Sats::_1BTC.into()), value._1btc).into(), + _10btc: (Filter::GreaterOrEqual(Sats::_10BTC.into()), value._10btc).into(), + _100btc: (Filter::GreaterOrEqual(Sats::_100BTC.into()), value._100btc).into(), + _1k_btc: (Filter::GreaterOrEqual(Sats::_1K_BTC.into()), value._1k_btc).into(), _10k_btc: ( - GroupFilter::GreaterOrEqual(Sats::_10K_BTC.into()), + Filter::GreaterOrEqual(Sats::_10K_BTC.into()), value._10k_btc, - ), + ) + .into(), } } } - -impl IVecs for ByGreatEqualAmount<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("_1sat", &self._1sat), - ("_10sats", &self._10sats), - ("_100sats", &self._100sats), - ("_1k_sats", &self._1k_sats), - ("_10k_sats", &self._10k_sats), - ("_100k_sats", &self._100k_sats), - ("_1m_sats", &self._1m_sats), - ("_10m_sats", &self._10m_sats), - ("_1btc", &self._1btc), - ("_10btc", &self._10btc), - ("_100btc", &self._100btc), - ("_1k_btc", &self._1k_btc), - ("_10k_btc", &self._10k_btc), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self._1sat.1.iter()); - iter = Box::new(iter.chain(self._10sats.1.iter())); - iter = Box::new(iter.chain(self._100sats.1.iter())); - iter = Box::new(iter.chain(self._1k_sats.1.iter())); - iter = Box::new(iter.chain(self._10k_sats.1.iter())); - iter = Box::new(iter.chain(self._100k_sats.1.iter())); - iter = Box::new(iter.chain(self._1m_sats.1.iter())); - iter = Box::new(iter.chain(self._10m_sats.1.iter())); - iter = Box::new(iter.chain(self._1btc.1.iter())); - iter = Box::new(iter.chain(self._10btc.1.iter())); - iter = Box::new(iter.chain(self._100btc.1.iter())); - iter = Box::new(iter.chain(self._1k_btc.1.iter())); - iter = Box::new(iter.chain(self._10k_btc.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_lt_amount.rs b/crates/brk_structs/src/groups/by_lt_amount.rs index 73728553d..cf100ee60 100644 --- a/crates/brk_structs/src/groups/by_lt_amount.rs +++ b/crates/brk_structs/src/groups/by_lt_amount.rs @@ -1,11 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use crate::Sats; +use crate::{Filtered, Sats}; -use super::GroupFilter; +use super::Filter; -#[derive(Default, Clone)] +#[derive(Default, Clone, Traversable)] pub struct ByLowerThanAmount { pub _10sats: T, pub _100sats: T, @@ -43,7 +42,7 @@ impl ByLowerThanAmount { } } -impl ByLowerThanAmount<(GroupFilter, T)> { +impl ByLowerThanAmount> { pub fn iter_right(&self) -> impl Iterator { [ &self._10sats.1, @@ -64,71 +63,22 @@ impl ByLowerThanAmount<(GroupFilter, T)> { } } -impl From> for ByLowerThanAmount<(GroupFilter, T)> { +impl From> for ByLowerThanAmount> { fn from(value: ByLowerThanAmount) -> Self { Self { - _10sats: (GroupFilter::LowerThan(Sats::_10.into()), value._10sats), - _100sats: (GroupFilter::LowerThan(Sats::_100.into()), value._100sats), - _1k_sats: (GroupFilter::LowerThan(Sats::_1K.into()), value._1k_sats), - _10k_sats: (GroupFilter::LowerThan(Sats::_10K.into()), value._10k_sats), - _100k_sats: (GroupFilter::LowerThan(Sats::_100K.into()), value._100k_sats), - _1m_sats: (GroupFilter::LowerThan(Sats::_1M.into()), value._1m_sats), - _10m_sats: (GroupFilter::LowerThan(Sats::_10M.into()), value._10m_sats), - _1btc: (GroupFilter::LowerThan(Sats::_1BTC.into()), value._1btc), - _10btc: (GroupFilter::LowerThan(Sats::_10BTC.into()), value._10btc), - _100btc: (GroupFilter::LowerThan(Sats::_100BTC.into()), value._100btc), - _1k_btc: (GroupFilter::LowerThan(Sats::_1K_BTC.into()), value._1k_btc), - _10k_btc: ( - GroupFilter::LowerThan(Sats::_10K_BTC.into()), - value._10k_btc, - ), - _100k_btc: ( - GroupFilter::LowerThan(Sats::_100K_BTC.into()), - value._100k_btc, - ), + _10sats: (Filter::LowerThan(Sats::_10.into()), value._10sats).into(), + _100sats: (Filter::LowerThan(Sats::_100.into()), value._100sats).into(), + _1k_sats: (Filter::LowerThan(Sats::_1K.into()), value._1k_sats).into(), + _10k_sats: (Filter::LowerThan(Sats::_10K.into()), value._10k_sats).into(), + _100k_sats: (Filter::LowerThan(Sats::_100K.into()), value._100k_sats).into(), + _1m_sats: (Filter::LowerThan(Sats::_1M.into()), value._1m_sats).into(), + _10m_sats: (Filter::LowerThan(Sats::_10M.into()), value._10m_sats).into(), + _1btc: (Filter::LowerThan(Sats::_1BTC.into()), value._1btc).into(), + _10btc: (Filter::LowerThan(Sats::_10BTC.into()), value._10btc).into(), + _100btc: (Filter::LowerThan(Sats::_100BTC.into()), value._100btc).into(), + _1k_btc: (Filter::LowerThan(Sats::_1K_BTC.into()), value._1k_btc).into(), + _10k_btc: (Filter::LowerThan(Sats::_10K_BTC.into()), value._10k_btc).into(), + _100k_btc: (Filter::LowerThan(Sats::_100K_BTC.into()), value._100k_btc).into(), } } } - -impl IVecs for ByLowerThanAmount<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("10sats", &self._10sats), - ("100sats", &self._100sats), - ("1k_sats", &self._1k_sats), - ("10k_sats", &self._10k_sats), - ("100k_sats", &self._100k_sats), - ("1m_sats", &self._1m_sats), - ("10m_sats", &self._10m_sats), - ("1btc", &self._1btc), - ("10btc", &self._10btc), - ("100btc", &self._100btc), - ("1k_btc", &self._1k_btc), - ("10k_btc", &self._10k_btc), - ("100k_btc", &self._100k_btc), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self._10sats.1.iter()); - iter = Box::new(iter.chain(self._100sats.1.iter())); - iter = Box::new(iter.chain(self._1k_sats.1.iter())); - iter = Box::new(iter.chain(self._10k_sats.1.iter())); - iter = Box::new(iter.chain(self._100k_sats.1.iter())); - iter = Box::new(iter.chain(self._1m_sats.1.iter())); - iter = Box::new(iter.chain(self._10m_sats.1.iter())); - iter = Box::new(iter.chain(self._1btc.1.iter())); - iter = Box::new(iter.chain(self._10btc.1.iter())); - iter = Box::new(iter.chain(self._100btc.1.iter())); - iter = Box::new(iter.chain(self._1k_btc.1.iter())); - iter = Box::new(iter.chain(self._10k_btc.1.iter())); - iter = Box::new(iter.chain(self._100k_btc.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_max_age.rs b/crates/brk_structs/src/groups/by_max_age.rs index c5db675a2..d91a48f97 100644 --- a/crates/brk_structs/src/groups/by_max_age.rs +++ b/crates/brk_structs/src/groups/by_max_age.rs @@ -1,9 +1,9 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use crate::Filtered; -use super::GroupFilter; +use super::Filter; +use brk_traversable::Traversable; -#[derive(Default, Clone)] +#[derive(Default, Clone, Traversable)] pub struct ByMaxAge { pub _1w: T, pub _1m: T, @@ -51,7 +51,7 @@ impl ByMaxAge { } } -impl ByMaxAge<(GroupFilter, T)> { +impl ByMaxAge> { pub fn iter_right(&self) -> impl Iterator { [ &self._1w.1, @@ -77,80 +77,27 @@ impl ByMaxAge<(GroupFilter, T)> { } } -impl From> for ByMaxAge<(GroupFilter, T)> { +impl From> for ByMaxAge> { fn from(value: ByMaxAge) -> Self { Self { - _1w: (GroupFilter::LowerThan(7), value._1w), - _1m: (GroupFilter::LowerThan(30), value._1m), - _2m: (GroupFilter::LowerThan(2 * 30), value._2m), - _3m: (GroupFilter::LowerThan(3 * 30), value._3m), - _4m: (GroupFilter::LowerThan(4 * 30), value._4m), - _5m: (GroupFilter::LowerThan(5 * 30), value._5m), - _6m: (GroupFilter::LowerThan(6 * 30), value._6m), - _1y: (GroupFilter::LowerThan(365), value._1y), - _2y: (GroupFilter::LowerThan(2 * 365), value._2y), - _3y: (GroupFilter::LowerThan(3 * 365), value._3y), - _4y: (GroupFilter::LowerThan(4 * 365), value._4y), - _5y: (GroupFilter::LowerThan(5 * 365), value._5y), - _6y: (GroupFilter::LowerThan(6 * 365), value._6y), - _7y: (GroupFilter::LowerThan(7 * 365), value._7y), - _8y: (GroupFilter::LowerThan(8 * 365), value._8y), - _10y: (GroupFilter::LowerThan(10 * 365), value._10y), - _12y: (GroupFilter::LowerThan(12 * 365), value._12y), - _15y: (GroupFilter::LowerThan(15 * 365), value._15y), + _1w: (Filter::LowerThan(7), value._1w).into(), + _1m: (Filter::LowerThan(30), value._1m).into(), + _2m: (Filter::LowerThan(2 * 30), value._2m).into(), + _3m: (Filter::LowerThan(3 * 30), value._3m).into(), + _4m: (Filter::LowerThan(4 * 30), value._4m).into(), + _5m: (Filter::LowerThan(5 * 30), value._5m).into(), + _6m: (Filter::LowerThan(6 * 30), value._6m).into(), + _1y: (Filter::LowerThan(365), value._1y).into(), + _2y: (Filter::LowerThan(2 * 365), value._2y).into(), + _3y: (Filter::LowerThan(3 * 365), value._3y).into(), + _4y: (Filter::LowerThan(4 * 365), value._4y).into(), + _5y: (Filter::LowerThan(5 * 365), value._5y).into(), + _6y: (Filter::LowerThan(6 * 365), value._6y).into(), + _7y: (Filter::LowerThan(7 * 365), value._7y).into(), + _8y: (Filter::LowerThan(8 * 365), value._8y).into(), + _10y: (Filter::LowerThan(10 * 365), value._10y).into(), + _12y: (Filter::LowerThan(12 * 365), value._12y).into(), + _15y: (Filter::LowerThan(15 * 365), value._15y).into(), } } } - -impl IVecs for ByMaxAge<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("1w", &self._1w), - ("1m", &self._1m), - ("2m", &self._2m), - ("3m", &self._3m), - ("4m", &self._4m), - ("5m", &self._5m), - ("6m", &self._6m), - ("1y", &self._1y), - ("2y", &self._2y), - ("3y", &self._3y), - ("4y", &self._4y), - ("5y", &self._5y), - ("6y", &self._6y), - ("7y", &self._7y), - ("8y", &self._8y), - ("10y", &self._10y), - ("12y", &self._12y), - ("15y", &self._15y), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self._1w.1.iter()); - iter = Box::new(iter.chain(self._1m.1.iter())); - iter = Box::new(iter.chain(self._2m.1.iter())); - iter = Box::new(iter.chain(self._3m.1.iter())); - iter = Box::new(iter.chain(self._4m.1.iter())); - iter = Box::new(iter.chain(self._5m.1.iter())); - iter = Box::new(iter.chain(self._6m.1.iter())); - iter = Box::new(iter.chain(self._1y.1.iter())); - iter = Box::new(iter.chain(self._2y.1.iter())); - iter = Box::new(iter.chain(self._3y.1.iter())); - iter = Box::new(iter.chain(self._4y.1.iter())); - iter = Box::new(iter.chain(self._5y.1.iter())); - iter = Box::new(iter.chain(self._6y.1.iter())); - iter = Box::new(iter.chain(self._7y.1.iter())); - iter = Box::new(iter.chain(self._8y.1.iter())); - iter = Box::new(iter.chain(self._10y.1.iter())); - iter = Box::new(iter.chain(self._12y.1.iter())); - iter = Box::new(iter.chain(self._15y.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_min_age.rs b/crates/brk_structs/src/groups/by_min_age.rs index 30f70a78f..0f70ee79c 100644 --- a/crates/brk_structs/src/groups/by_min_age.rs +++ b/crates/brk_structs/src/groups/by_min_age.rs @@ -1,9 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use super::GroupFilter; +use crate::Filtered; -#[derive(Default, Clone)] +use super::Filter; + +#[derive(Default, Clone, Traversable)] pub struct ByMinAge { pub _1d: T, pub _1w: T, @@ -51,7 +52,7 @@ impl ByMinAge { } } -impl ByMinAge<(GroupFilter, T)> { +impl ByMinAge> { pub fn iter_right(&self) -> impl Iterator { [ &self._1d.1, @@ -77,80 +78,27 @@ impl ByMinAge<(GroupFilter, T)> { } } -impl From> for ByMinAge<(GroupFilter, T)> { +impl From> for ByMinAge> { fn from(value: ByMinAge) -> Self { Self { - _1d: (GroupFilter::GreaterOrEqual(1), value._1d), - _1w: (GroupFilter::GreaterOrEqual(7), value._1w), - _1m: (GroupFilter::GreaterOrEqual(30), value._1m), - _2m: (GroupFilter::GreaterOrEqual(2 * 30), value._2m), - _3m: (GroupFilter::GreaterOrEqual(3 * 30), value._3m), - _4m: (GroupFilter::GreaterOrEqual(4 * 30), value._4m), - _5m: (GroupFilter::GreaterOrEqual(5 * 30), value._5m), - _6m: (GroupFilter::GreaterOrEqual(6 * 30), value._6m), - _1y: (GroupFilter::GreaterOrEqual(365), value._1y), - _2y: (GroupFilter::GreaterOrEqual(2 * 365), value._2y), - _3y: (GroupFilter::GreaterOrEqual(3 * 365), value._3y), - _4y: (GroupFilter::GreaterOrEqual(4 * 365), value._4y), - _5y: (GroupFilter::GreaterOrEqual(5 * 365), value._5y), - _6y: (GroupFilter::GreaterOrEqual(6 * 365), value._6y), - _7y: (GroupFilter::GreaterOrEqual(7 * 365), value._7y), - _8y: (GroupFilter::GreaterOrEqual(8 * 365), value._8y), - _10y: (GroupFilter::GreaterOrEqual(10 * 365), value._10y), - _12y: (GroupFilter::GreaterOrEqual(12 * 365), value._12y), + _1d: (Filter::GreaterOrEqual(1), value._1d).into(), + _1w: (Filter::GreaterOrEqual(7), value._1w).into(), + _1m: (Filter::GreaterOrEqual(30), value._1m).into(), + _2m: (Filter::GreaterOrEqual(2 * 30), value._2m).into(), + _3m: (Filter::GreaterOrEqual(3 * 30), value._3m).into(), + _4m: (Filter::GreaterOrEqual(4 * 30), value._4m).into(), + _5m: (Filter::GreaterOrEqual(5 * 30), value._5m).into(), + _6m: (Filter::GreaterOrEqual(6 * 30), value._6m).into(), + _1y: (Filter::GreaterOrEqual(365), value._1y).into(), + _2y: (Filter::GreaterOrEqual(2 * 365), value._2y).into(), + _3y: (Filter::GreaterOrEqual(3 * 365), value._3y).into(), + _4y: (Filter::GreaterOrEqual(4 * 365), value._4y).into(), + _5y: (Filter::GreaterOrEqual(5 * 365), value._5y).into(), + _6y: (Filter::GreaterOrEqual(6 * 365), value._6y).into(), + _7y: (Filter::GreaterOrEqual(7 * 365), value._7y).into(), + _8y: (Filter::GreaterOrEqual(8 * 365), value._8y).into(), + _10y: (Filter::GreaterOrEqual(10 * 365), value._10y).into(), + _12y: (Filter::GreaterOrEqual(12 * 365), value._12y).into(), } } } - -impl IVecs for ByMinAge<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("1d", &self._1d), - ("1w", &self._1w), - ("1m", &self._1m), - ("2m", &self._2m), - ("3m", &self._3m), - ("4m", &self._4m), - ("5m", &self._5m), - ("6m", &self._6m), - ("1y", &self._1y), - ("2y", &self._2y), - ("3y", &self._3y), - ("4y", &self._4y), - ("5y", &self._5y), - ("6y", &self._6y), - ("7y", &self._7y), - ("8y", &self._8y), - ("10y", &self._10y), - ("12y", &self._12y), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self._1d.1.iter()); - iter = Box::new(iter.chain(self._1w.1.iter())); - iter = Box::new(iter.chain(self._1m.1.iter())); - iter = Box::new(iter.chain(self._2m.1.iter())); - iter = Box::new(iter.chain(self._3m.1.iter())); - iter = Box::new(iter.chain(self._4m.1.iter())); - iter = Box::new(iter.chain(self._5m.1.iter())); - iter = Box::new(iter.chain(self._6m.1.iter())); - iter = Box::new(iter.chain(self._1y.1.iter())); - iter = Box::new(iter.chain(self._2y.1.iter())); - iter = Box::new(iter.chain(self._3y.1.iter())); - iter = Box::new(iter.chain(self._4y.1.iter())); - iter = Box::new(iter.chain(self._5y.1.iter())); - iter = Box::new(iter.chain(self._6y.1.iter())); - iter = Box::new(iter.chain(self._7y.1.iter())); - iter = Box::new(iter.chain(self._8y.1.iter())); - iter = Box::new(iter.chain(self._10y.1.iter())); - iter = Box::new(iter.chain(self._12y.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_spendable_type.rs b/crates/brk_structs/src/groups/by_spendable_type.rs index bbed69f28..b0ca8015f 100644 --- a/crates/brk_structs/src/groups/by_spendable_type.rs +++ b/crates/brk_structs/src/groups/by_spendable_type.rs @@ -1,13 +1,12 @@ use std::ops::{Add, AddAssign}; -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use crate::OutputType; +use crate::{Filtered, OutputType}; -use super::GroupFilter; +use super::Filter; -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, Traversable)] pub struct BySpendableType { pub p2pk65: T, pub p2pk33: T, @@ -75,7 +74,7 @@ impl BySpendableType { } } -impl BySpendableType<(GroupFilter, T)> { +impl BySpendableType> { pub fn iter_right(&self) -> impl Iterator { [ &self.p2pk65.1, @@ -94,20 +93,20 @@ impl BySpendableType<(GroupFilter, T)> { } } -impl From> for BySpendableType<(GroupFilter, T)> { +impl From> for BySpendableType> { fn from(value: BySpendableType) -> Self { Self { - p2pk65: (GroupFilter::Type(OutputType::P2PK65), value.p2pk65), - p2pk33: (GroupFilter::Type(OutputType::P2PK33), value.p2pk33), - p2pkh: (GroupFilter::Type(OutputType::P2PKH), value.p2pkh), - p2ms: (GroupFilter::Type(OutputType::P2MS), value.p2ms), - p2sh: (GroupFilter::Type(OutputType::P2SH), value.p2sh), - p2wpkh: (GroupFilter::Type(OutputType::P2WPKH), value.p2wpkh), - p2wsh: (GroupFilter::Type(OutputType::P2WSH), value.p2wsh), - p2tr: (GroupFilter::Type(OutputType::P2TR), value.p2tr), - p2a: (GroupFilter::Type(OutputType::P2A), value.p2a), - unknown: (GroupFilter::Type(OutputType::Unknown), value.unknown), - empty: (GroupFilter::Type(OutputType::Empty), value.empty), + p2pk65: (Filter::Type(OutputType::P2PK65), value.p2pk65).into(), + p2pk33: (Filter::Type(OutputType::P2PK33), value.p2pk33).into(), + p2pkh: (Filter::Type(OutputType::P2PKH), value.p2pkh).into(), + p2ms: (Filter::Type(OutputType::P2MS), value.p2ms).into(), + p2sh: (Filter::Type(OutputType::P2SH), value.p2sh).into(), + p2wpkh: (Filter::Type(OutputType::P2WPKH), value.p2wpkh).into(), + p2wsh: (Filter::Type(OutputType::P2WSH), value.p2wsh).into(), + p2tr: (Filter::Type(OutputType::P2TR), value.p2tr).into(), + p2a: (Filter::Type(OutputType::P2A), value.p2a).into(), + unknown: (Filter::Type(OutputType::Unknown), value.unknown).into(), + empty: (Filter::Type(OutputType::Empty), value.empty).into(), } } } @@ -152,42 +151,3 @@ where self.empty += rhs.empty; } } - -impl IVecs for BySpendableType<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("p2pk65", &self.p2pk65), - ("p2pk33", &self.p2pk33), - ("p2pkh", &self.p2pkh), - ("p2ms", &self.p2ms), - ("p2sh", &self.p2sh), - ("p2wpkh", &self.p2wpkh), - ("p2wsh", &self.p2wsh), - ("p2tr", &self.p2tr), - ("p2a", &self.p2a), - ("unknown", &self.unknown), - ("empty", &self.empty), - ] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.p2pk65.1.iter()); - iter = Box::new(iter.chain(self.p2pk33.1.iter())); - iter = Box::new(iter.chain(self.p2pkh.1.iter())); - iter = Box::new(iter.chain(self.p2ms.1.iter())); - iter = Box::new(iter.chain(self.p2sh.1.iter())); - iter = Box::new(iter.chain(self.p2wpkh.1.iter())); - iter = Box::new(iter.chain(self.p2wsh.1.iter())); - iter = Box::new(iter.chain(self.p2tr.1.iter())); - iter = Box::new(iter.chain(self.p2a.1.iter())); - iter = Box::new(iter.chain(self.unknown.1.iter())); - iter = Box::new(iter.chain(self.empty.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_term.rs b/crates/brk_structs/src/groups/by_term.rs index fac3b1ad5..68389a6b2 100644 --- a/crates/brk_structs/src/groups/by_term.rs +++ b/crates/brk_structs/src/groups/by_term.rs @@ -1,9 +1,10 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -use super::GroupFilter; +use crate::Filtered; -#[derive(Default, Clone)] +use super::Filter; + +#[derive(Default, Clone, Traversable)] pub struct ByTerm { pub short: T, pub long: T, @@ -15,35 +16,17 @@ impl ByTerm { } } -impl ByTerm<(GroupFilter, T)> { +impl ByTerm> { pub fn iter_right(&self) -> impl Iterator { [&self.short.1, &self.long.1].into_iter() } } -impl From> for ByTerm<(GroupFilter, T)> { +impl From> for ByTerm> { fn from(value: ByTerm) -> Self { Self { - short: (GroupFilter::LowerThan(5 * 30), value.short), - long: (GroupFilter::GreaterOrEqual(5 * 30), value.long), + short: (Filter::LowerThan(5 * 30), value.short).into(), + long: (Filter::GreaterOrEqual(5 * 30), value.long).into(), } } } - -impl IVecs for ByTerm<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [("short", &self.short), ("long", &self.long)] - .into_iter() - .map(|(name, (_, field))| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.short.1.iter()); - iter = Box::new(iter.chain(self.long.1.iter())); - iter - } -} diff --git a/crates/brk_structs/src/groups/by_type.rs b/crates/brk_structs/src/groups/by_type.rs index e344be08b..12b1ebda9 100644 --- a/crates/brk_structs/src/groups/by_type.rs +++ b/crates/brk_structs/src/groups/by_type.rs @@ -1,9 +1,6 @@ use std::ops::{Add, AddAssign}; -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; - -use crate::{GroupFilter, OutputType}; +use crate::OutputType; use super::{BySpendableType, ByUnspendableType}; @@ -73,24 +70,3 @@ where self.unspendable += rhs.unspendable; } } - -// impl IVecs for GroupedByType<(GroupFilter, T)> { -// fn to_tree_node(&self) -> TreeNode { -// TreeNode::Branch( -// [ -// ("spendable", self.spendable.to_tree_node()), -// ("unspendable", self.unspendable.to_tree_node()), -// ] -// .into_iter() -// .map(|(name, node)| (name.to_string(), node)) -// .collect(), -// ) -// } - -// fn iter(&self) -> impl Iterator { -// let mut iter: Box> = -// Box::new(self.spendable.iter()); -// iter = Box::new(iter.chain(self.unspendable.iter())); -// iter -// } -// } diff --git a/crates/brk_structs/src/groups/by_unspendable_type.rs b/crates/brk_structs/src/groups/by_unspendable_type.rs index ef2e8d6f9..6e288f820 100644 --- a/crates/brk_structs/src/groups/by_unspendable_type.rs +++ b/crates/brk_structs/src/groups/by_unspendable_type.rs @@ -1,9 +1,8 @@ use std::ops::{Add, AddAssign}; -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; -#[derive(Default, Clone, Debug)] +#[derive(Default, Clone, Debug, Traversable)] pub struct ByUnspendableType { pub opreturn: T, } @@ -34,18 +33,3 @@ where self.opreturn += rhs.opreturn; } } - -impl IVecs for ByUnspendableType { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [("opreturn", &self.opreturn)] - .into_iter() - .map(|(name, field)| (name.to_string(), field.to_tree_node())) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - self.opreturn.iter() - } -} diff --git a/crates/brk_structs/src/groups/filter.rs b/crates/brk_structs/src/groups/filter.rs index 73098b54a..78f667b2f 100644 --- a/crates/brk_structs/src/groups/filter.rs +++ b/crates/brk_structs/src/groups/filter.rs @@ -1,9 +1,12 @@ use std::ops::Range; +use brk_traversable::{Traversable, TreeNode}; +use vecdb::AnyCollectableVec; + use crate::{HalvingEpoch, OutputType}; #[derive(Debug, Clone, PartialEq, Eq)] -pub enum GroupFilter { +pub enum Filter { All, LowerThan(usize), Range(Range), @@ -12,37 +15,74 @@ pub enum GroupFilter { Type(OutputType), } -impl GroupFilter { +impl Filter { pub fn contains(&self, value: usize) -> bool { match self { - GroupFilter::Range(r) => r.contains(&value), - GroupFilter::LowerThan(max) => *max > value, - GroupFilter::GreaterOrEqual(min) => *min <= value, - GroupFilter::All => true, - GroupFilter::Epoch(_) | GroupFilter::Type(_) => false, + Filter::Range(r) => r.contains(&value), + Filter::LowerThan(max) => *max > value, + Filter::GreaterOrEqual(min) => *min <= value, + Filter::All => true, + Filter::Epoch(_) | Filter::Type(_) => false, } } - pub fn includes(&self, other: &GroupFilter) -> bool { + pub fn includes(&self, other: &Filter) -> bool { match self { - GroupFilter::All => true, - GroupFilter::LowerThan(max) => match other { - GroupFilter::LowerThan(max2) => max >= max2, - GroupFilter::Range(range) => range.end <= *max, - GroupFilter::All - | GroupFilter::GreaterOrEqual(_) - | GroupFilter::Epoch(_) - | GroupFilter::Type(_) => false, + Filter::All => true, + Filter::LowerThan(max) => match other { + Filter::LowerThan(max2) => max >= max2, + Filter::Range(range) => range.end <= *max, + Filter::All | Filter::GreaterOrEqual(_) | Filter::Epoch(_) | Filter::Type(_) => { + false + } }, - GroupFilter::GreaterOrEqual(min) => match other { - GroupFilter::Range(range) => range.start >= *min, - GroupFilter::GreaterOrEqual(min2) => min <= min2, - GroupFilter::All - | GroupFilter::LowerThan(_) - | GroupFilter::Epoch(_) - | GroupFilter::Type(_) => false, + Filter::GreaterOrEqual(min) => match other { + Filter::Range(range) => range.start >= *min, + Filter::GreaterOrEqual(min2) => min <= min2, + Filter::All | Filter::LowerThan(_) | Filter::Epoch(_) | Filter::Type(_) => false, }, - GroupFilter::Range(_) | GroupFilter::Epoch(_) | GroupFilter::Type(_) => false, + Filter::Range(_) | Filter::Epoch(_) | Filter::Type(_) => false, } } } + +#[derive(Clone)] +pub struct Filtered(pub Filter, pub T); + +impl Filtered { + pub fn includes(&self, other: &Filter) -> bool { + self.0.includes(other) + } + + pub fn filter(&self) -> &Filter { + &self.0 + } + + pub fn unwrap(self) -> T { + self.1 + } + + pub fn t(&self) -> &T { + &self.1 + } + + pub fn mut_t(&mut self) -> &mut T { + &mut self.1 + } +} + +impl From<(Filter, T)> for Filtered { + fn from(value: (Filter, T)) -> Self { + Self(value.0, value.1) + } +} + +impl Traversable for Filtered { + fn to_tree_node(&self) -> TreeNode { + self.1.to_tree_node() + } + + fn iter_any_collectable(&self) -> impl Iterator { + self.1.iter_any_collectable() + } +} diff --git a/crates/brk_structs/src/groups/utxo.rs b/crates/brk_structs/src/groups/utxo.rs index 0ca1bca48..0684f0575 100644 --- a/crates/brk_structs/src/groups/utxo.rs +++ b/crates/brk_structs/src/groups/utxo.rs @@ -1,12 +1,11 @@ -use brk_vecs::{IVecs, TreeNode}; -use vecdb::AnyCollectableVec; +use brk_traversable::Traversable; use crate::{ ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, ByMinAge, - BySpendableType, ByTerm, GroupFilter, + BySpendableType, ByTerm, Filter, Filtered, }; -#[derive(Default, Clone)] +#[derive(Default, Clone, Traversable)] pub struct UTXOGroups { pub all: T, pub age_range: ByAgeRange, @@ -54,7 +53,7 @@ impl UTXOGroups { } } -impl UTXOGroups<(GroupFilter, T)> { +impl UTXOGroups> { pub fn iter_right(&self) -> impl Iterator { [&self.all.1] .into_iter() @@ -70,10 +69,10 @@ impl UTXOGroups<(GroupFilter, T)> { } } -impl From> for UTXOGroups<(GroupFilter, T)> { +impl From> for UTXOGroups> { fn from(value: UTXOGroups) -> Self { Self { - all: (GroupFilter::All, value.all), + all: (Filter::All, value.all).into(), term: ByTerm::from(value.term), max_age: ByMaxAge::from(value.max_age), min_age: ByMinAge::from(value.min_age), @@ -86,40 +85,3 @@ impl From> for UTXOGroups<(GroupFilter, T)> { } } } - -impl IVecs for UTXOGroups<(GroupFilter, T)> { - fn to_tree_node(&self) -> TreeNode { - TreeNode::Branch( - [ - ("all", self.all.1.to_tree_node()), - ("age_range", self.age_range.to_tree_node()), - ("epoch", self.epoch.to_tree_node()), - ("min_age", self.min_age.to_tree_node()), - ("ge_amount", self.ge_amount.to_tree_node()), - ("amount_range", self.amount_range.to_tree_node()), - ("term", self.term.to_tree_node()), - ("type", self._type.to_tree_node()), - ("max_age", self.max_age.to_tree_node()), - ("lt_amount", self.lt_amount.to_tree_node()), - ] - .into_iter() - .map(|(name, node)| (name.to_string(), node)) - .collect(), - ) - } - - fn iter(&self) -> impl Iterator { - let mut iter: Box> = - Box::new(self.all.1.iter()); - iter = Box::new(iter.chain(IVecs::iter(&self.age_range))); - iter = Box::new(iter.chain(self.epoch.iter())); - iter = Box::new(iter.chain(self.min_age.iter())); - iter = Box::new(iter.chain(IVecs::iter(&self.ge_amount))); - iter = Box::new(iter.chain(IVecs::iter(&self.amount_range))); - iter = Box::new(iter.chain(self.term.iter())); - iter = Box::new(iter.chain(self._type.iter())); - iter = Box::new(iter.chain(self.max_age.iter())); - iter = Box::new(iter.chain(self.lt_amount.iter())); - iter - } -} diff --git a/crates/brk_vecs/Cargo.toml b/crates/brk_traversable/Cargo.toml similarity index 72% rename from crates/brk_vecs/Cargo.toml rename to crates/brk_traversable/Cargo.toml index d8491c584..e7abca84a 100644 --- a/crates/brk_vecs/Cargo.toml +++ b/crates/brk_traversable/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "brk_vecs" +name = "brk_traversable" description = "Traits for Vecs structs throughout BRK" version.workspace = true edition.workspace = true @@ -10,9 +10,9 @@ rust-version.workspace = true build = "build.rs" [features] -derive = ["brk_vecs_derive"] +derive = ["brk_traversable_derive"] [dependencies] -brk_vecs_derive = { workspace = true, optional = true } +brk_traversable_derive = { workspace = true, optional = true } serde = { workspace = true } vecdb = { workspace = true } diff --git a/crates/brk_traversable/README.md b/crates/brk_traversable/README.md new file mode 100644 index 000000000..257713ca3 --- /dev/null +++ b/crates/brk_traversable/README.md @@ -0,0 +1 @@ +# brk_traversable diff --git a/crates/brk_vecs/build.rs b/crates/brk_traversable/build.rs similarity index 100% rename from crates/brk_vecs/build.rs rename to crates/brk_traversable/build.rs diff --git a/crates/brk_traversable/src/lib.rs b/crates/brk_traversable/src/lib.rs new file mode 100644 index 000000000..2d24bbac6 --- /dev/null +++ b/crates/brk_traversable/src/lib.rs @@ -0,0 +1,202 @@ +use std::{ + collections::{BTreeMap, HashMap}, + fmt::Debug, +}; + +#[cfg(feature = "derive")] +pub use brk_traversable_derive::Traversable; +use serde::Serialize; +use vecdb::{ + AnyCollectableVec, AnyVec, CompressedVec, ComputedVec, EagerVec, LazyVecFrom1, LazyVecFrom2, + LazyVecFrom3, RawVec, StoredCompressed, StoredIndex, StoredRaw, StoredVec, +}; + +pub trait Traversable { + fn to_tree_node(&self) -> TreeNode; + fn iter_any_collectable(&self) -> impl Iterator; +} + +#[derive(Debug, Clone, Serialize)] +#[serde(untagged)] +pub enum TreeNode { + Branch(HashMap), + Leaf(String), +} + +impl Traversable for RawVec +where + I: StoredIndex, + T: StoredRaw, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for CompressedVec +where + I: StoredIndex, + T: StoredCompressed, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for StoredVec +where + I: StoredIndex, + T: StoredCompressed, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for EagerVec +where + I: StoredIndex, + T: StoredCompressed, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for LazyVecFrom1 +where + I: StoredIndex, + T: StoredRaw, + S1I: StoredIndex, + S1T: StoredRaw, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for LazyVecFrom2 +where + I: StoredIndex, + T: StoredRaw, + S1I: StoredIndex, + S1T: StoredRaw, + S2I: StoredIndex, + S2T: StoredRaw, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable + for LazyVecFrom3 +where + I: StoredIndex, + T: StoredRaw, + S1I: StoredIndex, + S1T: StoredRaw, + S2I: StoredIndex, + S2T: StoredRaw, + S3I: StoredIndex, + S3T: StoredRaw, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable + for ComputedVec +where + I: StoredIndex, + T: StoredCompressed, + S1I: StoredIndex, + S1T: StoredCompressed, + S2I: StoredIndex, + S2T: StoredCompressed, + S3I: StoredIndex, + S3T: StoredCompressed, +{ + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::once(self as &dyn AnyCollectableVec) + } + + fn to_tree_node(&self) -> TreeNode { + TreeNode::Leaf(self.name().to_string()) + } +} + +impl Traversable for Box { + fn to_tree_node(&self) -> TreeNode { + (**self).to_tree_node() + } + + fn iter_any_collectable(&self) -> impl Iterator { + (**self).iter_any_collectable() + } +} + +impl Traversable for Option { + fn to_tree_node(&self) -> TreeNode { + match self { + Some(inner) => inner.to_tree_node(), + None => TreeNode::Branch(HashMap::new()), + } + } + + fn iter_any_collectable(&self) -> impl Iterator { + match self { + Some(inner) => Box::new(inner.iter_any_collectable()) + as Box>, + None => Box::new(std::iter::empty()), + } + } +} + +impl Traversable for BTreeMap { + fn to_tree_node(&self) -> TreeNode { + let children = self + .iter() + .map(|(k, v)| (format!("{:?}", k), v.to_tree_node())) + .collect(); + TreeNode::Branch(children) + } + + fn iter_any_collectable(&self) -> impl Iterator { + let mut iter: Box> = + Box::new(std::iter::empty()); + for v in self.values() { + iter = Box::new(iter.chain(v.iter_any_collectable())); + } + iter + } +} diff --git a/crates/brk_vecs_derive/Cargo.toml b/crates/brk_traversable_derive/Cargo.toml similarity index 91% rename from crates/brk_vecs_derive/Cargo.toml rename to crates/brk_traversable_derive/Cargo.toml index 884eeefd7..e830516d2 100644 --- a/crates/brk_vecs_derive/Cargo.toml +++ b/crates/brk_traversable_derive/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "brk_vecs_derive" +name = "brk_traversable_derive" description = "Derive for brk_vec's used in BRK" version.workspace = true edition.workspace = true diff --git a/crates/brk_traversable_derive/README.md b/crates/brk_traversable_derive/README.md new file mode 100644 index 000000000..5b6ad7543 --- /dev/null +++ b/crates/brk_traversable_derive/README.md @@ -0,0 +1 @@ +# brk_traversable_derive diff --git a/crates/brk_vecs_derive/build.rs b/crates/brk_traversable_derive/build.rs similarity index 100% rename from crates/brk_vecs_derive/build.rs rename to crates/brk_traversable_derive/build.rs diff --git a/crates/brk_traversable_derive/src/lib.rs b/crates/brk_traversable_derive/src/lib.rs new file mode 100644 index 000000000..5a64b6577 --- /dev/null +++ b/crates/brk_traversable_derive/src/lib.rs @@ -0,0 +1,235 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput, Fields, Type, parse_macro_input}; + +#[proc_macro_derive(Traversable, attributes(vecs))] +pub fn derive_traversable(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = &input.ident; + let generics = &input.generics; + let (impl_generics, ty_generics, _) = generics.split_for_impl(); + + let traverse_impl = match &input.data { + Data::Struct(data) => { + match &data.fields { + Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { + // Special case for single-field tuple structs - just delegate + let generic_params = generics.type_params().map(|p| &p.ident); + let original_predicates = + &generics.where_clause.as_ref().map(|w| &w.predicates); + + let where_clause = + if original_predicates.is_some() || generics.type_params().count() > 0 { + quote! { + where + #(#generic_params: Send + Sync,)* + #original_predicates + } + } else { + quote! {} + }; + + quote! { + impl #impl_generics Traversable for #name #ty_generics + #where_clause + { + fn to_tree_node(&self) -> brk_traversable::TreeNode { + self.0.to_tree_node() + } + + fn iter_any_collectable(&self) -> impl Iterator { + self.0.iter_any_collectable() + } + } + } + } + _ => { + // Normal struct with named fields + let field_traversals = generate_field_traversals(&data.fields); + let iterator_impl = generate_iterator_impl(&data.fields); + + // Collect field types that need to implement Traversable + let field_types = if let Fields::Named(named_fields) = &data.fields { + named_fields + .named + .iter() + .filter(|f| matches!(f.vis, syn::Visibility::Public(_))) + .filter(|f| !has_skip_attribute(f)) + .map(|f| &f.ty) + .collect::>() + } else { + Vec::new() + }; + + let generic_params = generics.type_params().map(|p| &p.ident); + let original_predicates = + &generics.where_clause.as_ref().map(|w| &w.predicates); + + let where_clause = if !field_types.is_empty() + || original_predicates.is_some() + || generics.type_params().count() > 0 + { + quote! { + where + #(#field_types: brk_traversable::Traversable,)* + #(#generic_params: Send + Sync,)* + #original_predicates + } + } else { + quote! {} + }; + + quote! { + impl #impl_generics Traversable for #name #ty_generics + #where_clause + { + fn to_tree_node(&self) -> brk_traversable::TreeNode { + #field_traversals + } + + #iterator_impl + } + } + } + } + } + _ => panic!("Traversable can only be derived for structs"), + }; + + TokenStream::from(traverse_impl) +} + +fn generate_field_traversals(fields: &Fields) -> proc_macro2::TokenStream { + match fields { + Fields::Named(fields) => { + let entries = fields.named.iter().filter_map(|f| { + let field_name = f.ident.as_ref()?; + let field_name_str = field_name.to_string(); + + if has_skip_attribute(f) || !matches!(f.vis, syn::Visibility::Public(_)) { + return None; + } + + if get_option_inner_type(&f.ty).is_some() { + Some(quote! { + self.#field_name.as_ref().map(|nested| (String::from(#field_name_str), nested.to_tree_node())) + }) + } else { + Some(quote! { + Some((String::from(#field_name_str), self.#field_name.to_tree_node())) + }) + } + }); + + quote! { + return brk_traversable::TreeNode::Branch( + [#(#entries,)*] + .into_iter() + .flatten() + .collect() + ); + } + } + _ => quote! {}, + } +} + +fn has_skip_attribute(field: &syn::Field) -> bool { + field.attrs.iter().any(|attr| { + attr.path().is_ident("vecs") + && attr + .parse_args::() + .map(|ident| ident == "skip") + .unwrap_or(false) + }) +} + +fn generate_iterator_impl(fields: &Fields) -> proc_macro2::TokenStream { + match fields { + Fields::Named(fields) => { + let mut regular_fields = Vec::new(); + let mut option_fields = Vec::new(); + + for field in fields.named.iter() { + if let Some(field_name) = &field.ident { + if !matches!(field.vis, syn::Visibility::Public(_)) { + continue; + } + + if has_skip_attribute(field) { + continue; + } + + if get_option_inner_type(&field.ty).is_some() { + option_fields.push(field_name); + } else { + regular_fields.push(field_name); + } + } + } + + if regular_fields.is_empty() && option_fields.is_empty() { + quote! { + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::empty() + } + } + } else { + let regular_part = if !regular_fields.is_empty() { + let first = regular_fields.first().unwrap(); + let rest = ®ular_fields[1..]; + + quote! { + let mut regular_iter: Box> = + Box::new(self.#first.iter_any_collectable()); + #(regular_iter = Box::new(regular_iter.chain(self.#rest.iter_any_collectable()));)* + } + } else { + quote! { + let regular_iter = std::iter::empty(); + } + }; + + let option_part = if !option_fields.is_empty() { + quote! { + let option_iter = [ + #(self.#option_fields.as_ref().map(|x| Box::new(x.iter_any_collectable()) as Box>),)* + ] + .into_iter() + .flatten() + .flatten(); + } + } else { + quote! { + let option_iter = std::iter::empty(); + } + }; + + quote! { + fn iter_any_collectable(&self) -> impl Iterator { + #regular_part + #option_part + regular_iter.chain(option_iter) + } + } + } + } + _ => quote! { + fn iter_any_collectable(&self) -> impl Iterator { + std::iter::empty() + } + }, + } +} + +fn get_option_inner_type(ty: &Type) -> Option<&Type> { + if let Type::Path(type_path) = ty + && let Some(segment) = type_path.path.segments.last() + && segment.ident == "Option" + && let syn::PathArguments::AngleBracketed(args) = &segment.arguments + && let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() + { + return Some(inner_ty); + } + None +} diff --git a/crates/brk_vecs/README.md b/crates/brk_vecs/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/brk_vecs/src/lib.rs b/crates/brk_vecs/src/lib.rs deleted file mode 100644 index 97a45de6c..000000000 --- a/crates/brk_vecs/src/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::collections::HashMap; - -#[cfg(feature = "derive")] -pub use brk_vecs_derive::IVecs; -use serde::Serialize; -use vecdb::AnyCollectableVec; - -pub trait IVecs { - fn to_tree_node(&self) -> TreeNode; - fn iter(&self) -> impl Iterator; -} - -// Terminal implementation for any type that implements AnyCollectableVec -// impl IVecs for T { -// fn to_tree_node(&self) -> TreeNode { -// TreeNode::Leaf(self.name().to_string()) -// } - -// fn iter<'a>( -// &'a self, -// ) -> Box + 'a> { -// Box::new(std::iter::once(self as &dyn AnyCollectableVec)) -// } -// } - -// For Option types -// impl IVecs for Option { -// fn to_tree_node(&self) -> TreeNode { -// match self { -// Some(inner) => inner.to_tree_node(), -// None => TreeNode::Branch(HashMap::new()), -// } -// } - -// fn iter<'a>( -// &'a self, -// ) -> Box + 'a> { -// match self { -// Some(inner) => inner.iter(), -// None => Box::new(std::iter::empty()), -// } -// } -// } - -// For Box types -// impl IVecs for Box { -// fn to_tree_node(&self) -> TreeNode { -// (**self).to_tree_node() -// } - -// fn iter<'a>( -// &'a self, -// ) -> Box + 'a> { -// (**self).iter() -// } -// } - -#[derive(Debug, Clone, Serialize)] -#[serde(untagged)] -pub enum TreeNode { - Branch(HashMap), - Leaf(String), -} diff --git a/crates/brk_vecs_derive/README.md b/crates/brk_vecs_derive/README.md deleted file mode 100644 index bd3aba254..000000000 --- a/crates/brk_vecs_derive/README.md +++ /dev/null @@ -1 +0,0 @@ -# brk_vecs_derive diff --git a/crates/brk_vecs_derive/src/lib.rs b/crates/brk_vecs_derive/src/lib.rs deleted file mode 100644 index 3e9811e2e..000000000 --- a/crates/brk_vecs_derive/src/lib.rs +++ /dev/null @@ -1,298 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{Data, DeriveInput, Fields, Type, parse_macro_input}; - -#[proc_macro_derive(IVecs, attributes(vecs))] -pub fn derive_ivecs(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let name = &input.ident; - let generics = &input.generics; - let (impl_generics, ty_generics, _) = generics.split_for_impl(); - - // Build extended where clause with Send + Sync bounds - let generic_params = generics.type_params().map(|p| &p.ident); - let original_predicates = &generics.where_clause.as_ref().map(|w| &w.predicates); - - let where_clause = if original_predicates.is_some() || generics.type_params().count() > 0 { - quote! { - where - #(#generic_params: Send + Sync + std::fmt::Debug,)* - #original_predicates - } - } else { - quote! {} - }; - - let traverse_impl = match &input.data { - Data::Struct(data) => { - match &data.fields { - Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { - // Special case for single-field tuple structs - just delegate - quote! { - impl #impl_generics IVecs for #name #ty_generics - #where_clause - { - fn to_tree_node(&self) -> brk_vecs::TreeNode { - self.0.to_tree_node() - } - - fn iter(&self) -> impl Iterator { - IVecs::iter(&self.0) - } - } - } - } - _ => { - // Normal struct with named fields - let field_traversals = generate_field_traversals(&data.fields); - let iterator_impl = generate_iterator_impl(&data.fields); - - quote! { - impl #impl_generics IVecs for #name #ty_generics - #where_clause - { - fn to_tree_node(&self) -> brk_vecs::TreeNode { - let mut children = std::collections::HashMap::new(); - #field_traversals - brk_vecs::TreeNode::Branch(children) - } - - #iterator_impl - } - } - } - } - } - _ => panic!("IVecs can only be derived for structs"), - }; - - TokenStream::from(traverse_impl) -} - -// This catches EagerVec, RawVec, CompressedVec, StoredVec, and any future *Vec types -fn is_vec_type(ty: &Type) -> bool { - if let Type::Path(type_path) = ty - && let Some(segment) = type_path.path.segments.last() - { - let ident = segment.ident.to_string(); - return ident.ends_with("Vec") || ident.starts_with("LazyVecFrom"); - } - false -} - -fn generate_field_traversals(fields: &Fields) -> proc_macro2::TokenStream { - match fields { - Fields::Named(fields) => { - let traversals = fields.named.iter().filter_map(|f| { - let field_name = f.ident.as_ref()?; - let field_name_str = field_name.to_string(); - - if has_skip_attribute(f) { - return None; - } - - if !matches!(f.vis, syn::Visibility::Public(_)) { - return None; - } - - // Check for Option types - if let Some(inner_ty) = get_option_inner_type(&f.ty) { - if is_vec_like(inner_ty) { - // Option or Option> - let vec_access = if get_box_inner_type(inner_ty).is_some() { - quote! { vec.as_ref() } - } else { - quote! { vec } - }; - - return Some(quote! { - if let Some(ref vec) = self.#field_name { - children.insert( - String::from(#field_name_str), - brk_vecs::TreeNode::Leaf(vecdb::AnyVec::name(#vec_access).to_string()) - ); - } - }); - } else { - // Option - return Some(quote! { - if let Some(ref nested) = self.#field_name { - children.insert( - String::from(#field_name_str), - nested.to_tree_node() - ); - } - }); - } - } - - // Check for direct vec or Box - if is_vec_like(&f.ty) { - let vec_access = if get_box_inner_type(&f.ty).is_some() { - quote! { self.#field_name.as_ref() } - } else { - quote! { &self.#field_name } - }; - - Some(quote! { - children.insert( - String::from(#field_name_str), - brk_vecs::TreeNode::Leaf(vecdb::AnyVec::name(#vec_access).to_string()) - ); - }) - } else { - // Direct nested struct - Some(quote! { - children.insert( - String::from(#field_name_str), - self.#field_name.to_tree_node() - ); - }) - } - }); - - quote! { #(#traversals)* } - } - _ => quote! {}, - } -} - -fn has_skip_attribute(field: &syn::Field) -> bool { - field.attrs.iter().any(|attr| { - attr.path().is_ident("vecs") - && attr - .parse_args::() - .map(|ident| ident == "skip") - .unwrap_or(false) - }) -} - -fn is_vec_like(ty: &Type) -> bool { - if is_vec_type(ty) { - return true; - } - if let Some(inner) = get_box_inner_type(ty) { - return is_vec_type(inner); - } - false -} - -fn generate_iterator_impl(fields: &Fields) -> proc_macro2::TokenStream { - match fields { - Fields::Named(fields) => { - let mut direct_vecs = Vec::new(); - let mut option_vecs = Vec::new(); - let mut option_box_vecs = Vec::new(); - - for field in fields.named.iter() { - if let Some(field_name) = &field.ident { - if !matches!(field.vis, syn::Visibility::Public(_)) { - continue; - } - - if let Some(inner_ty) = get_option_inner_type(&field.ty) { - if is_vec_type(inner_ty) { - // Option - use as_ref() - option_vecs.push(field_name); - } else if let Some(box_inner) = get_box_inner_type(inner_ty) - && is_vec_type(box_inner) - { - // Option> - use as_deref() - option_box_vecs.push(field_name); - } - } else if is_vec_like(&field.ty) { - // Direct Vec or Box - direct_vecs.push(field_name); - } - } - } - - if direct_vecs.is_empty() && option_vecs.is_empty() && option_box_vecs.is_empty() { - quote! { - fn iter(&self) -> impl Iterator { - std::iter::empty() - } - } - } else { - let direct_part = if !direct_vecs.is_empty() { - quote! { - let direct_iter = [ - #(&self.#direct_vecs as &dyn vecdb::AnyCollectableVec,)* - ].into_iter(); - } - } else { - quote! { - let direct_iter = std::iter::empty(); - } - }; - - let option_part = if !option_vecs.is_empty() { - quote! { - let option_iter = [ - #((&self.#option_vecs).as_ref().map(|x| x as &dyn vecdb::AnyCollectableVec),)* - ] - .into_iter() - .flatten(); - } - } else { - quote! { - let option_iter = std::iter::empty(); - } - }; - - let option_box_part = if !option_box_vecs.is_empty() { - quote! { - let option_box_iter = [ - #(self.#option_box_vecs.as_deref(),)* - ] - .into_iter() - .flatten() - .map(|x| x as &dyn vecdb::AnyCollectableVec); - } - } else { - quote! { - let option_box_iter = std::iter::empty(); - } - }; - - quote! { - fn iter(&self) -> impl Iterator { - #direct_part - #option_part - #option_box_part - direct_iter.chain(option_iter).chain(option_box_iter) - } - } - } - } - _ => quote! { - fn iter(&self) -> impl Iterator { - std::iter::empty() - } - }, - } -} - -fn get_box_inner_type(ty: &Type) -> Option<&Type> { - if let Type::Path(type_path) = ty - && let Some(segment) = type_path.path.segments.last() - && segment.ident == "Box" - && let syn::PathArguments::AngleBracketed(args) = &segment.arguments - && let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() - { - return Some(inner_ty); - } - None -} - -fn get_option_inner_type(ty: &Type) -> Option<&Type> { - if let Type::Path(type_path) = ty - && let Some(segment) = type_path.path.segments.last() - && segment.ident == "Option" - && let syn::PathArguments::AngleBracketed(args) = &segment.arguments - && let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first() - { - return Some(inner_ty); - } - None -}