global: snapshot + core: impl Display for bytes structs

This commit is contained in:
nym21
2025-03-04 12:29:19 +01:00
parent fc6f12fb22
commit 0d0edd7917
36 changed files with 782 additions and 331 deletions

View File

@@ -1,3 +1,4 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!(concat!("../", env!("CARGO_PKG_README")))]
#[cfg(feature = "core")]

View File

@@ -8,15 +8,19 @@ use crate::run::RunConfig;
pub fn query(params: QueryParams) -> color_eyre::Result<()> {
let config = RunConfig::import(None)?;
let mut indexer = Indexer::new(&config.indexeddir())?;
let mut indexer = Indexer::new(config.indexeddir())?;
indexer.import_vecs()?;
let mut computer = Computer::new(&config.computeddir());
let mut computer = Computer::new(config.computeddir());
computer.import_vecs()?;
let query = Query::build(&indexer, &computer);
let ids = params.values.iter().flat_map(|v| v.split(",")).collect::<Vec<_>>();
let ids = params
.values
.iter()
.flat_map(|v| v.split(","))
.collect::<Vec<_>>();
let index = Index::try_from(params.index.as_str())?;
@@ -36,7 +40,8 @@ pub fn query(params: QueryParams) -> color_eyre::Result<()> {
Value::List(v) => vec![v],
Value::Matrix(v) => v,
};
let mut table = v.to_table(ids.iter().map(|id| id.to_string()).collect::<Vec<_>>());
let mut table =
v.to_table(ids.iter().map(|id| id.to_string()).collect::<Vec<_>>());
table.with(Style::psql());
table.to_string()
}

View File

