mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-31 12:43:06 -07:00
global: snapshot
This commit is contained in:
@@ -18,9 +18,11 @@ Command-line interface for running a Bitcoin Research Kit instance.
|
||||
|
||||
```bash
|
||||
rustup update
|
||||
RUSTFLAGS="-C target-cpu=native" cargo install --locked brk_cli --version "$(cargo search brk_cli | head -1 | awk -F'"' '{print $2}')"
|
||||
RUSTFLAGS="-C target-cpu=native -C target-feature=+bmi1,+bmi2,+avx2" cargo install --locked brk_cli --version "$(cargo search brk_cli | head -1 | awk -F'"' '{print $2}')"
|
||||
```
|
||||
|
||||
The SIMD flags (`bmi1`, `bmi2`, `avx2`) significantly improve pcodec decompression performance.
|
||||
|
||||
Portable build (without native CPU optimizations):
|
||||
|
||||
```bash
|
||||
|
||||
+817
-3111
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ brk_traversable = { workspace = true }
|
||||
brk_types = { workspace = true }
|
||||
derive_more = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
pco = "0.4.9"
|
||||
pco = "1.0.0"
|
||||
rayon = { workspace = true }
|
||||
rustc-hash = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, StoredI16, StoredU16, Version};
|
||||
use brk_types::{StoredF32, StoredI8, StoredU16, Version};
|
||||
|
||||
use super::{
|
||||
indexes,
|
||||
internal::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16},
|
||||
internal::{ConstantVecs, ReturnF32Tenths, ReturnI8, ReturnU16},
|
||||
};
|
||||
|
||||
pub const DB_NAME: &str = "constants";
|
||||
@@ -24,10 +24,10 @@ pub struct Vecs {
|
||||
pub constant_80: ConstantVecs<StoredU16>,
|
||||
pub constant_100: ConstantVecs<StoredU16>,
|
||||
pub constant_600: ConstantVecs<StoredU16>,
|
||||
pub constant_minus_1: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_2: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_3: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_4: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_1: ConstantVecs<StoredI8>,
|
||||
pub constant_minus_2: ConstantVecs<StoredI8>,
|
||||
pub constant_minus_3: ConstantVecs<StoredI8>,
|
||||
pub constant_minus_4: ConstantVecs<StoredI8>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -49,10 +49,10 @@ impl Vecs {
|
||||
constant_80: ConstantVecs::new::<ReturnU16<80>>("constant_80", v, indexes),
|
||||
constant_100: ConstantVecs::new::<ReturnU16<100>>("constant_100", v, indexes),
|
||||
constant_600: ConstantVecs::new::<ReturnU16<600>>("constant_600", v, indexes),
|
||||
constant_minus_1: ConstantVecs::new::<ReturnI16<-1>>("constant_minus_1", v, indexes),
|
||||
constant_minus_2: ConstantVecs::new::<ReturnI16<-2>>("constant_minus_2", v, indexes),
|
||||
constant_minus_3: ConstantVecs::new::<ReturnI16<-3>>("constant_minus_3", v, indexes),
|
||||
constant_minus_4: ConstantVecs::new::<ReturnI16<-4>>("constant_minus_4", v, indexes),
|
||||
constant_minus_1: ConstantVecs::new::<ReturnI8<-1>>("constant_minus_1", v, indexes),
|
||||
constant_minus_2: ConstantVecs::new::<ReturnI8<-2>>("constant_minus_2", v, indexes),
|
||||
constant_minus_3: ConstantVecs::new::<ReturnI8<-3>>("constant_minus_3", v, indexes),
|
||||
constant_minus_4: ConstantVecs::new::<ReturnI8<-4>>("constant_minus_4", v, indexes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::{
|
||||
use brk_error::{Error, Result};
|
||||
use brk_types::{CentsCompact, Dollars, Height, Sats, SupplyState};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use pco::standalone::{simple_decompress, simpler_compress};
|
||||
use pco::{standalone::{simple_compress, simple_decompress}, ChunkConfig};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::Bytes;
|
||||
@@ -234,15 +234,14 @@ impl PriceToAmount {
|
||||
#[derive(Clone, Default, Debug, Deref, DerefMut, Serialize, Deserialize)]
|
||||
struct State(BTreeMap<CentsCompact, Sats>);
|
||||
|
||||
const COMPRESSION_LEVEL: usize = 4;
|
||||
|
||||
impl State {
|
||||
fn serialize(&self) -> vecdb::Result<Vec<u8>> {
|
||||
let keys: Vec<i32> = self.keys().map(|k| i32::from(*k)).collect();
|
||||
let values: Vec<u64> = self.values().map(|v| u64::from(*v)).collect();
|
||||
|
||||
let compressed_keys = simpler_compress(&keys, COMPRESSION_LEVEL)?;
|
||||
let compressed_values = simpler_compress(&values, COMPRESSION_LEVEL)?;
|
||||
let config = ChunkConfig::default();
|
||||
let compressed_keys = simple_compress(&keys, &config)?;
|
||||
let compressed_values = simple_compress(&values, &config)?;
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
buffer.extend(keys.len().to_bytes());
|
||||
|
||||
@@ -21,7 +21,7 @@ mod ratio32;
|
||||
mod ratio32_neg;
|
||||
mod ratio_f32;
|
||||
mod return_f32_tenths;
|
||||
mod return_i16;
|
||||
mod return_i8;
|
||||
mod return_u16;
|
||||
mod rsi_formula;
|
||||
mod sat_halve;
|
||||
@@ -61,7 +61,7 @@ pub use ratio32::*;
|
||||
pub use ratio32_neg::*;
|
||||
pub use ratio_f32::*;
|
||||
pub use return_f32_tenths::*;
|
||||
pub use return_i16::*;
|
||||
pub use return_i8::*;
|
||||
pub use return_u16::*;
|
||||
pub use rsi_formula::*;
|
||||
pub use sat_halve::*;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::StoredI16;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant i16 value, ignoring the input.
|
||||
pub struct ReturnI16<const V: i16>;
|
||||
|
||||
impl<S, const V: i16> UnaryTransform<S, StoredI16> for ReturnI16<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredI16 {
|
||||
StoredI16::new(V)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
use brk_types::StoredI8;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant i8 value, ignoring the input.
|
||||
pub struct ReturnI8<const V: i8>;
|
||||
|
||||
impl<S, const V: i8> UnaryTransform<S, StoredI8> for ReturnI8<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredI8 {
|
||||
StoredI8::new(V)
|
||||
}
|
||||
}
|
||||
@@ -383,11 +383,9 @@ impl Stores {
|
||||
pub fn reset(&mut self) -> Result<()> {
|
||||
info!("Resetting stores...");
|
||||
|
||||
// Clear all keyspaces
|
||||
self.iter_any().try_for_each(|store| -> Result<()> {
|
||||
store.keyspace().clear()?;
|
||||
Ok(())
|
||||
})?;
|
||||
// Clear all stores (both in-memory buffers and on-disk keyspaces)
|
||||
self.par_iter_any_mut()
|
||||
.try_for_each(|store| store.reset())?;
|
||||
|
||||
// Persist the cleared state
|
||||
self.db.persist(PersistMode::SyncAll)?;
|
||||
|
||||
@@ -19,3 +19,11 @@ memmap2 = "0.9"
|
||||
plotters = "0.3"
|
||||
tracing = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
|
||||
[[example]]
|
||||
name = "heatmap"
|
||||
path = "examples/heatmap.rs"
|
||||
|
||||
[[example]]
|
||||
name = "oracle"
|
||||
path = "examples/oracle.rs"
|
||||
|
||||
@@ -1,4 +1,26 @@
|
||||
//! Experimental playground for brk development.
|
||||
//! Playground library for Bitcoin on-chain analysis
|
||||
//!
|
||||
//! This crate is for experiments and prototypes.
|
||||
//! Most contents are git-ignored.
|
||||
//! This crate provides tools for:
|
||||
//! - Phase histogram analysis of UTXO patterns
|
||||
//! - Filter-based output selection for price signal extraction
|
||||
//! - On-chain OHLC price oracle derivation
|
||||
|
||||
pub mod anchors;
|
||||
pub mod conditions;
|
||||
pub mod constants;
|
||||
pub mod filters;
|
||||
pub mod histogram;
|
||||
pub mod oracle;
|
||||
pub mod render;
|
||||
pub mod signal;
|
||||
|
||||
pub use anchors::{get_anchor_ohlc, get_anchor_range, Ohlc};
|
||||
pub use conditions::{out_bits, tx_bits, MappedOutputConditions};
|
||||
pub use constants::{HeatmapFilter, NUM_BINS, ROUND_USD_AMOUNTS};
|
||||
pub use filters::FILTERS;
|
||||
pub use oracle::{
|
||||
derive_daily_ohlc, derive_daily_ohlc_with_confidence, derive_height_price,
|
||||
derive_ohlc_from_height_prices, derive_price_from_histogram, OracleConfig, OracleResult,
|
||||
};
|
||||
pub use signal::{compute_expected_bins_per_day, usd_to_bin};
|
||||
pub use histogram::load_or_compute_output_conditions;
|
||||
|
||||
@@ -160,6 +160,7 @@ impl Query {
|
||||
total,
|
||||
start,
|
||||
end,
|
||||
height: *self.height(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -173,6 +174,7 @@ impl Query {
|
||||
total,
|
||||
start,
|
||||
end,
|
||||
..
|
||||
} = resolved;
|
||||
|
||||
let output = match format {
|
||||
|
||||
@@ -13,6 +13,7 @@ impl Query {
|
||||
total,
|
||||
start,
|
||||
end,
|
||||
..
|
||||
} = resolved;
|
||||
|
||||
if vecs.is_empty() {
|
||||
|
||||
@@ -10,11 +10,12 @@ pub struct ResolvedQuery {
|
||||
pub(crate) total: usize,
|
||||
pub(crate) start: usize,
|
||||
pub(crate) end: usize,
|
||||
pub(crate) height: u32,
|
||||
}
|
||||
|
||||
impl ResolvedQuery {
|
||||
pub fn etag(&self) -> Etag {
|
||||
Etag::from_metric(self.version, self.total, self.start, self.end)
|
||||
Etag::from_metric(self.version, self.total, self.start, self.end, self.height)
|
||||
}
|
||||
|
||||
pub fn format(&self) -> Format {
|
||||
|
||||
@@ -12,4 +12,5 @@ pub trait AnyStore: Send + Sync {
|
||||
fn export_meta_if_needed(&mut self, height: Height) -> Result<()>;
|
||||
fn keyspace(&self) -> &Keyspace;
|
||||
fn commit(&mut self, height: Height) -> Result<()>;
|
||||
fn reset(&mut self) -> Result<()>;
|
||||
}
|
||||
|
||||
@@ -349,4 +349,15 @@ where
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<()> {
|
||||
self.meta.reset()?;
|
||||
self.puts.clear();
|
||||
self.dels.clear();
|
||||
for cache in &mut self.caches {
|
||||
cache.clear();
|
||||
}
|
||||
self.keyspace.clear()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,14 @@ impl StoreMeta {
|
||||
pub fn has(&self, height: Height) -> bool {
|
||||
!self.needs(height)
|
||||
}
|
||||
pub fn reset(&mut self) -> io::Result<()> {
|
||||
self.height = None;
|
||||
let path = self.path_height();
|
||||
if path.exists() {
|
||||
fs::remove_file(&path)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn path_height(&self) -> PathBuf {
|
||||
Self::path_height_(&self.pathbuf)
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ impl FromCoarserIndex<MonthIndex> for DateIndex {
|
||||
|
||||
impl FromCoarserIndex<QuarterIndex> for DateIndex {
|
||||
fn min_from(coarser: QuarterIndex) -> usize {
|
||||
let coarser = u16::from(coarser);
|
||||
let coarser = u8::from(coarser);
|
||||
if coarser == 0 {
|
||||
0
|
||||
} else {
|
||||
@@ -163,7 +163,7 @@ impl FromCoarserIndex<QuarterIndex> for DateIndex {
|
||||
fn max_from_(coarser: QuarterIndex) -> usize {
|
||||
let d = Date::new(2009, 3, 31)
|
||||
.into_jiff()
|
||||
.checked_add(Span::new().months(3 * u16::from(coarser)))
|
||||
.checked_add(Span::new().months(3 * u8::from(coarser)))
|
||||
.unwrap();
|
||||
DateIndex::try_from(Date::from(d)).unwrap().into()
|
||||
}
|
||||
@@ -171,7 +171,7 @@ impl FromCoarserIndex<QuarterIndex> for DateIndex {
|
||||
|
||||
impl FromCoarserIndex<SemesterIndex> for DateIndex {
|
||||
fn min_from(coarser: SemesterIndex) -> usize {
|
||||
let coarser = u16::from(coarser);
|
||||
let coarser = u8::from(coarser);
|
||||
if coarser == 0 {
|
||||
0
|
||||
} else {
|
||||
@@ -186,7 +186,7 @@ impl FromCoarserIndex<SemesterIndex> for DateIndex {
|
||||
fn max_from_(coarser: SemesterIndex) -> usize {
|
||||
let d = Date::new(2009, 5, 31)
|
||||
.into_jiff()
|
||||
.checked_add(Span::new().months(1 + 6 * u16::from(coarser)))
|
||||
.checked_add(Span::new().months(1 + 6 * u8::from(coarser)))
|
||||
.unwrap();
|
||||
DateIndex::try_from(Date::from(d)).unwrap().into()
|
||||
}
|
||||
@@ -194,18 +194,18 @@ impl FromCoarserIndex<SemesterIndex> for DateIndex {
|
||||
|
||||
impl FromCoarserIndex<YearIndex> for DateIndex {
|
||||
fn min_from(coarser: YearIndex) -> usize {
|
||||
let coarser = u16::from(coarser);
|
||||
let coarser = u8::from(coarser);
|
||||
if coarser == 0 {
|
||||
0
|
||||
} else {
|
||||
Self::try_from(Date::new(2009 + coarser, 1, 1))
|
||||
Self::try_from(Date::new(2009 + coarser as u16, 1, 1))
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn max_from_(coarser: YearIndex) -> usize {
|
||||
Self::try_from(Date::new(2009 + u16::from(coarser), 12, 31))
|
||||
Self::try_from(Date::new(2009 + u8::from(coarser) as u16, 12, 31))
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
@@ -213,19 +213,19 @@ impl FromCoarserIndex<YearIndex> for DateIndex {
|
||||
|
||||
impl FromCoarserIndex<DecadeIndex> for DateIndex {
|
||||
fn min_from(coarser: DecadeIndex) -> usize {
|
||||
let coarser = u16::from(coarser);
|
||||
let coarser = u8::from(coarser);
|
||||
if coarser == 0 {
|
||||
0
|
||||
} else {
|
||||
Self::try_from(Date::new(2000 + 10 * coarser, 1, 1))
|
||||
Self::try_from(Date::new(2000 + 10 * coarser as u16, 1, 1))
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn max_from_(coarser: DecadeIndex) -> usize {
|
||||
let coarser = u16::from(coarser);
|
||||
Self::try_from(Date::new(2009 + (10 * coarser), 12, 31))
|
||||
let coarser = u8::from(coarser);
|
||||
Self::try_from(Date::new(2009 + 10 * coarser as u16, 12, 31))
|
||||
.unwrap()
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -23,16 +23,16 @@ use super::{Date, DateIndex, YearIndex};
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct DecadeIndex(u16);
|
||||
pub struct DecadeIndex(u8);
|
||||
|
||||
impl From<u16> for DecadeIndex {
|
||||
impl From<u8> for DecadeIndex {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DecadeIndex> for u16 {
|
||||
impl From<DecadeIndex> for u8 {
|
||||
#[inline]
|
||||
fn from(value: DecadeIndex) -> Self {
|
||||
value.0
|
||||
@@ -42,7 +42,7 @@ impl From<DecadeIndex> for u16 {
|
||||
impl From<usize> for DecadeIndex {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ impl Add<usize> for DecadeIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 + rhs as u16)
|
||||
Self::from(self.0 + rhs as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ impl From<Date> for DecadeIndex {
|
||||
if year < 2000 {
|
||||
panic!("unsupported")
|
||||
}
|
||||
Self((year - 2000) / 10)
|
||||
Self(((year - 2000) / 10) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ impl From<YearIndex> for DecadeIndex {
|
||||
if v == 0 {
|
||||
Self(0)
|
||||
} else {
|
||||
Self((((v - 1) / 10) + 1) as u16)
|
||||
Self((((v - 1) / 10) + 1) as u8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,16 +44,16 @@ impl Etag {
|
||||
///
|
||||
/// Format varies based on whether the slice touches the end:
|
||||
/// - Slice ends before total: `{version:x}-{start}-{end}` (len irrelevant, data won't change if metric grows)
|
||||
/// - Slice reaches the end: `{version:x}-{start}-{total}` (len matters, new data would change results)
|
||||
/// - Slice reaches the end: `{version:x}-{start}-{total}-{height}` (includes height since last value may be recomputed each block)
|
||||
///
|
||||
/// `version` is the metric version for single queries, or the sum of versions for bulk queries.
|
||||
pub fn from_metric(version: u64, total: usize, start: usize, end: usize) -> Self {
|
||||
pub fn from_metric(version: u64, total: usize, start: usize, end: usize, height: u32) -> Self {
|
||||
if end < total {
|
||||
// Fixed window not at the end - len doesn't matter
|
||||
Self(format!("{version:x}-{start}-{end}"))
|
||||
} else {
|
||||
// Fetching up to current end - len matters
|
||||
Self(format!("{version:x}-{start}-{total}"))
|
||||
// Fetching up to current end - include height since last value may change each block
|
||||
Self(format!("{version:x}-{start}-{total}-{height}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,17 +25,17 @@ pub const BLOCKS_PER_HALVING: u32 = 210_000;
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct HalvingEpoch(u16);
|
||||
pub struct HalvingEpoch(u8);
|
||||
|
||||
impl HalvingEpoch {
|
||||
pub const fn new(value: u16) -> Self {
|
||||
pub const fn new(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for HalvingEpoch {
|
||||
impl From<u8> for HalvingEpoch {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ impl From<u16> for HalvingEpoch {
|
||||
impl From<usize> for HalvingEpoch {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,14 +72,14 @@ impl Add<usize> for HalvingEpoch {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 + rhs as u16)
|
||||
Self::from(self.0 + rhs as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Height> for HalvingEpoch {
|
||||
#[inline]
|
||||
fn from(value: Height) -> Self {
|
||||
Self((u32::from(value) / BLOCKS_PER_HALVING) as u16)
|
||||
Self((u32::from(value) / BLOCKS_PER_HALVING) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ mod stored_bool;
|
||||
mod stored_f32;
|
||||
mod stored_f64;
|
||||
mod stored_i16;
|
||||
mod stored_i8;
|
||||
mod stored_string;
|
||||
mod stored_u16;
|
||||
mod stored_u32;
|
||||
@@ -302,6 +303,7 @@ pub use stored_bool::*;
|
||||
pub use stored_f32::*;
|
||||
pub use stored_f64::*;
|
||||
pub use stored_i16::*;
|
||||
pub use stored_i8::*;
|
||||
pub use stored_string::*;
|
||||
pub use stored_u8::*;
|
||||
pub use stored_u16::*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{Etag, Output, OutputLegacy};
|
||||
use crate::{Output, OutputLegacy};
|
||||
|
||||
/// Metric output with metadata for caching.
|
||||
#[derive(Debug)]
|
||||
@@ -10,12 +10,6 @@ pub struct MetricOutput {
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
impl MetricOutput {
|
||||
pub fn etag(&self) -> Etag {
|
||||
Etag::from_metric(self.version, self.total, self.start, self.end)
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated: Legacy metric output with metadata for caching.
|
||||
#[derive(Debug)]
|
||||
pub struct MetricOutputLegacy {
|
||||
@@ -25,9 +19,3 @@ pub struct MetricOutputLegacy {
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
impl MetricOutputLegacy {
|
||||
pub fn etag(&self) -> Etag {
|
||||
Etag::from_metric(self.version, self.total, self.start, self.end)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ impl From<DateIndex> for MonthIndex {
|
||||
impl From<Date> for MonthIndex {
|
||||
#[inline]
|
||||
fn from(value: Date) -> Self {
|
||||
Self(u16::from(YearIndex::from(value)) * 12 + value.month() as u16 - 1)
|
||||
Self(u8::from(YearIndex::from(value)) as u16 * 12 + value.month() as u16 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::AddressBytes;
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[repr(u16)]
|
||||
#[repr(u8)]
|
||||
/// Type (P2PKH, P2WPKH, P2SH, P2TR, etc.)
|
||||
pub enum OutputType {
|
||||
P2PK65,
|
||||
@@ -41,8 +41,8 @@ pub enum OutputType {
|
||||
}
|
||||
|
||||
impl OutputType {
|
||||
fn is_valid(value: u16) -> bool {
|
||||
value <= Self::Unknown as u16
|
||||
fn is_valid(value: u8) -> bool {
|
||||
value <= Self::Unknown as u8
|
||||
}
|
||||
|
||||
pub fn is_spendable(&self) -> bool {
|
||||
@@ -205,7 +205,7 @@ impl Bytes for OutputType {
|
||||
|
||||
#[inline]
|
||||
fn to_bytes(&self) -> Self::Array {
|
||||
(*self as u16).to_le_bytes()
|
||||
[*self as u8]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -216,7 +216,7 @@ impl Bytes for OutputType {
|
||||
received: bytes.len(),
|
||||
});
|
||||
};
|
||||
let value = u16::from_le_bytes([bytes[0], bytes[1]]);
|
||||
let value = bytes[0];
|
||||
if !Self::is_valid(value) {
|
||||
return Err(vecdb::Error::InvalidArgument("invalid OutputType"));
|
||||
}
|
||||
@@ -227,7 +227,7 @@ impl Bytes for OutputType {
|
||||
}
|
||||
|
||||
impl Pco for OutputType {
|
||||
type NumberType = u16;
|
||||
type NumberType = u8;
|
||||
}
|
||||
|
||||
impl TransparentPco<u16> for OutputType {}
|
||||
impl TransparentPco<u8> for OutputType {}
|
||||
|
||||
@@ -23,11 +23,11 @@ use super::MonthIndex;
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct QuarterIndex(u16);
|
||||
pub struct QuarterIndex(u8);
|
||||
|
||||
impl From<u16> for QuarterIndex {
|
||||
impl From<u8> for QuarterIndex {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,11 @@ impl From<u16> for QuarterIndex {
|
||||
impl From<usize> for QuarterIndex {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<QuarterIndex> for u16 {
|
||||
impl From<QuarterIndex> for u8 {
|
||||
#[inline]
|
||||
fn from(value: QuarterIndex) -> Self {
|
||||
value.0
|
||||
@@ -57,7 +57,7 @@ impl Add<usize> for QuarterIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 + rhs as u16)
|
||||
Self::from(self.0 + rhs as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ impl Div<usize> for QuarterIndex {
|
||||
impl From<MonthIndex> for QuarterIndex {
|
||||
#[inline]
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self((usize::from(value) / 3) as u16)
|
||||
Self((usize::from(value) / 3) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ use super::MonthIndex;
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct SemesterIndex(u16);
|
||||
pub struct SemesterIndex(u8);
|
||||
|
||||
impl From<u16> for SemesterIndex {
|
||||
impl From<u8> for SemesterIndex {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,11 @@ impl From<u16> for SemesterIndex {
|
||||
impl From<usize> for SemesterIndex {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SemesterIndex> for u16 {
|
||||
impl From<SemesterIndex> for u8 {
|
||||
#[inline]
|
||||
fn from(value: SemesterIndex) -> Self {
|
||||
value.0
|
||||
@@ -57,7 +57,7 @@ impl Add<usize> for SemesterIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 + rhs as u16)
|
||||
Self::from(self.0 + rhs as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ impl Div<usize> for SemesterIndex {
|
||||
impl From<MonthIndex> for SemesterIndex {
|
||||
#[inline]
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self((usize::from(value) / 6) as u16)
|
||||
Self((usize::from(value) / 6) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{Formattable, Pco, PrintableIndex};
|
||||
|
||||
/// Fixed-size boolean value optimized for on-disk storage (stored as u16)
|
||||
/// Fixed-size boolean value optimized for on-disk storage (stored as u8)
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
@@ -19,7 +19,7 @@ use vecdb::{Formattable, Pco, PrintableIndex};
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct StoredBool(u16);
|
||||
pub struct StoredBool(u8);
|
||||
|
||||
impl StoredBool {
|
||||
pub const FALSE: Self = Self(0);
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
|
||||
use derive_more::Deref;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Formattable, Pco, PrintableIndex};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Default,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct StoredI8(i8);
|
||||
|
||||
impl StoredI8 {
|
||||
pub const ZERO: Self = Self(0);
|
||||
|
||||
pub fn new(v: i8) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i8> for StoredI8 {
|
||||
#[inline]
|
||||
fn from(value: i8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for StoredI8 {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
if value > i8::MAX as usize {
|
||||
panic!("usize too big (value = {value})")
|
||||
}
|
||||
Self(value as i8)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<StoredI8> for StoredI8 {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredI8 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as i8)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredI8 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for StoredI8 {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = *self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for StoredI8 {
|
||||
#[inline]
|
||||
fn from(value: f64) -> Self {
|
||||
if value < i8::MIN as f64 || value > i8::MAX as f64 {
|
||||
panic!()
|
||||
}
|
||||
Self(value as i8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredI8> for f64 {
|
||||
#[inline]
|
||||
fn from(value: StoredI8) -> Self {
|
||||
value.0 as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredI8> for usize {
|
||||
#[inline]
|
||||
fn from(value: StoredI8) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintableIndex for StoredI8 {
|
||||
fn to_string() -> &'static str {
|
||||
"i8"
|
||||
}
|
||||
|
||||
fn to_possible_strings() -> &'static [&'static str] {
|
||||
&["i8"]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for StoredI8 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut buf = itoa::Buffer::new();
|
||||
let str = buf.format(self.0);
|
||||
f.write_str(str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Formattable for StoredI8 {
|
||||
#[inline(always)]
|
||||
fn may_need_escaping() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{Formattable, Pco};
|
||||
|
||||
use super::StoredU16;
|
||||
use super::StoredU8;
|
||||
|
||||
/// Transaction version number
|
||||
#[derive(
|
||||
@@ -20,13 +20,13 @@ use super::StoredU16;
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct TxVersion(u16);
|
||||
pub struct TxVersion(u8);
|
||||
|
||||
impl TxVersion {
|
||||
pub const ONE: Self = Self(1);
|
||||
pub const TWO: Self = Self(2);
|
||||
pub const THREE: Self = Self(3);
|
||||
pub const NON_STANDARD: Self = Self(u16::MAX);
|
||||
pub const NON_STANDARD: Self = Self(u8::MAX);
|
||||
}
|
||||
|
||||
impl From<bitcoin::transaction::Version> for TxVersion {
|
||||
@@ -48,7 +48,7 @@ impl From<TxVersion> for bitcoin::transaction::Version {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TxVersion> for StoredU16 {
|
||||
impl From<TxVersion> for StoredU8 {
|
||||
#[inline]
|
||||
fn from(value: TxVersion) -> Self {
|
||||
Self::from(value.0)
|
||||
|
||||
@@ -23,11 +23,11 @@ use super::{Date, DateIndex, MonthIndex};
|
||||
Pco,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub struct YearIndex(u16);
|
||||
pub struct YearIndex(u8);
|
||||
|
||||
impl From<u16> for YearIndex {
|
||||
impl From<u8> for YearIndex {
|
||||
#[inline]
|
||||
fn from(value: u16) -> Self {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ impl From<u16> for YearIndex {
|
||||
impl From<usize> for YearIndex {
|
||||
#[inline]
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as u16)
|
||||
Self(value as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ impl Add<usize> for YearIndex {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
Self::from(self.0 + rhs as u16)
|
||||
Self::from(self.0 + rhs as u8)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,11 +92,11 @@ impl From<DateIndex> for YearIndex {
|
||||
impl From<Date> for YearIndex {
|
||||
#[inline]
|
||||
fn from(value: Date) -> Self {
|
||||
Self(value.year() - 2009)
|
||||
Self((value.year() - 2009) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<YearIndex> for u16 {
|
||||
impl From<YearIndex> for u8 {
|
||||
#[inline]
|
||||
fn from(value: YearIndex) -> Self {
|
||||
value.0
|
||||
@@ -112,7 +112,7 @@ impl CheckedSub for YearIndex {
|
||||
impl From<MonthIndex> for YearIndex {
|
||||
#[inline]
|
||||
fn from(value: MonthIndex) -> Self {
|
||||
Self((usize::from(value) / 12) as u16)
|
||||
Self((usize::from(value) / 12) as u8)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user