mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: traversable
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -26,3 +26,6 @@ flamegraph.svg
|
||||
|
||||
# AI
|
||||
.claude/settings*
|
||||
|
||||
# Expand
|
||||
expand.rs
|
||||
|
||||
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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::<Vec<_>>().len());
|
||||
|
||||
std::process::exit(0);
|
||||
|
||||
loop {
|
||||
let i = Instant::now();
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit, true)?;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<I, T>
|
||||
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<I, T> {
|
||||
|
||||
@@ -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<I, T, S1I, S2T>
|
||||
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<I, T, S1I, T, I, S2T> {
|
||||
|
||||
@@ -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<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -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<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -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<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -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<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -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<ComputedVecsFromDateIndex<Dollars>>,
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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<Sats>,
|
||||
pub bitcoin: ComputedVecsFromDateIndex<Bitcoin>,
|
||||
|
||||
@@ -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<Sats>,
|
||||
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
|
||||
|
||||
@@ -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<Sats>,
|
||||
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
|
||||
|
||||
@@ -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<EagerVec<Height, Sats>>,
|
||||
pub bitcoin: EagerVec<Height, Bitcoin>,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<Height, PoolId>,
|
||||
|
||||
vecs: BTreeMap<PoolId, vecs::Vecs>,
|
||||
pub height_to_pool: RawVec<Height, PoolId>,
|
||||
pub vecs: BTreeMap<PoolId, vecs::Vecs>,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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<StoredU32>,
|
||||
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
indexes_to_fee: ComputedValueVecsFromHeight,
|
||||
indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
|
||||
pub indexes_to_blocks_mined: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_fee: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<Height>,
|
||||
|
||||
|
||||
@@ -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<Filtered<address_cohort::Vecs>>);
|
||||
|
||||
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::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
@@ -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::<Vec<_>>(),
|
||||
)
|
||||
})
|
||||
@@ -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<DateIndex, Dollars>>,
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EagerVec<Height, StoredU64>>);
|
||||
|
||||
impl From<ByAddressType<EagerVec<Height, StoredU64>>> for AddressTypeToHeightToAddressCount {
|
||||
|
||||
@@ -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<ComputedVecsFromHeight<StoredU64>>);
|
||||
|
||||
impl From<ByAddressType<ComputedVecsFromHeight<StoredU64>>> for AddressTypeToIndexesToAddressCount {
|
||||
|
||||
@@ -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<EagerVec<Height, Dollars>>,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Height>,
|
||||
|
||||
#[vecs(skip)]
|
||||
pub state: Option<UTXOCohortState>,
|
||||
|
||||
inner: common::Vecs,
|
||||
pub inner: common::Vecs,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
|
||||
@@ -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<Filtered<utxo_cohort::Vecs>>);
|
||||
|
||||
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::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>(),
|
||||
by_date_range.iter().map(Filtered::t).collect::<Vec<_>>(),
|
||||
)]
|
||||
.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::<Vec<_>>(),
|
||||
)
|
||||
}))
|
||||
.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::<Vec<_>>(),
|
||||
)
|
||||
}))
|
||||
.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::<Vec<_>>(),
|
||||
)
|
||||
}))
|
||||
.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::<Vec<_>>(),
|
||||
)
|
||||
}))
|
||||
.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::<Vec<_>>(),
|
||||
)
|
||||
}))
|
||||
@@ -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<DateIndex, Dollars>>,
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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::<Vec<_>>();
|
||||
// 44
|
||||
// let vecs = indexer.vecs.iter_any_collectable().collect::<Vec<_>>();
|
||||
// dbg!(indexer.vecs.to_tree_node());
|
||||
// dbg!(vecs.len());
|
||||
// std::process::exit(0);
|
||||
|
||||
@@ -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<EmptyOutputIndex, TxIndex>,
|
||||
@@ -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<Item = &dyn AnyCollectableVec> {
|
||||
// pub fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
// [
|
||||
// &self.emptyoutputindex_to_txindex as &dyn AnyCollectableVec,
|
||||
// &self.height_to_blockhash,
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<TreeNode>,
|
||||
metric_to_indexes: BTreeMap<&'a str, Vec<&'static str>>,
|
||||
index_to_metrics: BTreeMap<Index, Vec<&'a str>>,
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<AppState> {
|
||||
Json(app_state.interface.get_indexes()).into_response()
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/metrics/catalog",
|
||||
get(async |State(app_state): State<AppState>| -> Response {
|
||||
Json(app_state.interface.get_metrics_catalog()).into_response()
|
||||
}),
|
||||
)
|
||||
.route(
|
||||
"/api/metrics/list",
|
||||
get(
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<T> {
|
||||
pub ge_amount: ByGreatEqualAmount<T>,
|
||||
pub amount_range: ByAmountRange<T>,
|
||||
@@ -27,7 +28,7 @@ impl<T> AddressGroups<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddressGroups<(GroupFilter, T)> {
|
||||
impl<T> AddressGroups<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
self.amount_range
|
||||
.iter_right()
|
||||
@@ -36,7 +37,7 @@ impl<T> AddressGroups<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<AddressGroups<T>> for AddressGroups<(GroupFilter, T)> {
|
||||
impl<T> From<AddressGroups<T>> for AddressGroups<Filtered<T>> {
|
||||
fn from(value: AddressGroups<T>) -> Self {
|
||||
Self {
|
||||
amount_range: ByAmountRange::from(value.amount_range),
|
||||
@@ -45,26 +46,3 @@ impl<T> From<AddressGroups<T>> for AddressGroups<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
@@ -122,7 +122,7 @@ impl<T> ByAddressType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByAddressType<(GroupFilter, T)> {
|
||||
impl<T> ByAddressType<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.p2pk65.1,
|
||||
@@ -138,17 +138,17 @@ impl<T> ByAddressType<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByAddressType<T>> for ByAddressType<(GroupFilter, T)> {
|
||||
impl<T> From<ByAddressType<T>> for ByAddressType<Filtered<T>> {
|
||||
fn from(value: ByAddressType<T>) -> 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<T> ByAddressType<Option<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AnyCollectableVec + !IVecs> IVecs for ByAddressType<T> {
|
||||
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<Item = &dyn AnyCollectableVec> {
|
||||
[
|
||||
&self.p2pk65 as &dyn AnyCollectableVec,
|
||||
&self.p2pk33,
|
||||
&self.p2pkh,
|
||||
&self.p2sh,
|
||||
&self.p2wpkh,
|
||||
&self.p2wsh,
|
||||
&self.p2tr,
|
||||
&self.p2a,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> IVecs for ByAddressType<T> {
|
||||
impl<T: Traversable> Traversable for ByAddressType<T> {
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Branch(
|
||||
[
|
||||
@@ -249,16 +215,16 @@ impl<T: IVecs> IVecs for ByAddressType<T> {
|
||||
)
|
||||
}
|
||||
|
||||
fn iter(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub up_to_1d: T,
|
||||
pub _1d_to_1w: T,
|
||||
@@ -27,29 +28,29 @@ pub struct ByAgeRange<T> {
|
||||
pub from_15y: T,
|
||||
}
|
||||
|
||||
impl<T> From<ByAgeRange<T>> for ByAgeRange<(GroupFilter, T)> {
|
||||
impl<T> From<ByAgeRange<T>> for ByAgeRange<Filtered<T>> {
|
||||
fn from(value: ByAgeRange<T>) -> 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<T> ByAgeRange<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByAgeRange<(GroupFilter, T)> {
|
||||
impl<T> ByAgeRange<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.up_to_1d.1,
|
||||
@@ -135,60 +136,3 @@ impl<T> ByAgeRange<(GroupFilter, T)> {
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _0sats: T,
|
||||
pub _1sat_to_10sats: T,
|
||||
@@ -26,67 +25,81 @@ pub struct ByAmountRange<T> {
|
||||
pub _100k_btc_or_more: T,
|
||||
}
|
||||
|
||||
impl<T> From<ByAmountRange<T>> for ByAmountRange<(GroupFilter, T)> {
|
||||
impl<T> From<ByAmountRange<T>> for ByAmountRange<Filtered<T>> {
|
||||
fn from(value: ByAmountRange<T>) -> 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<T> ByAmountRange<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByAmountRange<(GroupFilter, T)> {
|
||||
impl<T> ByAmountRange<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self._0sats.1,
|
||||
@@ -262,50 +275,3 @@ where
|
||||
self._100k_btc_or_more += rhs._100k_btc_or_more;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub loaded: T,
|
||||
pub empty: T,
|
||||
@@ -13,21 +12,3 @@ impl<T> ByAnyAddress<Option<T>> {
|
||||
self.empty.take();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> IVecs for ByAnyAddress<T> {
|
||||
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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
Box::new(self.loaded.iter());
|
||||
iter = Box::new(iter.chain(self.empty.iter()));
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _0: T,
|
||||
pub _1: T,
|
||||
@@ -14,14 +13,14 @@ pub struct ByEpoch<T> {
|
||||
pub _4: T,
|
||||
}
|
||||
|
||||
impl<T> From<ByEpoch<T>> for ByEpoch<(GroupFilter, T)> {
|
||||
impl<T> From<ByEpoch<T>> for ByEpoch<Filtered<T>> {
|
||||
fn from(value: ByEpoch<T>) -> 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<T> ByEpoch<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByEpoch<(GroupFilter, T)> {
|
||||
impl<T> ByEpoch<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[&self._0.1, &self._1.1, &self._2.1, &self._3.1, &self._4.1].into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> = 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _1sat: T,
|
||||
pub _10sats: T,
|
||||
@@ -43,7 +42,7 @@ impl<T> ByGreatEqualAmount<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByGreatEqualAmount<(GroupFilter, T)> {
|
||||
impl<T> ByGreatEqualAmount<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self._1sat.1,
|
||||
@@ -64,95 +63,26 @@ impl<T> ByGreatEqualAmount<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByGreatEqualAmount<T>> for ByGreatEqualAmount<(GroupFilter, T)> {
|
||||
impl<T> From<ByGreatEqualAmount<T>> for ByGreatEqualAmount<Filtered<T>> {
|
||||
fn from(value: ByGreatEqualAmount<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _10sats: T,
|
||||
pub _100sats: T,
|
||||
@@ -43,7 +42,7 @@ impl<T> ByLowerThanAmount<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByLowerThanAmount<(GroupFilter, T)> {
|
||||
impl<T> ByLowerThanAmount<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self._10sats.1,
|
||||
@@ -64,71 +63,22 @@ impl<T> ByLowerThanAmount<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByLowerThanAmount<T>> for ByLowerThanAmount<(GroupFilter, T)> {
|
||||
impl<T> From<ByLowerThanAmount<T>> for ByLowerThanAmount<Filtered<T>> {
|
||||
fn from(value: ByLowerThanAmount<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _1w: T,
|
||||
pub _1m: T,
|
||||
@@ -51,7 +51,7 @@ impl<T> ByMaxAge<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByMaxAge<(GroupFilter, T)> {
|
||||
impl<T> ByMaxAge<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self._1w.1,
|
||||
@@ -77,80 +77,27 @@ impl<T> ByMaxAge<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByMaxAge<T>> for ByMaxAge<(GroupFilter, T)> {
|
||||
impl<T> From<ByMaxAge<T>> for ByMaxAge<Filtered<T>> {
|
||||
fn from(value: ByMaxAge<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub _1d: T,
|
||||
pub _1w: T,
|
||||
@@ -51,7 +52,7 @@ impl<T> ByMinAge<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByMinAge<(GroupFilter, T)> {
|
||||
impl<T> ByMinAge<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self._1d.1,
|
||||
@@ -77,80 +78,27 @@ impl<T> ByMinAge<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByMinAge<T>> for ByMinAge<(GroupFilter, T)> {
|
||||
impl<T> From<ByMinAge<T>> for ByMinAge<Filtered<T>> {
|
||||
fn from(value: ByMinAge<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub p2pk65: T,
|
||||
pub p2pk33: T,
|
||||
@@ -75,7 +74,7 @@ impl<T> BySpendableType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BySpendableType<(GroupFilter, T)> {
|
||||
impl<T> BySpendableType<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.p2pk65.1,
|
||||
@@ -94,20 +93,20 @@ impl<T> BySpendableType<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<BySpendableType<T>> for BySpendableType<(GroupFilter, T)> {
|
||||
impl<T> From<BySpendableType<T>> for BySpendableType<Filtered<T>> {
|
||||
fn from(value: BySpendableType<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub short: T,
|
||||
pub long: T,
|
||||
@@ -15,35 +16,17 @@ impl<T> ByTerm<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByTerm<(GroupFilter, T)> {
|
||||
impl<T> ByTerm<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[&self.short.1, &self.long.1].into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ByTerm<T>> for ByTerm<(GroupFilter, T)> {
|
||||
impl<T> From<ByTerm<T>> for ByTerm<Filtered<T>> {
|
||||
fn from(value: ByTerm<T>) -> 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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
Box::new(self.short.1.iter());
|
||||
iter = Box::new(iter.chain(self.long.1.iter()));
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
// let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
// Box::new(self.spendable.iter());
|
||||
// iter = Box::new(iter.chain(self.unspendable.iter()));
|
||||
// iter
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -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<T> {
|
||||
pub opreturn: T,
|
||||
}
|
||||
@@ -34,18 +33,3 @@ where
|
||||
self.opreturn += rhs.opreturn;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> IVecs for ByUnspendableType<T> {
|
||||
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<Item = &dyn AnyCollectableVec> {
|
||||
self.opreturn.iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<usize>),
|
||||
@@ -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<T>(pub Filter, pub T);
|
||||
|
||||
impl<T> Filtered<T> {
|
||||
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<T> From<(Filter, T)> for Filtered<T> {
|
||||
fn from(value: (Filter, T)) -> Self {
|
||||
Self(value.0, value.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Traversable> Traversable for Filtered<T> {
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
self.1.to_tree_node()
|
||||
}
|
||||
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
self.1.iter_any_collectable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
pub all: T,
|
||||
pub age_range: ByAgeRange<T>,
|
||||
@@ -54,7 +53,7 @@ impl<T> UTXOGroups<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UTXOGroups<(GroupFilter, T)> {
|
||||
impl<T> UTXOGroups<Filtered<T>> {
|
||||
pub fn iter_right(&self) -> impl Iterator<Item = &T> {
|
||||
[&self.all.1]
|
||||
.into_iter()
|
||||
@@ -70,10 +69,10 @@ impl<T> UTXOGroups<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<UTXOGroups<T>> for UTXOGroups<(GroupFilter, T)> {
|
||||
impl<T> From<UTXOGroups<T>> for UTXOGroups<Filtered<T>> {
|
||||
fn from(value: UTXOGroups<T>) -> 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<T> From<UTXOGroups<T>> for UTXOGroups<(GroupFilter, T)> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IVecs> 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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
1
crates/brk_traversable/README.md
Normal file
1
crates/brk_traversable/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# brk_traversable
|
||||
202
crates/brk_traversable/src/lib.rs
Normal file
202
crates/brk_traversable/src/lib.rs
Normal file
@@ -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<Item = &dyn AnyCollectableVec>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum TreeNode {
|
||||
Branch(HashMap<String, TreeNode>),
|
||||
Leaf(String),
|
||||
}
|
||||
|
||||
impl<I, T> Traversable for RawVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredRaw,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Traversable for CompressedVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredCompressed,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Traversable for StoredVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredCompressed,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> Traversable for EagerVec<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredCompressed,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, S1I, S1T> Traversable for LazyVecFrom1<I, T, S1I, S1T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredRaw,
|
||||
S1I: StoredIndex,
|
||||
S1T: StoredRaw,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, S1I, S1T, S2I, S2T> Traversable for LazyVecFrom2<I, T, S1I, S1T, S2I, S2T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredRaw,
|
||||
S1I: StoredIndex,
|
||||
S1T: StoredRaw,
|
||||
S2I: StoredIndex,
|
||||
S2T: StoredRaw,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, S1I, S1T, S2I, S2T, S3I, S3T> Traversable
|
||||
for LazyVecFrom3<I, T, S1I, S1T, S2I, S2T, S3I, S3T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredRaw,
|
||||
S1I: StoredIndex,
|
||||
S1T: StoredRaw,
|
||||
S2I: StoredIndex,
|
||||
S2T: StoredRaw,
|
||||
S3I: StoredIndex,
|
||||
S3T: StoredRaw,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, S1I, S1T, S2I, S2T, S3I, S3T> Traversable
|
||||
for ComputedVec<I, T, S1I, S1T, S2I, S2T, S3I, S3T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
T: StoredCompressed,
|
||||
S1I: StoredIndex,
|
||||
S1T: StoredCompressed,
|
||||
S2I: StoredIndex,
|
||||
S2T: StoredCompressed,
|
||||
S3I: StoredIndex,
|
||||
S3T: StoredCompressed,
|
||||
{
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
std::iter::once(self as &dyn AnyCollectableVec)
|
||||
}
|
||||
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
TreeNode::Leaf(self.name().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Traversable + ?Sized> Traversable for Box<T> {
|
||||
fn to_tree_node(&self) -> TreeNode {
|
||||
(**self).to_tree_node()
|
||||
}
|
||||
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn AnyCollectableVec> {
|
||||
(**self).iter_any_collectable()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Traversable> Traversable for Option<T> {
|
||||
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<Item = &dyn AnyCollectableVec> {
|
||||
match self {
|
||||
Some(inner) => Box::new(inner.iter_any_collectable())
|
||||
as Box<dyn Iterator<Item = &dyn AnyCollectableVec>>,
|
||||
None => Box::new(std::iter::empty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Debug, V: Traversable> Traversable for BTreeMap<K, V> {
|
||||
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<Item = &dyn AnyCollectableVec> {
|
||||
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
|
||||
Box::new(std::iter::empty());
|
||||
for v in self.values() {
|
||||
iter = Box::new(iter.chain(v.iter_any_collectable()));
|
||||
}
|
||||
iter
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
1
crates/brk_traversable_derive/README.md
Normal file
1
crates/brk_traversable_derive/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# brk_traversable_derive
|
||||
235
crates/brk_traversable_derive/src/lib.rs
Normal file
235
crates/brk_traversable_derive/src/lib.rs
Normal file
@@ -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<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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::<Vec<_>>()
|
||||
} 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::<syn::Ident>()
|
||||
.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<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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<dyn Iterator<Item = &dyn vecdb::AnyCollectableVec>> =
|
||||
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<dyn Iterator<Item = &dyn vecdb::AnyCollectableVec>>),)*
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten();
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
let option_iter = std::iter::empty();
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
#regular_part
|
||||
#option_part
|
||||
regular_iter.chain(option_iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
fn iter_any_collectable(&self) -> impl Iterator<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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
|
||||
}
|
||||
@@ -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<Item = &dyn AnyCollectableVec>;
|
||||
}
|
||||
|
||||
// Terminal implementation for any type that implements AnyCollectableVec
|
||||
// impl<T: AnyCollectableVec> IVecs for T {
|
||||
// fn to_tree_node(&self) -> TreeNode {
|
||||
// TreeNode::Leaf(self.name().to_string())
|
||||
// }
|
||||
|
||||
// fn iter<'a>(
|
||||
// &'a self,
|
||||
// ) -> Box<dyn Iterator<Item = &'a dyn AnyCollectableVec> + 'a> {
|
||||
// Box::new(std::iter::once(self as &dyn AnyCollectableVec))
|
||||
// }
|
||||
// }
|
||||
|
||||
// For Option types
|
||||
// impl<T: IVecs> IVecs for Option<T> {
|
||||
// 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<dyn Iterator<Item = &'a dyn AnyCollectableVec> + 'a> {
|
||||
// match self {
|
||||
// Some(inner) => inner.iter(),
|
||||
// None => Box::new(std::iter::empty()),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// For Box types
|
||||
// impl<T: IVecs> IVecs for Box<T> {
|
||||
// fn to_tree_node(&self) -> TreeNode {
|
||||
// (**self).to_tree_node()
|
||||
// }
|
||||
|
||||
// fn iter<'a>(
|
||||
// &'a self,
|
||||
// ) -> Box<dyn Iterator<Item = &'a dyn AnyCollectableVec> + 'a> {
|
||||
// (**self).iter()
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum TreeNode {
|
||||
Branch(HashMap<String, TreeNode>),
|
||||
Leaf(String),
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
# brk_vecs_derive
|
||||
@@ -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<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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<inner> types
|
||||
if let Some(inner_ty) = get_option_inner_type(&f.ty) {
|
||||
if is_vec_like(inner_ty) {
|
||||
// Option<Vec> or Option<Box<Vec>>
|
||||
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<nested_struct>
|
||||
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<vec>
|
||||
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::<syn::Ident>()
|
||||
.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<Vec> - 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<Box<Vec>> - use as_deref()
|
||||
option_box_vecs.push(field_name);
|
||||
}
|
||||
} else if is_vec_like(&field.ty) {
|
||||
// Direct Vec or Box<Vec>
|
||||
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<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
#direct_part
|
||||
#option_part
|
||||
#option_box_part
|
||||
direct_iter.chain(option_iter).chain(option_box_iter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => quote! {
|
||||
fn iter(&self) -> impl Iterator<Item = &dyn vecdb::AnyCollectableVec> {
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user