@@ -8,7 +8,7 @@ use std::{
use brk_computer::Computer;
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_parser::rpc::{self, Auth, RpcApi};
use brk_parser::rpc::{self, Auth, Client, RpcApi};
use brk_server::tokio;
use clap::{Parser, ValueEnum};
use color_eyre::eyre::eyre;
@@ -20,26 +20,17 @@ use crate::path_dot_brk;
pub fn run(config: RunConfig) -> color_eyre::Result<()> {
let config = RunConfig::import(Some(config))?;
let bitcoin_dir = config.bitcoindir();
let rpc = Box::leak(Box::new(rpc::Client::new(
&format!(
"http://{}:{}",
config.rpcconnect().unwrap_or(&"localhost".to_string()),
config.rpcport().unwrap_or(8332)
),
config.to_rpc_auth().unwrap(),
)?));
let rpc = config.rpc()?;
let exit = Exit::new();
let parser = brk_parser::Parser::new(bitcoin_dir.as_path(), rpc);
let parser = brk_parser::Parser::new(config.bitcoindir(), rpc);
let mut indexer = Indexer::new(&config.indexeddir())?;
let mut indexer = Indexer::new(config.indexeddir())?;
indexer.import_stores()?;
indexer.import_vecs()?;
let mut computer = Computer::new(&config.computeddir());
let mut computer = Computer::new(config.computeddir());
computer.import_stores()?;
computer.import_vecs()?;
@@ -52,7 +43,9 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
let handle = if config.serve() {
Some(tokio::spawn(async move {
brk_server::main(served_indexer, served_computer).await.unwrap();
brk_server::main(served_indexer, served_computer)
.await
.unwrap();
}))
} else {
None
@@ -231,7 +224,7 @@ impl RunConfig {
std::process::exit(1);
}
if self.to_rpc_auth().is_err() {
if self.rpc_auth().is_err() {
println!(
"No way found to authenticate the RPC client, please either set --rpccookiefile or --rpcuser and --rpcpassword.\nRun the program with '-h' for help."
);
@@ -249,7 +242,18 @@ impl RunConfig {
fs::write(path, toml::to_string(self).unwrap())
}
pub fn to_rpc_auth(&self) -> color_eyre::Result<Auth> {
pub fn rpc(&self) -> color_eyre::Result<&'static Client> {
Ok(Box::leak(Box::new(rpc::Client::new(
&format!(
"http://{}:{}",
self.rpcconnect().unwrap_or(&"localhost".to_string()),
self.rpcport().unwrap_or(8332)
),
self.rpc_auth().unwrap(),
)?)))
}
fn rpc_auth(&self) -> color_eyre::Result<Auth> {
let cookie = self.path_cookiefile();
if cookie.is_file() {
@@ -264,11 +268,11 @@ impl RunConfig {
}
}
pub fn rpcconnect(&self) -> Option<&String> {
fn rpcconnect(&self) -> Option<&String> {
self.rpcconnect.as_ref()
}
pub fn rpcport(&self) -> Option<u16> {
fn rpcport(&self) -> Option<u16> {
self.rpcport
}
@@ -297,11 +301,13 @@ impl RunConfig {
}
pub fn process(&self) -> bool {
self.mode.is_none_or(|m| m == Mode::All || m == Mode::Processor)
self.mode
.is_none_or(|m| m == Mode::All || m == Mode::Processor)
}
pub fn serve(&self) -> bool {
self.mode.is_none_or(|m| m == Mode::All || m == Mode::Server)
self.mode
.is_none_or(|m| m == Mode::All || m == Mode::Server)
}
fn path_cookiefile(&self) -> PathBuf {
@@ -314,7 +320,9 @@ impl RunConfig {
fn fix_user_path(path: &str) -> PathBuf {
let fix = move |pattern: &str| {
if path.starts_with(pattern) {
let path = &path.replace(&format!("{pattern}/"), "").replace(pattern, "");
let path = &path
.replace(&format!("{pattern}/"), "")
.replace(pattern, "");
let home = std::env::var("HOME").unwrap();
@@ -328,7 +336,20 @@ impl RunConfig {
}
}
#[derive(Default, Debug, Clone, Copy, Parser, ValueEnum, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
#[derive(
Default,
Debug,
Clone,
Copy,
Parser,
ValueEnum,
Serialize,
Deserialize,
PartialEq,
Eq,
PartialOrd,
Ord,
)]
pub enum Mode {
#[default]
All,

View File

@@ -17,19 +17,19 @@ pub fn main() -> color_eyre::Result<()> {
let bitcoin_dir = Path::new("../../../bitcoin");
let rpc = Box::leak(Box::new(rpc::Client::new(
"http://localhost:8332",
rpc::Auth::CookieFile(Path::new(bitcoin_dir).join(".cookie")),
rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let exit = Exit::new();
let parser = Parser::new(bitcoin_dir, rpc);
let parser = Parser::new(bitcoin_dir.to_owned(), rpc);
let outputs_dir = Path::new("../../_outputs");
let mut indexer = Indexer::new(&outputs_dir.join("indexed"))?;
let mut indexer = Indexer::new(outputs_dir.join("indexed"))?;
indexer.import_stores()?;
indexer.import_vecs()?;
let mut computer = Computer::new(&outputs_dir.join("computed"));
let mut computer = Computer::new(outputs_dir.join("computed"));
computer.import_stores()?;
computer.import_vecs()?;

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::path::{Path, PathBuf};
@@ -23,9 +24,9 @@ pub struct Computer {
}
impl Computer {
pub fn new(computed_dir: &Path) -> Self {
pub fn new(computed_dir: PathBuf) -> Self {
Self {
path: computed_dir.to_owned(),
path: computed_dir,
vecs: None,
stores: None,
}
@@ -36,6 +37,8 @@ impl Computer {
Ok(())
}
/// Do NOT import multiple times are things will break !!!
/// Clone struct instead
pub fn import_stores(&mut self) -> color_eyre::Result<()> {
self.stores = Some(Stores::import(&self.path.join("stores"))?);
Ok(())
@@ -43,7 +46,12 @@ impl Computer {
}
impl Computer {
pub fn compute(&mut self, indexer: &mut Indexer, starting_indexes: Indexes, exit: &Exit) -> color_eyre::Result<()> {
pub fn compute(
&mut self,
indexer: &mut Indexer,
starting_indexes: Indexes,
exit: &Exit,
) -> color_eyre::Result<()> {
info!("Computing...");
let height_count = indexer.vecs().height_to_size.len();

View File

@@ -16,7 +16,7 @@ log = { workspace = true }
rapidhash = "1.4.0"
rlimit = "0.10.2"
serde = { workspace = true }
serde_bytes = "0.11.15"
serde_bytes = "0.11.16"
zerocopy = { workspace = true }
[package.metadata.cargo-machete]

View File

@@ -1,3 +1,4 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
mod error;

View File

@@ -1,6 +1,13 @@
use bitcoin::ScriptBuf;
use std::fmt;
use bitcoin::{
Address, Network, ScriptBuf,
hex::{Case, DisplayHex},
opcodes,
script::Builder,
};
use derive_deref::{Deref, DerefMut};
use serde::Serialize;
use serde::{Serialize, Serializer};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::Error;
@@ -89,64 +96,207 @@ impl TryFrom<(&ScriptBuf, Addresstype)> for Addressbytes {
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PK65AddressBytes(U8x65);
impl fmt::Display for P2PK65AddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_hex_string(Case::Lower))
}
}
impl Serialize for P2PK65AddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2PK65AddressBytes> for Addressbytes {
fn from(value: P2PK65AddressBytes) -> Self {
Self::P2PK65(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PK33AddressBytes(U8x33);
impl fmt::Display for P2PK33AddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_hex_string(Case::Lower))
}
}
impl Serialize for P2PK33AddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2PK33AddressBytes> for Addressbytes {
fn from(value: P2PK33AddressBytes) -> Self {
Self::P2PK33(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2PKHAddressBytes(U8x20);
impl fmt::Display for P2PKHAddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let script = Builder::new()
.push_opcode(opcodes::all::OP_DUP)
.push_opcode(opcodes::all::OP_HASH160)
.push_slice(*self.0)
.push_opcode(opcodes::all::OP_EQUALVERIFY)
.push_opcode(opcodes::all::OP_CHECKSIG)
.into_script();
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
write!(f, "{}", address)
}
}
impl Serialize for P2PKHAddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2PKHAddressBytes> for Addressbytes {
fn from(value: P2PKHAddressBytes) -> Self {
Self::P2PKH(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2SHAddressBytes(U8x20);
impl fmt::Display for P2SHAddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let script = Builder::new()
.push_opcode(opcodes::all::OP_HASH160)
.push_slice(*self.0)
.push_opcode(opcodes::all::OP_EQUAL)
.into_script();
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
write!(f, "{}", address)
}
}
impl Serialize for P2SHAddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2SHAddressBytes> for Addressbytes {
fn from(value: P2SHAddressBytes) -> Self {
Self::P2SH(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2WPKHAddressBytes(U8x20);
impl fmt::Display for P2WPKHAddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
write!(f, "{}", address)
}
}
impl Serialize for P2WPKHAddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2WPKHAddressBytes> for Addressbytes {
fn from(value: P2WPKHAddressBytes) -> Self {
Self::P2WPKH(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2WSHAddressBytes(U8x32);
impl fmt::Display for P2WSHAddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let script = Builder::new().push_int(0).push_slice(*self.0).into_script();
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
write!(f, "{}", address)
}
}
impl Serialize for P2WSHAddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2WSHAddressBytes> for Addressbytes {
fn from(value: P2WSHAddressBytes) -> Self {
Self::P2WSH(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct P2TRAddressBytes(U8x32);
impl fmt::Display for P2TRAddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let script = Builder::new().push_int(1).push_slice(*self.0).into_script();
let address = Address::from_script(&script, Network::Bitcoin).unwrap();
write!(f, "{}", address)
}
}
impl Serialize for P2TRAddressBytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(&self.to_string())
}
}
impl From<P2TRAddressBytes> for Addressbytes {
fn from(value: P2TRAddressBytes) -> Self {
Self::P2TR(value)
}
}
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2PK65AddressBytes(U8x65);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2PK33AddressBytes(U8x33);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2PKHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2SHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2WPKHAddressBytes(U8x20);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2WSHAddressBytes(U8x32);
#[derive(Debug, Clone, Deref, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
pub struct P2TRAddressBytes(U8x32);
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(
Debug,
Clone,
Deref,
DerefMut,
PartialEq,
Eq,
Immutable,
IntoBytes,
KnownLayout,
FromBytes,
Serialize,
)]
pub struct U8x20([u8; 20]);
impl From<&[u8]> for U8x20 {
fn from(slice: &[u8]) -> Self {
@@ -156,7 +306,19 @@ impl From<&[u8]> for U8x20 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(
Debug,
Clone,
Deref,
DerefMut,
PartialEq,
Eq,
Immutable,
IntoBytes,
KnownLayout,
FromBytes,
Serialize,
)]
pub struct U8x32([u8; 32]);
impl From<&[u8]> for U8x32 {
fn from(slice: &[u8]) -> Self {
@@ -166,7 +328,19 @@ impl From<&[u8]> for U8x32 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(
Debug,
Clone,
Deref,
DerefMut,
PartialEq,
Eq,
Immutable,
IntoBytes,
KnownLayout,
FromBytes,
Serialize,
)]
pub struct U8x33(#[serde(with = "serde_bytes")] [u8; 33]);
impl From<&[u8]> for U8x33 {
fn from(slice: &[u8]) -> Self {
@@ -176,7 +350,19 @@ impl From<&[u8]> for U8x33 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(
Debug,
Clone,
Deref,
DerefMut,
PartialEq,
Eq,
Immutable,
IntoBytes,
KnownLayout,
FromBytes,
Serialize,
)]
pub struct U8x64(#[serde(with = "serde_bytes")] [u8; 64]);
impl From<&[u8]> for U8x64 {
fn from(slice: &[u8]) -> Self {
@@ -186,7 +372,19 @@ impl From<&[u8]> for U8x64 {
}
}
#[derive(Debug, Clone, Deref, DerefMut, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(
Debug,
Clone,
Deref,
DerefMut,
PartialEq,
Eq,
Immutable,
IntoBytes,
KnownLayout,
FromBytes,
Serialize,
)]
pub struct U8x65(#[serde(with = "serde_bytes")] [u8; 65]);
impl From<&[u8]> for U8x65 {
fn from(slice: &[u8]) -> Self {

View File

@@ -1,13 +1,14 @@
use std::mem;
use std::{fmt, mem};
use bitcoin::hashes::Hash;
use bitcoincore_rpc::{Client, RpcApi};
use derive_deref::Deref;
use serde::Serialize;
use serde::{Serialize, Serializer};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::Height;
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct BlockHash([u8; 32]);
impl From<bitcoin::BlockHash> for BlockHash {
@@ -22,9 +23,30 @@ impl From<BlockHash> for bitcoin::BlockHash {
}
}
impl From<&BlockHash> for bitcoin::BlockHash {
fn from(value: &BlockHash) -> Self {
bitcoin::BlockHash::from_slice(&value.0).unwrap()
}
}
impl TryFrom<(&Client, Height)> for BlockHash {
type Error = bitcoincore_rpc::Error;
fn try_from((rpc, height): (&Client, Height)) -> Result<Self, Self::Error> {
Ok(Self::from(rpc.get_block_hash(u64::from(height))?))
}
}
impl fmt::Display for BlockHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", bitcoin::BlockHash::from(self))
}
}
impl Serialize for BlockHash {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

View File

@@ -1,11 +1,11 @@
use jiff::{Span, civil::Date as Date_, tz::TimeZone};
use serde::Serialize;
use serde::{Serialize, Serializer};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::{Dateindex, Timestamp};
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromBytes, Immutable, IntoBytes, KnownLayout,
)]
pub struct Date(u32);
@@ -52,7 +52,9 @@ impl From<Date> for Date_ {
impl From<Timestamp> for Date {
fn from(value: Timestamp) -> Self {
Self::from(Date_::from(jiff::Timestamp::from(value).to_zoned(TimeZone::UTC)))
Self::from(Date_::from(
jiff::Timestamp::from(value).to_zoned(TimeZone::UTC),
))
}
}
@@ -68,6 +70,20 @@ impl From<Dateindex> for Date {
impl std::fmt::Display for Date {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("{}-{}-{}", self.year(), self.month(), self.day()))
f.write_str(&format!(
"{}-{:0>2}-{:0>2}",
self.year(),
self.month(),
self.day()
))
}
}
impl Serialize for Date {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

View File

@@ -1,10 +1,11 @@
use std::mem;
use std::{fmt, mem};
use bitcoin::hashes::Hash;
use derive_deref::Deref;
use serde::Serialize;
use serde::{Serialize, Serializer};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes, Serialize)]
#[derive(Debug, Deref, Clone, PartialEq, Eq, Immutable, IntoBytes, KnownLayout, FromBytes)]
pub struct Txid([u8; 32]);
impl From<bitcoin::Txid> for Txid {
@@ -18,3 +19,24 @@ impl From<Txid> for bitcoin::Txid {
unsafe { mem::transmute(value) }
}
}
impl From<&Txid> for bitcoin::Txid {
fn from(value: &Txid) -> Self {
bitcoin::Txid::from_slice(&value.0).unwrap()
}
}
impl fmt::Display for Txid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", bitcoin::Txid::from(self))
}
}
impl Serialize for Txid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

View File

@@ -1,3 +1,4 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
use std::{

View File

@@ -9,7 +9,11 @@ fn main() -> color_eyre::Result<()> {
let mut fetcher = Fetcher::import(None)?;
dbg!(fetcher.get_date(Date::new(2025, 1, 1))?);
dbg!(fetcher.get_height(885604_u32.into(), 1740683986.into(), Some(1740683000.into()))?);
dbg!(fetcher.get_height(
880_000_u32.into(),
1740683986.into(),
Some(1740683000.into())
)?);
Ok(())
}

View File

@@ -30,12 +30,19 @@ impl Kibo {
pub fn get_from_height(&mut self, height: Height) -> color_eyre::Result<OHLCCents> {
#[allow(clippy::map_entry)]
if !self.height_to_ohlc_vec.contains_key(&height)
|| ((usize::from(height) + self.height_to_ohlc_vec.get(&height).unwrap().len()) <= usize::from(height))
|| ((usize::from(height) + self.height_to_ohlc_vec.get(&height).unwrap().len())
<= usize::from(height))
{
self.height_to_ohlc_vec
.insert(height, Self::fetch_height_prices(height)?);
self.height_to_ohlc_vec.insert(
height,
Self::fetch_height_prices(height).inspect_err(|e| {
dbg!(e);
})?,
);
}
dbg!(&self.height_to_ohlc_vec.keys());
self.height_to_ohlc_vec
.get(&height)
.unwrap()
@@ -51,9 +58,9 @@ impl Kibo {
|try_index| {
let base_url = Self::get_base_url(try_index);
let body: Value = minreq::get(format!("{base_url}/height-to-price?chunk={}", height))
.send()?
.json()?;
let url = format!("{base_url}/height-to-price?chunk={}", height);
let body: Value = minreq::get(url).send()?.json()?;
let vec = body
.as_object()
@@ -91,7 +98,8 @@ impl Kibo {
.0
< date
{
self.year_to_date_to_ohlc.insert(year, Self::fetch_date_prices(year)?);
self.year_to_date_to_ohlc
.insert(year, Self::fetch_date_prices(year)?);
}
self.year_to_date_to_ohlc
@@ -125,7 +133,8 @@ impl Kibo {
.context("Expect to be an object")?
.iter()
.map(|(serialized_date, value)| -> color_eyre::Result<_> {
let date = Date::from(jiff::civil::Date::from_str(serialized_date).unwrap());
let date =
Date::from(jiff::civil::Date::from_str(serialized_date).unwrap());
Ok((date, Self::value_to_ohlc(value)?))
})
.collect::<Result<BTreeMap<_, _>, _>>()

View File

@@ -1,4 +1,4 @@
use std::{thread::sleep, time::Duration};
use std::{fmt::Debug, thread::sleep, time::Duration};
use log::info;
@@ -6,7 +6,10 @@ pub fn retry<T>(
function: impl Fn(usize) -> color_eyre::Result<T>,
sleep_in_s: u64,
retries: usize,
) -> color_eyre::Result<T> {
) -> color_eyre::Result<T>
where
T: Debug,
{
let mut i = 0;
loop {

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::{collections::BTreeMap, fs, path::Path};
@@ -93,9 +94,10 @@ impl Fetcher {
previous_timestamp: Option<Timestamp>,
name: &str,
) -> color_eyre::Result<OHLCCents> {
let previous_ohlc = previous_timestamp.map_or(Some(OHLCCents::default()), |previous_timestamp| {
tree.get(&previous_timestamp).cloned()
});
let previous_ohlc = previous_timestamp
.map_or(Some(OHLCCents::default()), |previous_timestamp| {
tree.get(&previous_timestamp).cloned()
});
let last_ohlc = tree.get(&timestamp);

View File

@@ -16,13 +16,13 @@ fn main() -> color_eyre::Result<()> {
let bitcoin_dir = Path::new("../../../bitcoin");
let rpc = Box::leak(Box::new(rpc::Client::new(
"http://localhost:8332",
rpc::Auth::CookieFile(Path::new(bitcoin_dir).join(".cookie")),
rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let exit = Exit::new();
let parser = Parser::new(bitcoin_dir, rpc);
let parser = Parser::new(bitcoin_dir.to_owned(), rpc);
let mut indexer = Indexer::new(Path::new("../../_outputs/indexed"))?;
let mut indexer = Indexer::new(Path::new("../../_outputs/indexed").to_owned())?;
indexer.import_stores()?;
indexer.import_vecs()?;

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::{
@@ -11,8 +12,8 @@ use std::{
};
use brk_core::{
AddressHash, Addressbytes, Addressindex, Addresstype, BlockHash, BlockHashPrefix, Height, Sats, Timestamp, Txid,
TxidPrefix, Txindex, Txinindex, Txoutindex, Vin, Vout, setrlimit,
AddressHash, Addressbytes, Addressindex, Addresstype, BlockHash, BlockHashPrefix, Height, Sats,
Timestamp, Txid, TxidPrefix, Txindex, Txinindex, Txoutindex, Vin, Vout, setrlimit,
};
pub use brk_parser::*;
@@ -39,10 +40,10 @@ pub struct Indexer {
}
impl Indexer {
pub fn new(indexes_dir: &Path) -> color_eyre::Result<Self> {
pub fn new(indexes_dir: PathBuf) -> color_eyre::Result<Self> {
setrlimit()?;
Ok(Self {
path: indexes_dir.to_owned(),
path: indexes_dir,
vecs: None,
stores: None,
})
@@ -53,27 +54,40 @@ impl Indexer {
Ok(())
}
/// Do NOT import multiple times are things will break !!!
pub fn import_stores(&mut self) -> color_eyre::Result<()> {
self.stores = Some(Stores::import(&self.path.join("stores"))?);
Ok(())
}
pub fn index(&mut self, parser: &Parser, rpc: &'static rpc::Client, exit: &Exit) -> color_eyre::Result<Indexes> {
pub fn index(
&mut self,
parser: &Parser,
rpc: &'static rpc::Client,
exit: &Exit,
) -> color_eyre::Result<Indexes> {
let check_collisions = true;
let starting_indexes = Indexes::try_from((self.vecs.as_mut().unwrap(), self.stores.as_ref().unwrap(), rpc))
.unwrap_or_else(|_| {
let indexes = Indexes::default();
indexes.push_if_needed(self.vecs.as_mut().unwrap()).unwrap();
indexes
});
let starting_indexes = Indexes::try_from((
self.vecs.as_mut().unwrap(),
self.stores.as_ref().unwrap(),
rpc,
))
.unwrap_or_else(|_| {
let indexes = Indexes::default();
indexes.push_if_needed(self.vecs.as_mut().unwrap()).unwrap();
indexes
});
exit.block();
self.stores
.as_mut()
.unwrap()
.rollback_if_needed(self.vecs.as_ref().unwrap(), &starting_indexes)?;
self.vecs.as_mut().unwrap().rollback_if_needed(&starting_indexes)?;
self.vecs
.as_mut()
.unwrap()
.rollback_if_needed(&starting_indexes)?;
exit.release();
let vecs = self.vecs.as_mut().unwrap();
@@ -84,25 +98,31 @@ impl Indexer {
let start = Some(idxs.height);
let end = None; //Some(Height::new(400_000));
if starting_indexes.height > Height::try_from(rpc)? || end.is_some_and(|end| starting_indexes.height > end) {
if starting_indexes.height > Height::try_from(rpc)?
|| end.is_some_and(|end| starting_indexes.height > end)
{
return Ok(starting_indexes);
}
info!("Started indexing...");
let export_if_needed =
|stores: &mut Stores, vecs: &mut Vecs, height: Height, rem: bool, exit: &Exit| -> color_eyre::Result<()> {
if height == 0 || (height % SNAPSHOT_BLOCK_RANGE != 0) != rem || exit.triggered() {
return Ok(());
}
let export_if_needed = |stores: &mut Stores,
vecs: &mut Vecs,
height: Height,
rem: bool,
exit: &Exit|
-> color_eyre::Result<()> {
if height == 0 || (height % SNAPSHOT_BLOCK_RANGE != 0) != rem || exit.triggered() {
return Ok(());
}
info!("Exporting...");
exit.block();
stores.commit(height)?;
vecs.flush(height)?;
exit.release();
Ok(())
};
info!("Exporting...");
exit.block();
stores.commit(height)?;
vecs.flush(height)?;
exit.release();
Ok(())
};
parser.parse(start, None).iter().try_for_each(
|(height, block, blockhash)| -> color_eyre::Result<()> {

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::{
@@ -18,7 +19,11 @@ use jiff::{Timestamp, tz};
pub fn init(path: Option<&Path>) {
let file = path.map(|path| {
let _ = fs::remove_file(path);
OpenOptions::new().create(true).append(true).open(path).unwrap()
OpenOptions::new()
.create(true)
.append(true)
.open(path)
.unwrap()
});
Builder::from_env(Env::default().default_filter_or("info,fjall=off,lsm_tree=off"))
@@ -34,7 +39,14 @@ pub fn init(path: Option<&Path>) {
let args = record.args();
if let Some(file) = file.as_ref() {
let _ = write(file.try_clone().unwrap(), &date_time, target, &level, dash, args);
let _ = write(
file.try_clone().unwrap(),
&date_time,
target,
&level,
dash,
args,
);
}
let colored_date_time = date_time.bright_black();
@@ -48,7 +60,14 @@ pub fn init(path: Option<&Path>) {
};
let colored_dash = dash.bright_black();
write(buf, colored_date_time, target, colored_level, colored_dash, args)
write(
buf,
colored_date_time,
target,
colored_level,
colored_dash,
args,
)
})
.init();
}

View File

@@ -0,0 +1,58 @@
use std::path::Path;
use bitcoincore_rpc::{Auth, Client};
use brk_core::Height;
use brk_parser::Parser;
fn main() {
let i = std::time::Instant::now();
let bitcoin_dir = Path::new("../../../bitcoin");
let rpc = Box::leak(Box::new(
Client::new(
"http://localhost:8332",
Auth::CookieFile(bitcoin_dir.join(".cookie")),
)
.unwrap(),
));
// let start = None;
// let end = None;
let parser = Parser::new(bitcoin_dir.to_owned(), rpc);
// parser
// .parse(start, end)
// .iter()
// .for_each(|(height, _block, hash)| {
// println!("{height}: {hash}");
// });
println!(
"{}",
parser
.get(Height::new(0))
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.script_pubkey
);
println!(
"{}",
parser
.get(Height::new(840_000))
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.value
);
dbg!(i.elapsed());
}

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::{
@@ -8,7 +9,7 @@ use std::{
collections::BTreeMap,
fs::{self},
ops::ControlFlow,
path::{Path, PathBuf},
path::PathBuf,
thread,
};
@@ -52,15 +53,16 @@ pub struct Parser {
}
impl Parser {
pub fn new(bitcoin_dir: &Path, rpc: &'static bitcoincore_rpc::Client) -> Self {
Self {
bitcoin_dir: bitcoin_dir.to_owned(),
rpc,
}
pub fn new(bitcoin_dir: PathBuf, rpc: &'static bitcoincore_rpc::Client) -> Self {
Self { bitcoin_dir, rpc }
}
pub fn get(&self, height: Height) -> Block {
self.parse(Some(height), Some(height)).iter().next().unwrap().1
self.parse(Some(height), Some(height))
.iter()
.next()
.unwrap()
.1
}
///
@@ -68,7 +70,11 @@ impl Parser {
///
/// For an example checkout `./main.rs`
///
pub fn parse(&self, start: Option<Height>, end: Option<Height>) -> Receiver<(Height, Block, BlockHash)> {
pub fn parse(
&self,
start: Option<Height>,
end: Option<Height>,
) -> Receiver<(Height, Block, BlockHash)> {
let bitcoin_dir = self.bitcoin_dir.as_path();
let rpc = self.rpc;
@@ -119,9 +125,12 @@ impl Parser {
}
}
let len =
u32::from_le_bytes(xor_i.bytes(&mut blk_bytes[i..(i + 4)], &xor_bytes).try_into().unwrap())
as usize;
let len = u32::from_le_bytes(
xor_i
.bytes(&mut blk_bytes[i..(i + 4)], &xor_bytes)
.try_into()
.unwrap(),
) as usize;
i += 4;
let block_bytes = (blk_bytes[i..(i + len)]).to_vec();
@@ -152,18 +161,19 @@ impl Parser {
BlockState::decode(block_state, xor_i, &xor_bytes);
});
bulk.drain(..).try_for_each(|(blk_metadata, block_state, _)| {
let block = match block_state {
BlockState::Decoded(block) => block,
_ => unreachable!(),
};
bulk.drain(..)
.try_for_each(|(blk_metadata, block_state, _)| {
let block = match block_state {
BlockState::Decoded(block) => block,
_ => unreachable!(),
};
if send_block.send((blk_metadata, block)).is_err() {
return ControlFlow::Break(());
}
if send_block.send((blk_metadata, block)).is_err() {
return ControlFlow::Break(());
}
ControlFlow::Continue(())
})
ControlFlow::Continue(())
})
};
recv_bytes.iter().try_for_each(|tuple| {
@@ -230,7 +240,9 @@ impl Parser {
let mut opt = if current_height == height {
Some((block, hash))
} else {
if start.is_none_or(|start| start <= height) && end.is_none_or(|end| end >= height) {
if start.is_none_or(|start| start <= height)
&& end.is_none_or(|end| end >= height)
{
future_blocks.insert(height, (block, hash));
}
None
@@ -247,7 +259,9 @@ impl Parser {
return ControlFlow::Break(());
}
send_height_block_hash.send((current_height, block, hash)).unwrap();
send_height_block_hash
.send((current_height, block, hash))
.unwrap();
if end.is_some_and(|end| end == current_height) {
return ControlFlow::Break(());

View File

@@ -1,32 +0,0 @@
use std::path::Path;
use bitcoincore_rpc::{Auth, Client};
use brk_core::Height;
use brk_parser::Parser;
fn main() {
let i = std::time::Instant::now();
let bitcoin_dir = Path::new("../../../bitcoin");
let rpc = Box::leak(Box::new(
Client::new(
"http://localhost:8332",
Auth::CookieFile(Path::new(bitcoin_dir).join(".cookie")),
)
.unwrap(),
));
let start = None;
let end = None;
let parser = Parser::new(bitcoin_dir, rpc);
parser.parse(start, end).iter().for_each(|(height, _block, hash)| {
println!("{height}: {hash}");
});
parser.get(Height::new(0));
parser.get(Height::new(840_000));
dbg!(i.elapsed());
}

View File

@@ -9,10 +9,10 @@ pub fn main() -> color_eyre::Result<()> {
let outputs_dir = Path::new("../../_outputs");
let mut indexer = Indexer::new(&outputs_dir.join("indexed"))?;
let mut indexer = Indexer::new(outputs_dir.join("indexed"))?;
indexer.import_vecs()?;
let mut computer = Computer::new(&outputs_dir.join("computed"));
let mut computer = Computer::new(outputs_dir.join("computed"));
computer.import_vecs()?;
let query = Query::build(&indexer, &computer);

View File

@@ -38,7 +38,8 @@ impl Index {
]
}
pub fn self_to_ids(&self) -> &[&str] {
pub fn possible_values(&self) -> &[&str] {
// Always have the "correct" id at the end
match self {
Self::Dateindex => &["d", "date", "dateindex"],
Self::Height => &["h", "height"],
@@ -56,10 +57,10 @@ impl Index {
}
}
pub fn possible_values() -> Vec<String> {
pub fn all_possible_values() -> Vec<String> {
Self::all()
.iter()
.flat_map(|i| i.self_to_ids().iter().map(|s| s.to_string()))
.flat_map(|i| i.possible_values().iter().map(|s| s.to_string()))
.collect::<Vec<_>>()
}
}
@@ -68,19 +69,19 @@ impl TryFrom<&str> for Index {
type Error = color_eyre::Report;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Ok(match value {
v if (Self::Dateindex).self_to_ids().contains(&v) => Self::Dateindex,
v if (Self::Height).self_to_ids().contains(&v) => Self::Height,
v if (Self::Txindex).self_to_ids().contains(&v) => Self::Txindex,
v if (Self::Txinindex).self_to_ids().contains(&v) => Self::Txinindex,
v if (Self::Txoutindex).self_to_ids().contains(&v) => Self::Txoutindex,
v if (Self::Addressindex).self_to_ids().contains(&v) => Self::Addressindex,
v if (Self::P2PK33index).self_to_ids().contains(&v) => Self::P2PK33index,
v if (Self::P2PK65index).self_to_ids().contains(&v) => Self::P2PK65index,
v if (Self::P2PKHindex).self_to_ids().contains(&v) => Self::P2PKHindex,
v if (Self::P2SHindex).self_to_ids().contains(&v) => Self::P2SHindex,
v if (Self::P2TRindex).self_to_ids().contains(&v) => Self::P2TRindex,
v if (Self::P2WPKHindex).self_to_ids().contains(&v) => Self::P2WPKHindex,
v if (Self::P2WSHindex).self_to_ids().contains(&v) => Self::P2WSHindex,
v if (Self::Dateindex).possible_values().contains(&v) => Self::Dateindex,
v if (Self::Height).possible_values().contains(&v) => Self::Height,
v if (Self::Txindex).possible_values().contains(&v) => Self::Txindex,
v if (Self::Txinindex).possible_values().contains(&v) => Self::Txinindex,
v if (Self::Txoutindex).possible_values().contains(&v) => Self::Txoutindex,
v if (Self::Addressindex).possible_values().contains(&v) => Self::Addressindex,
v if (Self::P2PK33index).possible_values().contains(&v) => Self::P2PK33index,
v if (Self::P2PK65index).possible_values().contains(&v) => Self::P2PK65index,
v if (Self::P2PKHindex).possible_values().contains(&v) => Self::P2PKHindex,
v if (Self::P2SHindex).possible_values().contains(&v) => Self::P2SHindex,
v if (Self::P2TRindex).possible_values().contains(&v) => Self::P2TRindex,
v if (Self::P2WPKHindex).possible_values().contains(&v) => Self::P2WPKHindex,
v if (Self::P2WSHindex).possible_values().contains(&v) => Self::P2WSHindex,
_ => return Err(eyre!("Bad index")),
})
}

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use brk_computer::Computer;
@@ -61,10 +62,15 @@ impl<'a> Query<'a> {
let tuples = ids
.iter()
.map(|s| {
(
s.to_owned(),
self.vecid_to_index_to_vec.get(&s.to_lowercase().replace("_", "-")),
)
let mut id = s.to_lowercase().replace("_", "-");
let mut res = self.vecid_to_index_to_vec.get(&id);
if res.is_none() {
if let Ok(index) = Index::try_from(id.as_str()) {
id = index.possible_values().last().unwrap().to_string();
res = self.vecid_to_index_to_vec.get(&id)
}
}
(id, res)
})
.filter(|(_, opt)| opt.is_some())
.map(|(id, vec)| (id, vec.unwrap()))
@@ -77,7 +83,9 @@ impl<'a> Query<'a> {
let mut values = tuples
.iter()
.flat_map(|(_, i_to_v)| i_to_v.get(&index))
.map(|vec| -> brk_vec::Result<Vec<serde_json::Value>> { vec.collect_range_values(from, to) })
.map(|vec| -> brk_vec::Result<Vec<serde_json::Value>> {
vec.collect_range_values(from, to)
})
.collect::<brk_vec::Result<Vec<_>>>()?;
if values.is_empty() {
@@ -88,7 +96,11 @@ impl<'a> Query<'a> {
Ok(match format {
Some(Format::CSV) | Some(Format::TSV) => {
let delimiter = if format == Some(Format::CSV) { ',' } else { '\t' };
let delimiter = if format == Some(Format::CSV) {
','
} else {
'\t'
};
let mut text = tuples
.into_iter()
@@ -120,7 +132,8 @@ impl<'a> Query<'a> {
}
}
Some(Format::MD) => {
let mut table = values.to_table(ids.iter().map(|s| s.to_string()).collect::<Vec<_>>());
let mut table =
values.to_table(tuples.iter().map(|(s, _)| s.to_owned()).collect::<Vec<_>>());
table.with(Style::markdown());

View File

@@ -5,7 +5,7 @@ use crate::{Format, Index};
#[derive(Debug, Deserialize, Parser)]
pub struct Params {
#[clap(short, long, value_parser = PossibleValuesParser::new(Index::possible_values()))]
#[clap(short, long, value_parser = PossibleValuesParser::new(Index::all_possible_values()))]
/// Index of the values requested
pub index: String,
#[clap(short, long, value_delimiter = ' ', num_args = 1..)]

View File

@@ -18,7 +18,7 @@ brk_vec = { workspace = true }
color-eyre = { workspace = true }
jiff = { workspace = true }
log = { workspace = true }
oxc = { version = "0.53.0", features = ["codegen", "minifier"] }
oxc = { version = "0.54.0", features = ["codegen", "minifier"] }
serde_json = { workspace = true }
tokio = { version = "1.43.0", features = ["full"] }
tower-http = { version = "0.6.2", features = ["compression-full"] }

View File

@@ -17,19 +17,19 @@ pub fn main() -> color_eyre::Result<()> {
let bitcoin_dir = Path::new("../../../bitcoin");
let rpc = Box::leak(Box::new(rpc::Client::new(
"http://localhost:8332",
rpc::Auth::CookieFile(Path::new(bitcoin_dir).join(".cookie")),
rpc::Auth::CookieFile(bitcoin_dir.join(".cookie")),
)?));
let exit = Exit::new();
let parser = Parser::new(bitcoin_dir, rpc);
let parser = Parser::new(bitcoin_dir.to_owned(), rpc);
let outputs_dir = Path::new("../../_outputs");
let mut indexer = Indexer::new(&outputs_dir.join("indexed"))?;
let mut indexer = Indexer::new(outputs_dir.join("indexed"))?;
indexer.import_stores()?;
indexer.import_vecs()?;
let mut computer = Computer::new(&outputs_dir.join("computed"));
let mut computer = Computer::new(outputs_dir.join("computed"));
computer.import_stores()?;
computer.import_vecs()?;
@@ -41,7 +41,9 @@ pub fn main() -> color_eyre::Result<()> {
let served_computer = computer.clone();
tokio::spawn(async move {
brk_server::main(served_indexer, served_computer).await.unwrap();
brk_server::main(served_indexer, served_computer)
.await
.unwrap();
});
loop {

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::time::Instant;
@@ -37,7 +38,11 @@ pub async fn main(indexer: Indexer, computer: Computer) -> color_eyre::Result<()
let state = AppState { query };
let compression_layer = CompressionLayer::new().br(true).deflate(true).gzip(true).zstd(true);
let compression_layer = CompressionLayer::new()
.br(true)
.deflate(true)
.gzip(true)
.zstd(true);
let router = Router::new()
.add_api_routes()

View File

@@ -1,6 +1,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc = "\n## Example\n\n```rust"]
#![doc = include_str!("main.rs")]
#![doc = include_str!("../examples/main.rs")]
#![doc = "```"]
use std::{
@@ -81,7 +82,11 @@ where
pub fn forced_import(path: &Path, version: Version) -> Result<Self> {
let res = Self::import(path, version);
match res {
Err(Error::WrongEndian) | Err(Error::DifferentVersion { found: _, expected: _ }) => {
Err(Error::WrongEndian)
| Err(Error::DifferentVersion {
found: _,
expected: _,
}) => {
fs::remove_dir_all(path)?;
Self::import(path, version)
}
@@ -243,7 +248,9 @@ where
return Ok(Some(Value::Ref(T::try_ref_from_bytes(slice)?)));
}
Ok(self.open_then_read_(index).map_or(None, |v| Some(Value::Owned(v))))
Ok(self
.open_then_read_(index)
.map_or(None, |v| Some(Value::Owned(v))))
}
#[inline]
@@ -289,7 +296,10 @@ where
let disk_len = I::from(Self::read_disk_len_(&file)?);
let pushed_len = I::from(self.pushed_len());
Self::seek_(&mut file, Self::index_to_byte_index(Self::i_to_usize(index)?))?;
Self::seek_(
&mut file,
Self::index_to_byte_index(Self::i_to_usize(index)?),
)?;
let mut buf = Self::create_buffer();
@@ -301,7 +311,10 @@ where
let disk_len = Self::i_to_usize(disk_len)?;
let mut i = I::default();
while i < pushed_len {
f((i + disk_len, self.pushed.get(Self::i_to_usize(i)?).as_ref().unwrap()))?;
f((
i + disk_len,
self.pushed.get(Self::i_to_usize(i)?).as_ref().unwrap(),
))?;
i = i + 1;
}
@@ -525,7 +538,12 @@ where
}
pub fn file_name(&self) -> String {
self.path().file_name().unwrap().to_str().unwrap().to_owned()
self.path()
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_owned()
}
#[inline]
@@ -567,10 +585,14 @@ where
A: StoredType,
F: Fn(&A, I) -> T,
{
self.validate_computed_version_or_reset_file(Version::from(0) + self.version + other.version)?;
self.validate_computed_version_or_reset_file(
Version::from(0) + self.version + other.version,
)?;
let index = max_from.min(I::from(self.len()));
other.iter_from(index, |(i, a)| self.push_and_flush_if_needed(i, t(a, i), exit))?;
other.iter_from(index, |(i, a)| {
self.push_and_flush_if_needed(i, t(a, i), exit)
})?;
Ok(self.safe_flush(exit)?)
}
@@ -585,7 +607,9 @@ where
I: StoredType + StoredIndex,
T: StoredIndex,
{
self.validate_computed_version_or_reset_file(Version::from(0) + self.version + other.version)?;
self.validate_computed_version_or_reset_file(
Version::from(0) + self.version + other.version,
)?;
let index = max_from.min(self.read_last()?.cloned().unwrap_or_default());
other.iter_from(index, |(v, i)| self.push_and_flush_if_needed(*i, v, exit))?;
@@ -612,7 +636,8 @@ where
first_indexes.iter_from(index, |(value, first_index)| {
let first_index = Self::i_to_usize(*first_index)?;
let last_index = Self::i_to_usize(*last_indexes.read(value)?.unwrap())?;
(first_index..last_index).try_for_each(|index| self.push_and_flush_if_needed(I::from(index), value, exit))
(first_index..last_index)
.try_for_each(|index| self.push_and_flush_if_needed(I::from(index), value, exit))
})?;
Ok(self.safe_flush(exit)?)
@@ -628,7 +653,9 @@ where
where
T: Copy + From<usize> + Sub<T, Output = T> + StoredIndex,
{
self.validate_computed_version_or_reset_file(Version::from(0) + self.version + first_indexes.version)?;
self.validate_computed_version_or_reset_file(
Version::from(0) + self.version + first_indexes.version,
)?;
let index = max_from.min(I::from(self.len()));
let one = T::from(1);
@@ -691,7 +718,11 @@ where
let index = max_from.min(I::from(self.len()));
self_to_other.iter_from(index, |(i, other)| {
self.push_and_flush_if_needed(i, T::from(other_to_self.read(*other)?.unwrap() == &i), exit)
self.push_and_flush_if_needed(
i,
T::from(other_to_self.read(*other)?.unwrap() == &i),
exit,
)
})?;
Ok(self.safe_flush(exit)?)