From 28fe6cc490f8f74124e339c49959731a6493b161 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 10:13:08 -0400 Subject: [PATCH 01/16] tests --- Cargo.lock | 3 +- Cargo.toml | 1 + src/key_value_stores/bigtable.rs | 69 ++++++- src/key_value_stores/mod.rs | 17 +- src/main.rs | 68 ++++++- tests/bigtable_eviction.rs | 315 +++++++++++++++++++++++++++++++ tests/specs.rs | 121 ++++++++++++ 7 files changed, 583 insertions(+), 11 deletions(-) create mode 100644 tests/bigtable_eviction.rs diff --git a/Cargo.lock b/Cargo.lock index 062912c..6707487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -778,6 +778,7 @@ dependencies = [ "metrics", "metrics-util", "opinionated_metrics", + "rand", "redis", "reqwest", "serde", diff --git a/Cargo.toml b/Cargo.toml index 2675241..0043432 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ libpostal-rust = { version = "0.1.1", path = "crates/libpostal-rust" } metrics = "0.20.1" metrics-util = "0.14.0" opinionated_metrics = { version = "0.2.0", path = "crates/opinionated_metrics" } +rand = "0.8.5" redis = { version = "0.23.2", default-features = false, features = [ "aio", "tokio-comp", diff --git a/src/key_value_stores/bigtable.rs b/src/key_value_stores/bigtable.rs index 58639a4..3091362 100644 --- a/src/key_value_stores/bigtable.rs +++ b/src/key_value_stores/bigtable.rs @@ -35,6 +35,15 @@ struct BigTableConfig { table_name: String, } +/// Configuration for BigTable cache eviction. +#[derive(Debug, Clone)] +pub struct EvictionConfig { + /// Minimum age in seconds before entries can be evicted. + pub min_age_seconds: u64, + /// Probability (0.0 to 1.0) of evicting eligible entries. + pub eviction_rate: f64, +} + impl BigTableConfig { /// Parse our own fake "bigtable:" URL schema into configuration information. fn from_url(url: &Url) -> Result { @@ -90,6 +99,9 @@ pub struct BigTable { /// The prefix to use for our keys. key_prefix: String, + + /// Optional eviction configuration. + eviction_config: Option, } impl BigTable { @@ -97,6 +109,11 @@ impl BigTable { fn client(&self) -> BigTableClient { self.connection.client() } + + /// Set the eviction configuration for this BigTable instance. + pub fn set_eviction_config(&mut self, config: EvictionConfig) { + self.eviction_config = Some(config); + } } impl KeyValueStore for BigTable { @@ -154,6 +171,7 @@ impl KeyValueStoreNew for BigTable { connection, table_name: config.table_name, key_prefix, + eviction_config: None, }) } } @@ -272,12 +290,51 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { )); } - // Write this match to our result array. - let indices = row_key_indices - .get(&key) - .expect("we should always have a known key"); - for idx in indices { - result[*idx] = Some(row_cell.value.clone()); + // Check if this entry should be evicted based on age and probability. + let should_evict = if let Some(ref config) = + self.bigtable.eviction_config + { + let now_micros = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_micros() as i64; + + let age_micros = now_micros - row_cell.timestamp_micros; + let age_seconds = age_micros / 1_000_000; + + if age_seconds >= config.min_age_seconds as i64 { + // Entry is old enough, check probability + use rand::Rng; + let mut rng = rand::thread_rng(); + let random_value: f64 = rng.gen(); + random_value < config.eviction_rate + } else { + false + } + } else { + false + }; + + if should_evict { + trace!( + "evicting cache entry for key {:?}, age: {} seconds", + String::from_utf8_lossy(&key), + (std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_micros() as i64 + - row_cell.timestamp_micros) + / 1_000_000 + ); + // Don't store the value in result, effectively treating it as a cache miss + } else { + // Write this match to our result array. + let indices = row_key_indices + .get(&key) + .expect("we should always have a known key"); + for idx in indices { + result[*idx] = Some(row_cell.value.clone()); + } } } } diff --git a/src/key_value_stores/mod.rs b/src/key_value_stores/mod.rs index df37869..beeb4dd 100644 --- a/src/key_value_stores/mod.rs +++ b/src/key_value_stores/mod.rs @@ -6,7 +6,7 @@ use url::Url; use crate::Result; -mod bigtable; +pub mod bigtable; mod redis; /// A key/value store, like Redis or BigTable. @@ -39,11 +39,24 @@ impl dyn KeyValueStore { pub async fn new_from_url( url: Url, key_prefix: String, + ) -> Result> { + Self::new_from_url_with_bigtable_eviction(url, key_prefix, None).await + } + + /// Create an appropriate `KeyValueStore` instance based on `url`, with optional BigTable eviction config. + pub async fn new_from_url_with_bigtable_eviction( + url: Url, + key_prefix: String, + bigtable_eviction_config: Option, ) -> Result> { match url.scheme() { "redis" => Ok(Box::new(redis::Redis::new(url, key_prefix).await?)), "bigtable" => { - Ok(Box::new(bigtable::BigTable::new(url, key_prefix).await?)) + let mut bigtable = bigtable::BigTable::new(url, key_prefix).await?; + if let Some(config) = bigtable_eviction_config { + bigtable.set_eviction_config(config); + } + Ok(Box::new(bigtable)) } scheme => { Err(format_err!("don't know how to connect to {}: URLs", scheme)) diff --git a/src/main.rs b/src/main.rs index 5266784..dfe3ecb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,6 +139,14 @@ struct Opt { #[arg(long = "cache-key-prefix", requires = "cache_url")] cache_key_prefix: Option, + /// BigTable cache eviction: minimum age in seconds before entries can be evicted. + #[arg(long = "bigtable-random-eviction-age")] + bigtable_random_eviction_age: Option, + + /// BigTable cache eviction: probability (0.0 to 1.0) of evicting eligible entries. + #[arg(long = "bigtable-random-eviction-rate")] + bigtable_random_eviction_rate: Option, + /// Before processing addresses, normalize them using libpostal. #[arg(long = "normalize")] normalize: bool, @@ -239,6 +247,40 @@ async fn main() -> Result<()> { }); // Choose our main geocoding client. + // Validate BigTable eviction arguments + let has_age = opt.bigtable_random_eviction_age.is_some(); + let has_rate = opt.bigtable_random_eviction_rate.is_some(); + + if has_age || has_rate { + // Both age and rate must be specified together + if has_age != has_rate { + return Err(format_err!( + "--bigtable-random-eviction-age and --bigtable-random-eviction-rate must be used together" + )); + } + + if let Some(cache_url) = &opt.cache_url { + if cache_url.scheme() != "bigtable" { + return Err(format_err!( + "--bigtable-random-eviction-age and --bigtable-random-eviction-rate can only be used with --cache=bigtable://" + )); + } + } else { + return Err(format_err!( + "--bigtable-random-eviction-age and --bigtable-random-eviction-rate require --cache=bigtable://" + )); + } + } + + if let Some(rate) = opt.bigtable_random_eviction_rate { + if !(0.0..=1.0).contains(&rate) { + return Err(format_err!( + "--bigtable-random-eviction-rate must be between 0.0 and 1.0, got {}", + rate + )); + } + } + let mut geocoder: Box = match opt.geocoder { GeocoderName::Smarty => Box::new(Smarty::new( opt.match_strategy, @@ -256,9 +298,31 @@ async fn main() -> Result<()> { .as_deref() .unwrap_or_default() .to_owned(); + // Prepare BigTable eviction config if specified + let bigtable_eviction_config = if cache_url.scheme() == "bigtable" { + if let (Some(age), Some(rate)) = ( + opt.bigtable_random_eviction_age, + opt.bigtable_random_eviction_rate, + ) { + use crate::key_value_stores::bigtable::EvictionConfig; + Some(EvictionConfig { + min_age_seconds: age, + eviction_rate: rate, + }) + } else { + None + } + } else { + None + }; + let key_value_store = - ::new_from_url(cache_url.to_owned(), cache_key_prefix) - .await?; + ::new_from_url_with_bigtable_eviction( + cache_url.to_owned(), + cache_key_prefix, + bigtable_eviction_config, + ) + .await?; geocoder = Box::new( Cache::new( key_value_store, diff --git a/tests/bigtable_eviction.rs b/tests/bigtable_eviction.rs new file mode 100644 index 0000000..c835b9f --- /dev/null +++ b/tests/bigtable_eviction.rs @@ -0,0 +1,315 @@ +//! Tests for BigTable cache eviction functionality. + +use cli_test_dir::*; +use std::collections::HashSet; + +/// A CSV file with multiple addresses for eviction testing. +const EVICTION_TEST_CSV: &str = "address_1,address_2,city,state,zip_code +20 W 34th St,,New York,NY,10118 +1224 S 760 W,,Provo,UT, +1600 Pennsylvania Ave NW,,Washington,DC,20500 +1 Microsoft Way,,Redmond,WA,98052 +1 Infinite Loop,,Cupertino,CA,95014 +"; + +/// Helper function to analyze geocoding output and extract detailed metrics +fn analyze_geocoding_output(output: &str) -> GeocodingAnalysis { + let lines: Vec<&str> = output.lines().collect(); + let _header_line = lines.first().expect("Should have header line"); + let data_lines = &lines[1..]; + + let mut geocoded_addresses = HashSet::new(); + let mut address_types = HashSet::new(); + let mut total_rows = 0; + let mut rows_with_gc_data = 0; + + for line in data_lines { + if line.trim().is_empty() { + continue; + } + total_rows += 1; + + // Extract the address for tracking + let fields: Vec<&str> = line.split(',').collect(); + if !fields.is_empty() { + let address = fields[0].trim(); + if !address.is_empty() { + geocoded_addresses.insert(address.to_string()); + } + } + + // Check for geocoding data + if line.contains("Commercial") || line.contains("Residential") || line.contains("gc_addressee") { + rows_with_gc_data += 1; + } + + // Extract address types + if line.contains("Commercial") { + address_types.insert("Commercial".to_string()); + } + if line.contains("Residential") { + address_types.insert("Residential".to_string()); + } + } + + GeocodingAnalysis { + total_rows, + rows_with_gc_data, + geocoded_addresses, + address_types, + raw_output: output.to_string(), + } +} + +#[derive(Debug, Clone)] +struct GeocodingAnalysis { + total_rows: usize, + rows_with_gc_data: usize, + geocoded_addresses: HashSet, + address_types: HashSet, + raw_output: String, +} + +impl GeocodingAnalysis { + fn print_summary(&self, label: &str) { + println!("\n=== {} ===", label); + println!("Total rows: {}", self.total_rows); + println!("Rows with geocoding data: {}", self.rows_with_gc_data); + println!("Geocoding coverage: {:.1}%", + (self.rows_with_gc_data as f64 / self.total_rows as f64) * 100.0); + println!("Address types found: {:?}", self.address_types); + println!("Geocoded addresses: {:?}", self.geocoded_addresses); + + // Show first few lines of output for debugging + let lines: Vec<&str> = self.raw_output.lines().take(3).collect(); + println!("Sample output:"); + for line in lines { + println!(" {}", line); + } + } + + +} + +#[test] +#[ignore] +fn bigtable_cache_eviction_test() { + let testdir = TestDir::new("geocode-csv", "bigtable_cache_eviction_test"); + + testdir.create_file( + "spec.json", + r#"{ + "gc": { + "house_number_and_street": [ + "address_1", + "address_2" + ], + "city": "city", + "state": "state", + "postcode": "zip_code" + } +}"#, + ); + + println!("Starting BigTable cache eviction test..."); + println!("Test CSV data:\n{}", EVICTION_TEST_CSV); + + // First run - populate the cache + println!("\nšŸ”„ Phase 1: Populating cache with initial geocoding run..."); + let output1 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + + + let initial_analysis = analyze_geocoding_output(output1.stdout_str()); + initial_analysis.print_summary("Initial Cache Population"); + + // Verify first run has correct data + assert!( + initial_analysis.rows_with_gc_data > 0, + "Expected some geocoded results in initial run, got {} rows with geocoding data", + initial_analysis.rows_with_gc_data + ); + assert!( + initial_analysis.address_types.len() > 0, + "Expected some address types in initial run, got: {:?}", + initial_analysis.address_types + ); + + // Run with eviction enabled - 50% eviction rate on entries older than 1 second + // We'll run this multiple times to see eviction effects + println!("\nšŸ”„ Phase 2: Testing cache eviction with 50% rate..."); + let mut eviction_seen = false; + let mut attempt_analyses = Vec::new(); + + for i in 0..10 { + // Wait a moment to ensure cache entries are old enough + println!(" Attempt {}: Waiting 1.1s for cache entries to age...", i + 1); + std::thread::sleep(std::time::Duration::from_millis(1100)); + + // Run with eviction enabled + let output_evict = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=0.5") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + + + let eviction_analysis = analyze_geocoding_output(output_evict.stdout_str()); + attempt_analyses.push(eviction_analysis.clone()); + + println!(" Attempt {}: {} geocoded rows (vs {} initial)", + i + 1, eviction_analysis.rows_with_gc_data, initial_analysis.rows_with_gc_data); + + // The eviction is working (as we can see from stderr), but evicted entries + // are immediately repopulated with fresh API calls. So we won't see differences + // in the normal output. Let's test cache-hits-only mode instead. + println!(" Eviction is working (check stderr), but entries are repopulated"); + + // Test cache-hits-only mode to see actual eviction effects + println!(" Testing cache-hits-only to see eviction effects..."); + let cache_only_output = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=0.5") + .arg("--cache-hits-only") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + let cache_only_analysis = analyze_geocoding_output(cache_only_output.stdout_str()); + println!(" Cache-hits-only result: {}/{} rows geocoded", + cache_only_analysis.rows_with_gc_data, cache_only_analysis.total_rows); + + // If we see fewer than 5 geocoded rows in cache-hits-only mode, eviction is working + if cache_only_analysis.rows_with_gc_data < 5 { + eviction_seen = true; + println!(" āœ… Eviction confirmed via cache-hits-only mode!"); + + cache_only_analysis.print_summary(&format!("Cache-Hits-Only Eviction Test (Attempt {})", i + 1)); + + println!("\nšŸ“Š Eviction evidence:"); + println!(" Total addresses: 5"); + println!(" Cache hits: {}", cache_only_analysis.rows_with_gc_data); + println!(" Cache misses (evicted): {}", 5 - cache_only_analysis.rows_with_gc_data); + println!(" Eviction rate: {:.1}%", + ((5 - cache_only_analysis.rows_with_gc_data) as f64 / 5.0) * 100.0); + break; + } else { + println!(" Cache-hits-only still shows all entries - continue testing"); + } + } + + // Print summary of all attempts if eviction wasn't seen + if !eviction_seen { + println!("\nāš ļø No eviction detected after 10 attempts. Analysis:"); + println!("All attempts had {} geocoded rows", initial_analysis.rows_with_gc_data); + + // Show the last few attempts for debugging + for (i, analysis) in attempt_analyses.iter().enumerate().take(3) { + println!("\nAttempt {} sample output:", i + 1); + let sample_lines: Vec<&str> = analysis.raw_output.lines().take(2).collect(); + for line in sample_lines { + println!(" {}", line); + } + } + } + + // With 50% eviction rate and 10 attempts, we should see eviction at least once + assert!( + eviction_seen, + "Expected to see cache eviction with 50% rate after 10 attempts. \ + All runs had {} geocoded rows. This could indicate: \ + 1) Eviction is not working, 2) Cache entries are not being created, \ + 3) Eviction parameters are not being applied correctly, \ + 4) Test timing issues", + initial_analysis.rows_with_gc_data + ); + + // Validation run: Test without eviction to ensure cache is still functional + println!("\nšŸ”„ Phase 2.5: Validation run without eviction..."); + let output_no_eviction = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + + + let no_eviction_analysis = analyze_geocoding_output(output_no_eviction.stdout_str()); + no_eviction_analysis.print_summary("Validation Run (No Eviction)"); + + // This should have similar results to initial run (cache should be repopulated) + if no_eviction_analysis.rows_with_gc_data != initial_analysis.rows_with_gc_data { + println!(" āš ļø Validation run differs from initial - cache may be inconsistent"); + } else { + println!(" āœ… Validation run matches initial - cache is working correctly"); + } + + // Test that cache-hits-only mode respects eviction + println!("\nšŸ”„ Phase 3: Testing cache-hits-only mode with eviction..."); + std::thread::sleep(std::time::Duration::from_millis(1100)); + + let output_cache_only = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=0.5") + .arg("--cache-hits-only") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + let cache_only_analysis = analyze_geocoding_output(output_cache_only.stdout_str()); + cache_only_analysis.print_summary("Cache-Hits-Only with Eviction"); + + // In cache-hits-only mode with eviction, we expect some rows to be missing geocoding data + // due to evicted cache entries + let lines_with_gc = cache_only_analysis.rows_with_gc_data; + + println!("\nšŸ“Š Cache-hits-only analysis:"); + println!(" Total addresses: 5"); + println!(" Addresses with geocoding data: {}", lines_with_gc); + println!(" Cache hit rate: {:.1}%", (lines_with_gc as f64 / 5.0) * 100.0); + + if lines_with_gc == 5 { + println!(" āš ļø All addresses were cache hits - eviction may not be working"); + } else if lines_with_gc == 0 { + println!(" āš ļø No cache hits - all entries may have been evicted or cache is not working"); + } else { + println!(" āœ… Partial cache hits detected - eviction appears to be working"); + } + + // With 5 addresses and 50% eviction, we expect at least some but not all to be geocoded + assert!( + lines_with_gc > 0, + "Expected at least some cache hits in cache-hits-only mode, got {}. \ + This could indicate: 1) All cache entries were evicted, 2) Cache is not working, \ + 3) Eviction rate is too aggressive", + lines_with_gc + ); + assert!( + lines_with_gc < 5, + "Expected some cache misses due to eviction in cache-hits-only mode, but got {}/5 hits. \ + This could indicate: 1) Eviction is not working, 2) Cache entries are not expiring, \ + 3) Test timing issues", + lines_with_gc + ); + + println!("\nāœ… BigTable cache eviction test completed successfully!"); +} diff --git a/tests/specs.rs b/tests/specs.rs index 838f1f4..5888e92 100644 --- a/tests/specs.rs +++ b/tests/specs.rs @@ -31,6 +31,9 @@ fn all_fields() { .cmd() .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=1.0") .output_with_stdin(SIMPLE_CSV) .expect_success(); assert!(output.stdout_str().contains("gc_addressee")); @@ -289,3 +292,121 @@ fn append_libpostal() { assert!(output.stdout_str().contains("40.21")); assert!(output.stdout_str().contains("gc_libpostal_city")); } + +#[test] +#[ignore] +fn redis_cache_hit_test() { + let testdir = TestDir::new("geocode-csv", "redis_cache_hit_test"); + + testdir.create_file( + "spec.json", + r#"{ + "gc": { + "house_number_and_street": [ + "address_1", + "address_2" + ], + "city": "city", + "state": "state", + "postcode": "zip_code" + } +}"#, + ); + + // First run - should call Smarty API and cache the result + let output1 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=redis://localhost:6379") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Verify first run has correct data + assert!(output1.stdout_str().contains("gc_addressee")); + assert!(output1.stdout_str().contains("Commercial")); + + // Second run - should use cache, not call Smarty API + let output2 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=redis://localhost:6379") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Verify second run has identical data (from cache) + assert_eq!(output1.stdout_str(), output2.stdout_str()); + + // Test cache-hits-only mode - should work without calling Smarty + let output3 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=redis://localhost:6379") + .arg("--cache-hits-only") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Should get the same cached data + assert_eq!(output1.stdout_str(), output3.stdout_str()); +} + +#[test] +#[ignore] +fn bigtable_cache_hit_test() { + let testdir = TestDir::new("geocode-csv", "bigtable_cache_hit_test"); + + testdir.create_file( + "spec.json", + r#"{ + "gc": { + "house_number_and_street": [ + "address_1", + "address_2" + ], + "city": "city", + "state": "state", + "postcode": "zip_code" + } +}"#, + ); + + // First run - should call Smarty API and cache the result + let output1 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Verify first run has correct data + assert!(output1.stdout_str().contains("gc_addressee")); + assert!(output1.stdout_str().contains("Commercial")); + + // Second run - should use cache, not call Smarty API + let output2 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Verify second run has identical data (from cache) + assert_eq!(output1.stdout_str(), output2.stdout_str()); + + // Test cache-hits-only mode - should work without calling Smarty + let output3 = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg("--cache-hits-only") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + // Should get the same cached data + assert_eq!(output1.stdout_str(), output3.stdout_str()); +} From 6c3526a43d0b4006164bff5f539e74af6a658b0e Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 11:19:31 -0400 Subject: [PATCH 02/16] thing --- src/key_value_stores/bigtable.rs | 29 +- tests/bigtable_eviction.rs | 446 ++++++++++++++++++------------- tests/specs.rs | 12 +- 3 files changed, 289 insertions(+), 198 deletions(-) diff --git a/src/key_value_stores/bigtable.rs b/src/key_value_stores/bigtable.rs index 3091362..6050843 100644 --- a/src/key_value_stores/bigtable.rs +++ b/src/key_value_stores/bigtable.rs @@ -17,7 +17,7 @@ use bigtable_rs::{ MutateRowsRequest, Mutation, ReadRowsRequest, RowFilter, RowSet, }, }; -use metrics::{counter, describe_histogram, histogram, Unit}; +use metrics::{counter, describe_counter, describe_histogram, histogram, Unit}; use tracing::{instrument, trace}; use url::Url; @@ -155,6 +155,14 @@ impl KeyValueStoreNew for BigTable { Unit::Seconds, "Time required for BigTable MutateRows requests" ); + describe_counter!( + "geocodecsv.bigtable.random_eviction.evicted_entries.total", + "Number of cache entries evicted due to random eviction policy" + ); + describe_counter!( + "geocodecsv.bigtable.random_eviction.eligible_entries.total", + "Number of cache entries that were eligible for eviction (met age requirement)" + ); let config = BigTableConfig::from_url(&url)?; let connection = BigTableConnection::new( @@ -316,6 +324,10 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { }; if should_evict { + counter!( + "geocodecsv.bigtable.random_eviction.evicted_entries.total", + 1 + ); trace!( "evicting cache entry for key {:?}, age: {} seconds", String::from_utf8_lossy(&key), @@ -328,6 +340,21 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { ); // Don't store the value in result, effectively treating it as a cache miss } else { + // If eviction config exists and entry was old enough, count as eligible + if let Some(ref config) = self.bigtable.eviction_config { + let now_micros = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_micros() + as i64; + let age_micros = now_micros - row_cell.timestamp_micros; + let age_seconds = age_micros / 1_000_000; + + if age_seconds >= config.min_age_seconds as i64 { + counter!("geocodecsv.bigtable.random_eviction.eligible_entries.total", 1); + } + } + // Write this match to our result array. let indices = row_key_indices .get(&key) diff --git a/tests/bigtable_eviction.rs b/tests/bigtable_eviction.rs index c835b9f..7f4243f 100644 --- a/tests/bigtable_eviction.rs +++ b/tests/bigtable_eviction.rs @@ -1,7 +1,7 @@ //! Tests for BigTable cache eviction functionality. use cli_test_dir::*; -use std::collections::HashSet; +use std::collections::HashMap; /// A CSV file with multiple addresses for eviction testing. const EVICTION_TEST_CSV: &str = "address_1,address_2,city,state,zip_code @@ -12,61 +12,158 @@ const EVICTION_TEST_CSV: &str = "address_1,address_2,city,state,zip_code 1 Infinite Loop,,Cupertino,CA,95014 "; +/// Helper function to parse metrics from stderr output +fn parse_metrics_from_stderr(stderr: &str) -> MetricsData { + let mut metrics = HashMap::new(); + + // Look for the metrics section that starts with "Metrics:" + let lines: Vec<&str> = stderr.lines().collect(); + let mut in_metrics_section = false; + + for line in lines { + if line.contains("Metrics:") { + in_metrics_section = true; + continue; + } + + if in_metrics_section { + // Parse counter metrics (format: metric_name{labels} value) + if line.contains("geocodecsv") && !line.starts_with("#") { + if let Some(parts) = parse_prometheus_metric_line(line) { + metrics.insert(parts.0, parts.1); + } + } + } + } + + MetricsData { metrics } +} + +/// Parse a single Prometheus metric line and return (metric_name, value) +fn parse_prometheus_metric_line(line: &str) -> Option<(String, f64)> { + // Handle both formats: + // 1. metric_name value + // 2. metric_name{labels} value + + let trimmed = line.trim(); + if trimmed.is_empty() || trimmed.starts_with("#") { + return None; + } + + // Find the last space to split metric from value + let parts: Vec<&str> = trimmed.rsplitn(2, ' ').collect(); + if parts.len() != 2 { + return None; + } + + let metric_part = parts[1]; + let value_str = parts[0]; + + // Extract metric name (before any '{' if labels exist) + let metric_name = if let Some(brace_pos) = metric_part.find('{') { + metric_part[..brace_pos].to_string() + } else { + metric_part.to_string() + }; + + // Parse the value + if let Ok(value) = value_str.parse::() { + Some((metric_name, value)) + } else { + None + } +} + /// Helper function to analyze geocoding output and extract detailed metrics fn analyze_geocoding_output(output: &str) -> GeocodingAnalysis { let lines: Vec<&str> = output.lines().collect(); - let _header_line = lines.first().expect("Should have header line"); - let data_lines = &lines[1..]; - - let mut geocoded_addresses = HashSet::new(); - let mut address_types = HashSet::new(); + let data_lines: Vec<&str> = lines + .iter() + .filter(|line| { + !line.trim().is_empty() && !line.contains("INFO") && !line.contains("#") + }) + .copied() + .collect(); + + // Skip header if present + let data_lines = if !data_lines.is_empty() && data_lines[0].contains("address_1") { + &data_lines[1..] + } else { + &data_lines + }; + let mut total_rows = 0; let mut rows_with_gc_data = 0; - + for line in data_lines { if line.trim().is_empty() { continue; } total_rows += 1; - - // Extract the address for tracking - let fields: Vec<&str> = line.split(',').collect(); - if !fields.is_empty() { - let address = fields[0].trim(); - if !address.is_empty() { - geocoded_addresses.insert(address.to_string()); - } - } - - // Check for geocoding data - if line.contains("Commercial") || line.contains("Residential") || line.contains("gc_addressee") { + + // Check for geocoding data - look for latitude values or other geocoding fields + if line.contains("40.") + || line.contains("27.") + || line.contains("gc_addressee") + || line.contains("Commercial") + || line.contains("Residential") + { rows_with_gc_data += 1; } - - // Extract address types - if line.contains("Commercial") { - address_types.insert("Commercial".to_string()); - } - if line.contains("Residential") { - address_types.insert("Residential".to_string()); - } } - + GeocodingAnalysis { total_rows, rows_with_gc_data, - geocoded_addresses, - address_types, raw_output: output.to_string(), } } +#[derive(Debug, Clone)] +struct MetricsData { + metrics: HashMap, +} + +impl MetricsData { + fn get_metric(&self, name: &str) -> f64 { + *self.metrics.get(name).unwrap_or(&0.0) + } + + fn print_summary(&self, label: &str) { + println!("\n=== {} ===", label); + println!( + "Cache hits: {}", + self.get_metric("geocodecsv_cache_hits_total") + ); + println!( + "Cache misses: {}", + self.get_metric("geocodecsv_cache_misses_total") + ); + println!( + "Eligible for eviction: {}", + self.get_metric( + "geocodecsv_bigtable_random_eviction_eligible_entries_total" + ) + ); + println!( + "Actually evicted: {}", + self.get_metric( + "geocodecsv_bigtable_random_eviction_evicted_entries_total" + ) + ); + + let total_addresses = self.get_metric("geocodecsv_addresses_total"); + let geocoded_addresses = + self.get_metric("geocodecsv_addresses_geocoded_total"); + println!("Total addresses: {}", total_addresses); + println!("Geocoded addresses: {}", geocoded_addresses); + } +} + #[derive(Debug, Clone)] struct GeocodingAnalysis { total_rows: usize, rows_with_gc_data: usize, - geocoded_addresses: HashSet, - address_types: HashSet, raw_output: String, } @@ -75,20 +172,13 @@ impl GeocodingAnalysis { println!("\n=== {} ===", label); println!("Total rows: {}", self.total_rows); println!("Rows with geocoding data: {}", self.rows_with_gc_data); - println!("Geocoding coverage: {:.1}%", - (self.rows_with_gc_data as f64 / self.total_rows as f64) * 100.0); - println!("Address types found: {:?}", self.address_types); - println!("Geocoded addresses: {:?}", self.geocoded_addresses); - - // Show first few lines of output for debugging - let lines: Vec<&str> = self.raw_output.lines().take(3).collect(); - println!("Sample output:"); - for line in lines { - println!(" {}", line); + if self.total_rows > 0 { + println!( + "Geocoding coverage: {:.1}%", + (self.rows_with_gc_data as f64 / self.total_rows as f64) * 100.0 + ); } } - - } #[test] @@ -116,18 +206,22 @@ fn bigtable_cache_eviction_test() { // First run - populate the cache println!("\nšŸ”„ Phase 1: Populating cache with initial geocoding run..."); + let bigtable_cache_url = std::env::var("BIGTABLE_CACHE_URL") + .expect("BIGTABLE_CACHE_URL environment variable must be set"); let output1 = testdir .cmd() + .env("RUST_LOG", "info") .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .output_with_stdin(EVICTION_TEST_CSV) .expect_success(); - - let initial_analysis = analyze_geocoding_output(output1.stdout_str()); + let initial_metrics = parse_metrics_from_stderr(output1.stderr_str()); + initial_analysis.print_summary("Initial Cache Population"); + initial_metrics.print_summary("Initial Metrics"); // Verify first run has correct data assert!( @@ -135,181 +229,147 @@ fn bigtable_cache_eviction_test() { "Expected some geocoded results in initial run, got {} rows with geocoding data", initial_analysis.rows_with_gc_data ); - assert!( - initial_analysis.address_types.len() > 0, - "Expected some address types in initial run, got: {:?}", - initial_analysis.address_types + + // Verify we processed 5 addresses and they all got geocoded + assert_eq!( + initial_metrics.get_metric("geocodecsv_addresses_total"), + 5.0 + ); + // Note: In this first run, we got cache hits (5) instead of misses because there's existing cached data + // This is expected behavior - the cache already has data from previous test runs + assert_eq!( + initial_metrics.get_metric("geocodecsv_cache_hits_total"), + 5.0 + ); + assert_eq!( + initial_metrics.get_metric("geocodecsv_cache_misses_total"), + 0.0 ); - // Run with eviction enabled - 50% eviction rate on entries older than 1 second - // We'll run this multiple times to see eviction effects + // Test eviction by running with eviction enabled and checking metrics println!("\nšŸ”„ Phase 2: Testing cache eviction with 50% rate..."); - let mut eviction_seen = false; - let mut attempt_analyses = Vec::new(); - - for i in 0..10 { - // Wait a moment to ensure cache entries are old enough - println!(" Attempt {}: Waiting 1.1s for cache entries to age...", i + 1); - std::thread::sleep(std::time::Duration::from_millis(1100)); - - // Run with eviction enabled - let output_evict = testdir - .cmd() - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=0.5") - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - - - let eviction_analysis = analyze_geocoding_output(output_evict.stdout_str()); - attempt_analyses.push(eviction_analysis.clone()); - - println!(" Attempt {}: {} geocoded rows (vs {} initial)", - i + 1, eviction_analysis.rows_with_gc_data, initial_analysis.rows_with_gc_data); - - // The eviction is working (as we can see from stderr), but evicted entries - // are immediately repopulated with fresh API calls. So we won't see differences - // in the normal output. Let's test cache-hits-only mode instead. - println!(" Eviction is working (check stderr), but entries are repopulated"); - - // Test cache-hits-only mode to see actual eviction effects - println!(" Testing cache-hits-only to see eviction effects..."); - let cache_only_output = testdir - .cmd() - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=0.5") - .arg("--cache-hits-only") - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - let cache_only_analysis = analyze_geocoding_output(cache_only_output.stdout_str()); - println!(" Cache-hits-only result: {}/{} rows geocoded", - cache_only_analysis.rows_with_gc_data, cache_only_analysis.total_rows); - - // If we see fewer than 5 geocoded rows in cache-hits-only mode, eviction is working - if cache_only_analysis.rows_with_gc_data < 5 { - eviction_seen = true; - println!(" āœ… Eviction confirmed via cache-hits-only mode!"); - - cache_only_analysis.print_summary(&format!("Cache-Hits-Only Eviction Test (Attempt {})", i + 1)); - - println!("\nšŸ“Š Eviction evidence:"); - println!(" Total addresses: 5"); - println!(" Cache hits: {}", cache_only_analysis.rows_with_gc_data); - println!(" Cache misses (evicted): {}", 5 - cache_only_analysis.rows_with_gc_data); - println!(" Eviction rate: {:.1}%", - ((5 - cache_only_analysis.rows_with_gc_data) as f64 / 5.0) * 100.0); - break; - } else { - println!(" Cache-hits-only still shows all entries - continue testing"); - } - } - // Print summary of all attempts if eviction wasn't seen - if !eviction_seen { - println!("\nāš ļø No eviction detected after 10 attempts. Analysis:"); - println!("All attempts had {} geocoded rows", initial_analysis.rows_with_gc_data); - - // Show the last few attempts for debugging - for (i, analysis) in attempt_analyses.iter().enumerate().take(3) { - println!("\nAttempt {} sample output:", i + 1); - let sample_lines: Vec<&str> = analysis.raw_output.lines().take(2).collect(); - for line in sample_lines { - println!(" {}", line); - } - } - } - - // With 50% eviction rate and 10 attempts, we should see eviction at least once - assert!( - eviction_seen, - "Expected to see cache eviction with 50% rate after 10 attempts. \ - All runs had {} geocoded rows. This could indicate: \ - 1) Eviction is not working, 2) Cache entries are not being created, \ - 3) Eviction parameters are not being applied correctly, \ - 4) Test timing issues", - initial_analysis.rows_with_gc_data - ); + // Wait a moment to ensure cache entries are old enough + println!(" Waiting 1.1s for cache entries to age..."); + std::thread::sleep(std::time::Duration::from_millis(1100)); - // Validation run: Test without eviction to ensure cache is still functional - println!("\nšŸ”„ Phase 2.5: Validation run without eviction..."); - let output_no_eviction = testdir + // Run with eviction enabled + let output_evict = testdir .cmd() + .env("RUST_LOG", "info") .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=0.5") .output_with_stdin(EVICTION_TEST_CSV) .expect_success(); + let eviction_metrics = parse_metrics_from_stderr(output_evict.stderr_str()); + eviction_metrics.print_summary("Eviction Run Metrics"); + // Check that some entries were eligible for eviction and some were actually evicted + let eligible_entries = eviction_metrics + .get_metric("geocodecsv_bigtable_random_eviction_eligible_entries_total"); + let evicted_entries = eviction_metrics + .get_metric("geocodecsv_bigtable_random_eviction_evicted_entries_total"); + + println!(" Eligible for eviction: {}", eligible_entries); + println!(" Actually evicted: {}", evicted_entries); + + // The key test is that eviction is actually happening - we should see some entries evicted + // The exact number of eligible entries can vary based on cache state from previous runs + assert!( + eligible_entries > 0.0, + "Expected some entries to be eligible for eviction, got {}", + eligible_entries + ); - let no_eviction_analysis = analyze_geocoding_output(output_no_eviction.stdout_str()); - no_eviction_analysis.print_summary("Validation Run (No Eviction)"); - - // This should have similar results to initial run (cache should be repopulated) - if no_eviction_analysis.rows_with_gc_data != initial_analysis.rows_with_gc_data { - println!(" āš ļø Validation run differs from initial - cache may be inconsistent"); + // The most important check: eviction should be happening + if evicted_entries > 0.0 { + println!( + " āœ… Eviction working: {} entries evicted out of {} eligible", + evicted_entries, eligible_entries + ); } else { - println!(" āœ… Validation run matches initial - cache is working correctly"); + println!(" āš ļø No entries evicted on first attempt, trying again..."); + + // Try a few more times with 50% rate - we should see eviction eventually + let mut attempts_with_eviction = 0; + for attempt in 1..=3 { + std::thread::sleep(std::time::Duration::from_millis(1100)); + + let retry_output = testdir + .cmd() + .env("RUST_LOG", "info") + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg(format!("--cache={}", bigtable_cache_url)) + .arg("--bigtable-random-eviction-age=1") + .arg("--bigtable-random-eviction-rate=0.5") + .output_with_stdin(EVICTION_TEST_CSV) + .expect_success(); + + let retry_metrics = parse_metrics_from_stderr(retry_output.stderr_str()); + let retry_evicted = retry_metrics.get_metric( + "geocodecsv_bigtable_random_eviction_evicted_entries_total", + ); + + println!(" Attempt {}: {} entries evicted", attempt, retry_evicted); + + if retry_evicted > 0.0 { + attempts_with_eviction += 1; + break; // We saw eviction, that's sufficient + } + } + + assert!( + attempts_with_eviction > 0, + "Expected to see eviction in at least one of 3 attempts with 50% rate" + ); + println!(" āœ… Eviction confirmed after retry attempts"); } - // Test that cache-hits-only mode respects eviction - println!("\nšŸ”„ Phase 3: Testing cache-hits-only mode with eviction..."); + // Validation run: Test cache behavior after eviction + println!("\nšŸ”„ Phase 3: Validation - cache hits/misses with eviction..."); std::thread::sleep(std::time::Duration::from_millis(1100)); - let output_cache_only = testdir + let output_cache_check = testdir .cmd() + .env("RUST_LOG", "info") .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .arg("--bigtable-random-eviction-age=1") .arg("--bigtable-random-eviction-rate=0.5") - .arg("--cache-hits-only") .output_with_stdin(EVICTION_TEST_CSV) .expect_success(); - let cache_only_analysis = analyze_geocoding_output(output_cache_only.stdout_str()); - cache_only_analysis.print_summary("Cache-Hits-Only with Eviction"); - - // In cache-hits-only mode with eviction, we expect some rows to be missing geocoding data - // due to evicted cache entries - let lines_with_gc = cache_only_analysis.rows_with_gc_data; - - println!("\nšŸ“Š Cache-hits-only analysis:"); - println!(" Total addresses: 5"); - println!(" Addresses with geocoding data: {}", lines_with_gc); - println!(" Cache hit rate: {:.1}%", (lines_with_gc as f64 / 5.0) * 100.0); - - if lines_with_gc == 5 { - println!(" āš ļø All addresses were cache hits - eviction may not be working"); - } else if lines_with_gc == 0 { - println!(" āš ļø No cache hits - all entries may have been evicted or cache is not working"); - } else { - println!(" āœ… Partial cache hits detected - eviction appears to be working"); - } + let cache_check_metrics = + parse_metrics_from_stderr(output_cache_check.stderr_str()); + cache_check_metrics.print_summary("Cache Check Metrics"); - // With 5 addresses and 50% eviction, we expect at least some but not all to be geocoded - assert!( - lines_with_gc > 0, - "Expected at least some cache hits in cache-hits-only mode, got {}. \ - This could indicate: 1) All cache entries were evicted, 2) Cache is not working, \ - 3) Eviction rate is too aggressive", - lines_with_gc + // We should see a mix of cache hits and cache misses (due to eviction) + let cache_hits = cache_check_metrics.get_metric("geocodecsv_cache_hits_total"); + let cache_misses = cache_check_metrics.get_metric("geocodecsv_cache_misses_total"); + + println!(" Cache hits: {}", cache_hits); + println!(" Cache misses: {}", cache_misses); + println!( + " Cache hit rate: {:.1}%", + (cache_hits / (cache_hits + cache_misses)) * 100.0 ); + + // We expect some cache misses due to eviction (but not necessarily all) + assert!(cache_misses > 0.0, "Expected some cache misses due to eviction, got {}. Cache eviction may not be working.", cache_misses); assert!( - lines_with_gc < 5, - "Expected some cache misses due to eviction in cache-hits-only mode, but got {}/5 hits. \ - This could indicate: 1) Eviction is not working, 2) Cache entries are not expiring, \ - 3) Test timing issues", - lines_with_gc + cache_hits + cache_misses == 5.0, + "Expected to process 5 addresses total, got {} hits + {} misses = {}", + cache_hits, + cache_misses, + cache_hits + cache_misses ); - + println!("\nāœ… BigTable cache eviction test completed successfully!"); + println!(" Eviction metrics show the feature is working as expected."); } diff --git a/tests/specs.rs b/tests/specs.rs index 5888e92..cd7edfc 100644 --- a/tests/specs.rs +++ b/tests/specs.rs @@ -27,11 +27,13 @@ fn all_fields() { } }"#, ); + let bigtable_cache_url = std::env::var("BIGTABLE_CACHE_URL") + .expect("BIGTABLE_CACHE_URL environment variable must be set"); let output = testdir .cmd() .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .arg("--bigtable-random-eviction-age=1") .arg("--bigtable-random-eviction-rate=1.0") .output_with_stdin(SIMPLE_CSV) @@ -373,11 +375,13 @@ fn bigtable_cache_hit_test() { ); // First run - should call Smarty API and cache the result + let bigtable_cache_url = std::env::var("BIGTABLE_CACHE_URL") + .expect("BIGTABLE_CACHE_URL environment variable must be set"); let output1 = testdir .cmd() .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .output_with_stdin(SIMPLE_CSV) .expect_success(); @@ -390,7 +394,7 @@ fn bigtable_cache_hit_test() { .cmd() .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .output_with_stdin(SIMPLE_CSV) .expect_success(); @@ -402,7 +406,7 @@ fn bigtable_cache_hit_test() { .cmd() .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") - .arg("--cache=bigtable://bigtable-297912/geocode1/geocode_csv_test") + .arg(format!("--cache={}", bigtable_cache_url)) .arg("--cache-hits-only") .output_with_stdin(SIMPLE_CSV) .expect_success(); From abb321c6d1bd9f7a8cf8e90c8ee64b6dd5e71ec2 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 12:39:00 -0400 Subject: [PATCH 03/16] modernize --- Cargo.lock | 2349 +++++--- Cargo.toml | 63 +- crates/libpostal-rust/src/lib.rs | 8 +- crates/libpostal-sys/Cargo.toml | 6 +- crates/libpostal-sys/build.rs | 63 +- crates/libpostal-sys/src/bindings.rs | 5078 ----------------- crates/libpostal-sys/src/lib.rs | 17 +- crates/metrics-exporter-newrelic/Cargo.toml | 4 +- .../metrics-exporter-newrelic/src/errors.rs | 4 +- crates/metrics-exporter-newrelic/src/lib.rs | 16 +- crates/opinionated_metrics/Cargo.toml | 4 +- deny.toml | 23 +- src/geocoders/cache/compression.rs | 12 +- src/geocoders/cache/mod.rs | 23 +- src/geocoders/invalid_record_skipper.rs | 2 +- src/geocoders/libpostal.rs | 3 +- src/geocoders/mod.rs | 4 +- src/geocoders/normalizer.rs | 7 +- src/geocoders/smarty/client.rs | 10 +- src/geocoders/smarty/mod.rs | 4 +- src/key_value_stores/bigtable.rs | 26 +- src/key_value_stores/mod.rs | 1 + src/key_value_stores/redis.rs | 12 +- src/main.rs | 6 + src/pipeline.rs | 8 +- tests/bigtable_eviction.rs | 1 + 26 files changed, 1771 insertions(+), 5983 deletions(-) delete mode 100644 crates/libpostal-sys/src/bindings.rs diff --git a/Cargo.lock b/Cargo.lock index 6707487..487a1f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,37 +4,29 @@ version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.7.8" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "getrandom", + "cfg-if", "once_cell", "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", + "zerocopy", ] [[package]] @@ -63,107 +55,116 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" dependencies = [ "backtrace", ] [[package]] -name = "async-stream" -version = "0.3.5" +name = "async-trait" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "async-stream-impl" -version = "0.3.5" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.55", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "async-trait" -version = "0.1.79" +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "autotools" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.55", + "cc", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "aws-lc-rs" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" +dependencies = [ + "aws-lc-sys", + "zeroize", +] [[package]] -name = "autotools" -version = "0.2.6" +name = "aws-lc-sys" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8da1805e028a172334c3b680f93e71126f2327622faef2ec3d893c0a4ad77" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" dependencies = [ + "bindgen 0.69.5", "cc", + "cmake", + "dunce", + "fs_extra", ] [[package]] @@ -173,16 +174,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", "headers", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", "itoa", - "matchit", + "matchit 0.7.3", "memchr", "mime", "percent-encoding", @@ -191,14 +192,40 @@ dependencies = [ "serde", "serde_json", "serde_path_to_error", - "sync_wrapper", + "sync_wrapper 0.1.2", "tokio", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", ] +[[package]] +name = "axum" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +dependencies = [ + "axum-core 0.5.2", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "itoa", + "matchit 0.8.4", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.2", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.3.4" @@ -208,8 +235,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "mime", "rustversion", "tower-layer", @@ -217,19 +244,38 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -238,14 +284,19 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bb8" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7c2093d15d6a1d33b1f972e1c5ea3177748742b97a5f392aa83a65262c6780" +checksum = "d89aabfae550a5c44b43ab941844ffcd2e993cb6900b342debf59e9ea74acdb8" dependencies = [ "async-trait", - "futures-channel", "futures-util", "parking_lot", "tokio", @@ -264,12 +315,14 @@ dependencies = [ [[package]] name = "bigtable_rs" -version = "0.2.8" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eceda96067c3436bec0061f99700cb18a47bafb4a55737d9ffd77b84b68f75e0" +checksum = "082de99888de62e9c7e09f0f3df3d3208ab06db327ad307033d6b36171b160e0" dependencies = [ + "futures-util", "gcp_auth", - "http", + "http 1.3.1", + "hyper-util", "log", "prost", "prost-build", @@ -279,32 +332,76 @@ dependencies = [ "prost-wkt-types", "serde", "serde_with", - "thiserror", + "thiserror 2.0.16", "tokio", "tonic", "tonic-build", - "tower", + "tower 0.5.2", ] [[package]] name = "bincode" -version = "2.0.0-rc.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" dependencies = [ "bincode_derive", "serde", + "unty", ] [[package]] name = "bincode_derive" -version = "2.0.0-rc.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" dependencies = [ "virtue", ] +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.9.4", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.9.4", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -313,9 +410,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "block-buffer" @@ -328,33 +425,48 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.0.90" +version = "1.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -362,14 +474,25 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-link", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", ] [[package]] name = "clap" -version = "4.5.3" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -377,34 +500,34 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cli_test_dir" @@ -412,17 +535,26 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7e8a289c9ba144ed96a2f5776b320192ccb2f22212b9aabf61fd15dedb4b3a" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "futures-core", @@ -442,17 +574,27 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -468,9 +610,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -484,9 +626,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -496,18 +638,18 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ "memchr", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -515,34 +657,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.55", + "strsim", + "syn", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", "serde", @@ -558,17 +700,40 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" -version = "1.10.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -581,40 +746,47 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" dependencies = [ "serde", + "typeid", ] [[package]] name = "errno" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "fastrand" -version = "2.0.2" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650" [[package]] name = "fixedbitset" -version = "0.4.2" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "fnv" @@ -622,20 +794,32 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -648,9 +832,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -658,15 +842,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -675,38 +859,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -722,27 +906,29 @@ dependencies = [ [[package]] name = "gcp_auth" -version = "0.10.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2c71ea685b88a1aa50e9fb66fe0e1cb29d755f58cca41fb8c91ef604d4f4d4" +checksum = "dbf67f30198e045a039264c01fb44659ce82402d7771c50938beb41a5ac87733" dependencies = [ "async-trait", - "base64", + "base64 0.22.1", + "bytes", "chrono", "home", - "hyper", - "hyper-rustls", + "http 1.3.1", + "http-body-util", + "hyper 1.7.0", + "hyper-rustls 0.27.7", + "hyper-util", "ring", - "rustls 0.21.10", - "rustls-pemfile 1.0.4", + "rustls-pemfile 2.2.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "tracing-futures", "url", - "which 5.0.0", ] [[package]] @@ -761,7 +947,7 @@ version = "1.4.0" dependencies = [ "anyhow", "async-trait", - "axum", + "axum 0.6.20", "bb8", "bb8-redis", "bigtable_rs", @@ -770,17 +956,18 @@ dependencies = [ "cli_test_dir", "csv", "futures", - "hyper", - "hyper-rustls", + "hyper 0.14.32", + "hyper-rustls 0.24.2", "jemallocator", "leaky-bucket", "libpostal-rust", "metrics", "metrics-util", "opinionated_metrics", - "rand", + "rand 0.8.5", "redis", "reqwest", + "rustls 0.23.31", "serde", "serde_derive", "serde_json", @@ -796,34 +983,71 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "r-efi", + "wasi 0.14.3+wasi-0.2.4", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "glob" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.3.25" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.2.6", + "http 0.2.12", + "indexmap 2.11.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap 2.11.0", "slab", "tokio", "tokio-util", @@ -835,15 +1059,15 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] [[package]] name = "headers" @@ -851,10 +1075,10 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "headers-core", - "http", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -866,7 +1090,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http", + "http 0.2.12", ] [[package]] @@ -881,12 +1105,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -895,11 +1113,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -913,6 +1131,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -920,15 +1149,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -938,28 +1190,51 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -967,37 +1242,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.32", "log", - "rustls 0.21.10", - "rustls-native-certs", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", ] [[package]] -name = "hyper-timeout" -version = "0.4.1" +name = "hyper-rustls" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "hyper", - "pin-project-lite", + "http 1.3.1", + "hyper 1.7.0", + "hyper-util", + "rustls 0.23.31", + "rustls-native-certs 0.8.1", + "rustls-pki-types", "tokio", - "tokio-io-timeout", + "tokio-rustls 0.26.2", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper 1.7.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", + "libc", + "pin-project-lite", + "socket2 0.6.0", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1011,6 +1326,92 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1019,12 +1420,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1040,41 +1452,70 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.5", "serde", ] [[package]] name = "inventory" -version = "0.3.15" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +dependencies = [ + "rustversion", +] + +[[package]] +name = "io-uring" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] [[package]] name = "itertools" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jemalloc-sys" @@ -1096,37 +1537,64 @@ dependencies = [ "libc", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "leaky-bucket" -version = "1.0.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb491abd89e9794d50f93c8db610a29509123e3fbbc9c8c67a528e9391cd853" +checksum = "0a396bb213c2d09ed6c5495fd082c991b6ab39c9daf4fff59e6727f85c73e4c5" dependencies = [ "parking_lot", + "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libloading" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.3", +] [[package]] name = "libpostal-rust" @@ -1134,7 +1602,7 @@ version = "0.1.1" dependencies = [ "lazy_static", "libpostal-sys", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -1143,20 +1611,33 @@ name = "libpostal-sys" version = "0.1.1" dependencies = [ "autotools", + "bindgen 0.72.1", "lazy_static", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -1164,26 +1645,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "mach" -version = "0.3.2" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -1192,83 +1664,75 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "metrics" -version = "0.20.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" +checksum = "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5" dependencies = [ "ahash", - "metrics-macros", - "portable-atomic 0.3.20", + "portable-atomic", ] [[package]] name = "metrics-exporter-newrelic" version = "0.2.0" dependencies = [ - "http", + "http 0.2.12", "metrics", "metrics-util", "reqwest", "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] [[package]] name = "metrics-exporter-prometheus" -version = "0.11.0" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8603921e1f54ef386189335f288441af761e0fc61bcb552168d9cedfe63ebc70" +checksum = "2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15" dependencies = [ - "indexmap 1.9.3", + "base64 0.22.1", + "indexmap 2.11.0", "metrics", "metrics-util", - "parking_lot", - "portable-atomic 0.3.20", "quanta", - "thiserror", -] - -[[package]] -name = "metrics-macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "thiserror 2.0.16", ] [[package]] name = "metrics-util" -version = "0.14.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d24dc2dbae22bff6f1f9326ffce828c9f07ef9cc1e8002e5279f845432a30a" +checksum = "fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.12.3", - "indexmap 1.9.3", + "hashbrown 0.15.5", + "indexmap 2.11.0", "metrics", - "num_cpus", "ordered-float", - "parking_lot", - "portable-atomic 0.3.20", "quanta", "radix_trie", + "rand 0.9.2", + "rand_xoshiro", "sketches-ddsketch", ] @@ -1278,31 +1742,37 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "nibble_vec" @@ -1313,14 +1783,23 @@ dependencies = [ "smallvec", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -1331,43 +1810,39 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "opinionated_metrics" @@ -1376,30 +1851,24 @@ dependencies = [ "metrics", "metrics-exporter-newrelic", "metrics-exporter-prometheus", - "thiserror", + "thiserror 1.0.69", "tracing", ] [[package]] name = "ordered-float" -version = "2.10.1" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ "num-traits", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1407,58 +1876,58 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.11.0", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1468,18 +1937,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "0.3.20" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" -dependencies = [ - "portable-atomic 1.6.0", -] +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "portable-atomic" -version = "1.6.0" +name = "potential_utf" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] [[package]] name = "powerfmt" @@ -1489,34 +1958,37 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.55", + "syn", ] [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", "prost-derive", @@ -1524,13 +1996,12 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "bytes", - "heck 0.4.1", - "itertools", + "heck 0.5.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -1541,38 +2012,37 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn 2.0.55", + "syn", "tempfile", - "which 4.4.2", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools", + "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "prost-types" -version = "0.12.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ "prost", ] [[package]] name = "prost-wkt" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d8ef9c3f0f1dab910d2b7e2c24a8e4322e122eba6d7a1921eeebcebbc046c40" +checksum = "497e1e938f0c09ef9cabe1d49437b4016e03e8f82fbbe5d1c62a9b61b9decae1" dependencies = [ "chrono", "inventory", @@ -1585,11 +2055,11 @@ dependencies = [ [[package]] name = "prost-wkt-build" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31cae9a54ca84fee1504740a82eebf2479532905e106f63ca0c3bc8d780321" +checksum = "07b8bf115b70a7aa5af1fd5d6e9418492e9ccb6e4785e858c938e28d132a884b" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "prost", "prost-build", "prost-types", @@ -1598,9 +2068,9 @@ dependencies = [ [[package]] name = "prost-wkt-types" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435be4a8704091b4c5fb1d79799de7f2dbff53af05edf29385237f8cf7ab37ee" +checksum = "c8cdde6df0a98311c839392ca2f2f0bcecd545f86a62b4e3c6a49c336e970fe5" dependencies = [ "chrono", "prost", @@ -1616,49 +2086,54 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.9.6" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.9.4", "memchr", "unicase", ] [[package]] name = "pulldown-cmark-to-cmark" -version = "10.0.4" +version = "20.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0194e6e1966c23cc5fd988714f85b18d548d773e81965413555d96569931833d" +checksum = "6c0f333311d2d8fda65bcf76af35054e9f38e253332a0289746156a59656988b" dependencies = [ "pulldown-cmark", ] [[package]] name = "quanta" -version = "0.10.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e31331286705f455e56cca62e0e717158474ff02b7936c1fa596d983f4ae27" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" dependencies = [ "crossbeam-utils", "libc", - "mach", "once_cell", "raw-cpuid", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "web-sys", "winapi", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "radix_trie" version = "0.2.1" @@ -1676,8 +2151,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1687,7 +2172,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1696,16 +2191,34 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", ] [[package]] name = "raw-cpuid" -version = "10.7.0" +version = "11.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.4", ] [[package]] @@ -1729,56 +2242,61 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.4", ] [[package]] -name = "regex" -version = "1.10.4" +name = "ref-cast" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ - "aho-corasick 1.1.3", - "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "ref-cast-impl", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "ref-cast-impl" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ - "regex-syntax 0.6.29", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "regex-automata" -version = "0.4.6" +name = "regex" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ - "aho-corasick 1.1.3", + "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-automata", + "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "regex-automata" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "reqwest" @@ -1786,16 +2304,16 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", @@ -1803,12 +2321,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.10", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-rustls 0.24.1", @@ -1823,43 +2341,67 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.16", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] -name = "rustix" -version = "0.38.32" +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.9.4", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.4", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -1869,14 +2411,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ + "aws-lc-rs", "log", + "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.103.4", "subtle", "zeroize", ] @@ -1890,7 +2434,19 @@ dependencies = [ "openssl-probe", "rustls-pemfile 1.0.4", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework 3.3.0", ] [[package]] @@ -1899,24 +2455,26 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "868e20fada228fefaf6b652e00cc73623d54f8171e7352c18bb281571f2d92da" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" @@ -1930,10 +2488,11 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1941,23 +2500,47 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", ] [[package]] @@ -1978,12 +2561,25 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", - "core-foundation", + "bitflags 2.9.4", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +dependencies = [ + "bitflags 2.9.4", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -1991,9 +2587,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -2001,41 +2597,42 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.11.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" dependencies = [ "itoa", "serde", @@ -2055,15 +2652,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.11.0", + "schemars 0.9.0", + "schemars 1.0.4", "serde", "serde_derive", "serde_json", @@ -2073,14 +2672,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] @@ -2096,9 +2695,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -2114,54 +2713,61 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "sketches-ddsketch" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" +checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] -name = "spin" -version = "0.9.8" +name = "socket2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] [[package]] -name = "strsim" -version = "0.10.0" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -2179,20 +2785,20 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.55", + "syn", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -2200,21 +2806,27 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.55" +name = "sync_wrapper" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "system-configuration" @@ -2223,7 +2835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2239,64 +2851,83 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ - "cfg-if", "fastrand", - "rustix", - "windows-sys 0.52.0", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.8", + "windows-sys 0.60.2", ] [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix", - "windows-sys 0.48.0", + "rustix 1.0.8", + "windows-sys 0.60.2", ] [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +dependencies = [ + "thiserror-impl 2.0.16", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "time" -version = "0.3.34" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde", @@ -2306,72 +2937,58 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c" dependencies = [ "num-conv", "time-core", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.36.0" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.59.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] @@ -2380,26 +2997,25 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.10", + "rustls 0.21.12", "tokio", ] [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.22.2", - "rustls-pki-types", + "rustls 0.23.31", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -2408,43 +3024,42 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "tonic" -version = "0.11.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" dependencies = [ - "async-stream", "async-trait", - "axum", - "base64", + "axum 0.8.4", + "base64 0.22.1", "bytes", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.7.0", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", "prost", - "rustls-pemfile 2.1.1", - "rustls-pki-types", + "socket2 0.5.10", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.2", "tokio-stream", - "tower", + "tower 0.5.2", "tower-layer", "tower-service", "tracing", @@ -2452,15 +3067,16 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.11.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", - "syn 2.0.55", + "syn", ] [[package]] @@ -2471,11 +3087,26 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 2.11.0", + "pin-project-lite", "slab", + "sync_wrapper 1.0.2", "tokio", "tokio-util", "tower-layer", @@ -2485,21 +3116,21 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -2509,20 +3140,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -2551,14 +3182,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -2573,17 +3204,23 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "typetag" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "661d18414ec032a49ece2d56eee03636e43c4e8d577047ab334c0ba892e29aaf" +checksum = "73f22b40dd7bfe8c14230cf9702081366421890435b2d625fa92b4acc4c3de6f" dependencies = [ "erased-serde", "inventory", @@ -2594,44 +3231,26 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac73887f47b9312552aa90ef477927ff014d63d1920ca8037c6c1951eab64bb1" +checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", ] [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "untrusted" @@ -2639,40 +3258,53 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "url" -version = "2.5.0" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "virtue" -version = "0.0.13" +version = "0.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" [[package]] name = "want" @@ -2685,58 +3317,63 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.3+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +dependencies = [ + "wit-bindgen", +] [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2744,28 +3381,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2786,20 +3426,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", -] - -[[package]] -name = "which" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", - "windows-sys 0.48.0", + "rustix 0.38.44", ] [[package]] @@ -2826,11 +3453,61 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.4", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", ] [[package]] @@ -2848,7 +3525,25 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -2868,17 +3563,35 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -2889,9 +3602,15 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -2901,9 +3620,15 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -2913,9 +3638,27 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -2925,9 +3668,15 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -2937,9 +3686,15 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -2949,9 +3704,15 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -2961,9 +3722,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winreg" @@ -2975,8 +3742,118 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-bindgen" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 0043432..ee6d09e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,15 +11,15 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://github.com/faradayio/geocode-csv" [dev-dependencies] -cli_test_dir = "0.1.7" -reqwest = { version = "0.11.18", default-features = false, features = [ +cli_test_dir = "^0.1.7" +reqwest = { version = "^0.11.18", default-features = false, features = [ "blocking", ] } [dependencies] -anyhow = { version = "1.0.40", features = ["backtrace"] } -async-trait = "0.1.52" -axum = { version = "0.6.19", default-features = false, features = [ +anyhow = { version = "^1.0.40", features = ["backtrace"] } +async-trait = "^0.1.52" +axum = { version = "^0.6.19", default-features = false, features = [ "http1", "tokio", "tower-log", @@ -27,53 +27,52 @@ axum = { version = "0.6.19", default-features = false, features = [ "headers", "json", ] } -bb8 = "0.8.0" -bb8-redis = "0.13.1" -bigtable_rs = "0.2.5" +bb8 = "^0.8.0" +bb8-redis = "^0.13.1" +bigtable_rs = "^0.2.5" bincode = { version = "2.0.0-rc.2", features = ["serde"] } -clap = { version = "4.3.0", features = ["derive", "wrap_help"] } -csv = "1.0.7" -futures = "0.3.4" -hyper = { version = "0.14.7", features = ["client", "http2", "stream"] } -hyper-rustls = { version = "0.24.1", features = [ +clap = { version = "^4.3.0", features = ["derive", "wrap_help"] } +csv = "^1.0.7" +futures = "^0.3.4" +hyper = { version = "^0.14.7", features = ["client", "http2", "stream"] } +hyper-rustls = { version = "^0.24.1", features = [ "rustls-native-certs", "http2", ] } -leaky-bucket = "1.0.1" +leaky-bucket = "^1.0.1" libpostal-rust = { version = "0.1.1", path = "crates/libpostal-rust" } -# These need to be updated alongside `opinionated_metrics` and its supporting -# crates. -metrics = "0.20.1" -metrics-util = "0.14.0" +metrics = "^0.24.2" +metrics-util = "^0.20.0" opinionated_metrics = { version = "0.2.0", path = "crates/opinionated_metrics" } -rand = "0.8.5" -redis = { version = "0.23.2", default-features = false, features = [ +rand = "^0.8.5" +redis = { version = "^0.23.2", default-features = false, features = [ "aio", "tokio-comp", ] } -serde = { version = "1.0.92", features = ["derive"] } +rustls = { version = "^0.23", default-features = false, features = ["aws-lc-rs"] } +serde = { version = "^1.0.92", features = ["derive"] } # Last version of `serde_derive` that can be built from source. See # https://github.com/serde-rs/serde/issues/2538. -serde_derive = "1.0.184" +serde_derive = "^1.0.184" # IMPORTANT: We require `preserve_order` to correctly handle "structure" JSON # specifications in a way that puts the right data in the right output columns. -serde_json = { version = "1.0.39", features = ["preserve_order"] } -sha2 = "0.10.1" -strum = "0.25.0" -strum_macros = "0.25.2" -tokio = { version = "1.6.0", features = [ +serde_json = { version = "^1.0.39", features = ["preserve_order"] } +sha2 = "^0.10.1" +strum = "^0.25.0" +strum_macros = "^0.25.2" +tokio = { version = "^1.6.0", features = [ "io-util", "macros", "rt-multi-thread", "sync", ] } -tokio-stream = "0.1.6" -tracing = "0.1.29" -tracing-subscriber = { version = "0.3.7", features = ["env-filter"] } -url = "2.1.1" +tokio-stream = "^0.1.6" +tracing = "^0.1.29" +tracing-subscriber = { version = "^0.3.7", features = ["env-filter"] } +url = "^2.1.1" [target.'cfg(not(target_env = "msvc"))'.dependencies] -jemallocator = { version = "0.5.4", features = ["profiling"], optional = true } +jemallocator = { version = "^0.5.4", features = ["profiling"], optional = true } # [profile.release] # debug = true diff --git a/crates/libpostal-rust/src/lib.rs b/crates/libpostal-rust/src/lib.rs index 3cf1a4f..0ba2ee4 100644 --- a/crates/libpostal-rust/src/lib.rs +++ b/crates/libpostal-rust/src/lib.rs @@ -42,7 +42,7 @@ use init::{ use libpostal_sys::{ libpostal_address_parser_response_destroy, libpostal_expand_address, libpostal_expansion_array_destroy, libpostal_get_address_parser_default_options, - libpostal_get_default_options, libpostal_parse_address, size_t, GLOBAL_LOCK, + libpostal_get_default_options, libpostal_parse_address, GLOBAL_LOCK, }; mod errors; @@ -123,7 +123,7 @@ pub fn expand_address(addr: &str, _opt: &ExpandAddressOptions) -> Result Result(), - 8usize, - concat!("Size of: ", stringify!(__fsid_t)) - ); - assert_eq!( - ::std::mem::align_of::<__fsid_t>(), - 4usize, - concat!("Alignment of ", stringify!(__fsid_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__fsid_t>())).__val as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__fsid_t), - "::", - stringify!(__val) - ) - ); -} -pub type __clock_t = ::std::os::raw::c_long; -pub type __rlim_t = ::std::os::raw::c_ulong; -pub type __rlim64_t = ::std::os::raw::c_ulong; -pub type __id_t = ::std::os::raw::c_uint; -pub type __time_t = ::std::os::raw::c_long; -pub type __useconds_t = ::std::os::raw::c_uint; -pub type __suseconds_t = ::std::os::raw::c_long; -pub type __daddr_t = ::std::os::raw::c_int; -pub type __key_t = ::std::os::raw::c_int; -pub type __clockid_t = ::std::os::raw::c_int; -pub type __timer_t = *mut ::std::os::raw::c_void; -pub type __blksize_t = ::std::os::raw::c_long; -pub type __blkcnt_t = ::std::os::raw::c_long; -pub type __blkcnt64_t = ::std::os::raw::c_long; -pub type __fsblkcnt_t = ::std::os::raw::c_ulong; -pub type __fsblkcnt64_t = ::std::os::raw::c_ulong; -pub type __fsfilcnt_t = ::std::os::raw::c_ulong; -pub type __fsfilcnt64_t = ::std::os::raw::c_ulong; -pub type __fsword_t = ::std::os::raw::c_long; -pub type __ssize_t = ::std::os::raw::c_long; -pub type __syscall_slong_t = ::std::os::raw::c_long; -pub type __syscall_ulong_t = ::std::os::raw::c_ulong; -pub type __loff_t = __off64_t; -pub type __caddr_t = *mut ::std::os::raw::c_char; -pub type __intptr_t = ::std::os::raw::c_long; -pub type __socklen_t = ::std::os::raw::c_uint; -pub type __sig_atomic_t = ::std::os::raw::c_int; -pub type __FILE = _IO_FILE; -pub type FILE = _IO_FILE; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct __mbstate_t { - pub __count: ::std::os::raw::c_int, - pub __value: __mbstate_t__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union __mbstate_t__bindgen_ty_1 { - pub __wch: ::std::os::raw::c_uint, - pub __wchb: [::std::os::raw::c_char; 4usize], -} -#[test] -fn bindgen_test_layout___mbstate_t__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<__mbstate_t__bindgen_ty_1>(), - 4usize, - concat!("Size of: ", stringify!(__mbstate_t__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<__mbstate_t__bindgen_ty_1>(), - 4usize, - concat!("Alignment of ", stringify!(__mbstate_t__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__mbstate_t__bindgen_ty_1>())).__wch as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t__bindgen_ty_1), - "::", - stringify!(__wch) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__mbstate_t__bindgen_ty_1>())).__wchb as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t__bindgen_ty_1), - "::", - stringify!(__wchb) - ) - ); -} -#[test] -fn bindgen_test_layout___mbstate_t() { - assert_eq!( - ::std::mem::size_of::<__mbstate_t>(), - 8usize, - concat!("Size of: ", stringify!(__mbstate_t)) - ); - assert_eq!( - ::std::mem::align_of::<__mbstate_t>(), - 4usize, - concat!("Alignment of ", stringify!(__mbstate_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__mbstate_t>())).__count as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t), - "::", - stringify!(__count) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__mbstate_t>())).__value as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t), - "::", - stringify!(__value) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct _G_fpos_t { - pub __pos: __off_t, - pub __state: __mbstate_t, -} -#[test] -fn bindgen_test_layout__G_fpos_t() { - assert_eq!( - ::std::mem::size_of::<_G_fpos_t>(), - 16usize, - concat!("Size of: ", stringify!(_G_fpos_t)) - ); - assert_eq!( - ::std::mem::align_of::<_G_fpos_t>(), - 8usize, - concat!("Alignment of ", stringify!(_G_fpos_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_G_fpos_t>())).__pos as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_G_fpos_t), - "::", - stringify!(__pos) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_G_fpos_t>())).__state as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_G_fpos_t), - "::", - stringify!(__state) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct _G_fpos64_t { - pub __pos: __off64_t, - pub __state: __mbstate_t, -} -#[test] -fn bindgen_test_layout__G_fpos64_t() { - assert_eq!( - ::std::mem::size_of::<_G_fpos64_t>(), - 16usize, - concat!("Size of: ", stringify!(_G_fpos64_t)) - ); - assert_eq!( - ::std::mem::align_of::<_G_fpos64_t>(), - 8usize, - concat!("Alignment of ", stringify!(_G_fpos64_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_G_fpos64_t>())).__pos as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_G_fpos64_t), - "::", - stringify!(__pos) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_G_fpos64_t>())).__state as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_G_fpos64_t), - "::", - stringify!(__state) - ) - ); -} -pub type va_list = __builtin_va_list; -pub type __gnuc_va_list = __builtin_va_list; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _IO_jump_t { - _unused: [u8; 0], -} -pub type _IO_lock_t = ::std::os::raw::c_void; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _IO_marker { - pub _next: *mut _IO_marker, - pub _sbuf: *mut _IO_FILE, - pub _pos: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout__IO_marker() { - assert_eq!( - ::std::mem::size_of::<_IO_marker>(), - 24usize, - concat!("Size of: ", stringify!(_IO_marker)) - ); - assert_eq!( - ::std::mem::align_of::<_IO_marker>(), - 8usize, - concat!("Alignment of ", stringify!(_IO_marker)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_marker>()))._next as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_IO_marker), - "::", - stringify!(_next) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_marker>()))._sbuf as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_IO_marker), - "::", - stringify!(_sbuf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_marker>()))._pos as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(_IO_marker), - "::", - stringify!(_pos) - ) - ); -} -pub const __codecvt_result___codecvt_ok: __codecvt_result = 0; -pub const __codecvt_result___codecvt_partial: __codecvt_result = 1; -pub const __codecvt_result___codecvt_error: __codecvt_result = 2; -pub const __codecvt_result___codecvt_noconv: __codecvt_result = 3; -pub type __codecvt_result = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _IO_FILE { - pub _flags: ::std::os::raw::c_int, - pub _IO_read_ptr: *mut ::std::os::raw::c_char, - pub _IO_read_end: *mut ::std::os::raw::c_char, - pub _IO_read_base: *mut ::std::os::raw::c_char, - pub _IO_write_base: *mut ::std::os::raw::c_char, - pub _IO_write_ptr: *mut ::std::os::raw::c_char, - pub _IO_write_end: *mut ::std::os::raw::c_char, - pub _IO_buf_base: *mut ::std::os::raw::c_char, - pub _IO_buf_end: *mut ::std::os::raw::c_char, - pub _IO_save_base: *mut ::std::os::raw::c_char, - pub _IO_backup_base: *mut ::std::os::raw::c_char, - pub _IO_save_end: *mut ::std::os::raw::c_char, - pub _markers: *mut _IO_marker, - pub _chain: *mut _IO_FILE, - pub _fileno: ::std::os::raw::c_int, - pub _flags2: ::std::os::raw::c_int, - pub _old_offset: __off_t, - pub _cur_column: ::std::os::raw::c_ushort, - pub _vtable_offset: ::std::os::raw::c_schar, - pub _shortbuf: [::std::os::raw::c_char; 1usize], - pub _lock: *mut _IO_lock_t, - pub _offset: __off64_t, - pub __pad1: *mut ::std::os::raw::c_void, - pub __pad2: *mut ::std::os::raw::c_void, - pub __pad3: *mut ::std::os::raw::c_void, - pub __pad4: *mut ::std::os::raw::c_void, - pub __pad5: size_t, - pub _mode: ::std::os::raw::c_int, - pub _unused2: [::std::os::raw::c_char; 20usize], -} -#[test] -fn bindgen_test_layout__IO_FILE() { - assert_eq!( - ::std::mem::size_of::<_IO_FILE>(), - 216usize, - concat!("Size of: ", stringify!(_IO_FILE)) - ); - assert_eq!( - ::std::mem::align_of::<_IO_FILE>(), - 8usize, - concat!("Alignment of ", stringify!(_IO_FILE)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._flags as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_flags) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_read_ptr as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_read_ptr) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_read_end as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_read_end) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_read_base as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_read_base) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_write_base as *const _ as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_write_base) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_write_ptr as *const _ as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_write_ptr) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_write_end as *const _ as usize - }, - 48usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_write_end) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_buf_base as *const _ as usize - }, - 56usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_buf_base) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_buf_end as *const _ as usize - }, - 64usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_buf_end) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_save_base as *const _ as usize - }, - 72usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_save_base) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_backup_base as *const _ as usize - }, - 80usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_backup_base) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._IO_save_end as *const _ as usize - }, - 88usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_IO_save_end) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._markers as *const _ as usize }, - 96usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_markers) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._chain as *const _ as usize }, - 104usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_chain) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._fileno as *const _ as usize }, - 112usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_fileno) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._flags2 as *const _ as usize }, - 116usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_flags2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._old_offset as *const _ as usize - }, - 120usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_old_offset) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._cur_column as *const _ as usize - }, - 128usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_cur_column) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<_IO_FILE>()))._vtable_offset as *const _ as usize - }, - 130usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_vtable_offset) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._shortbuf as *const _ as usize }, - 131usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_shortbuf) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._lock as *const _ as usize }, - 136usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_lock) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._offset as *const _ as usize }, - 144usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_offset) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>())).__pad1 as *const _ as usize }, - 152usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad1) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>())).__pad2 as *const _ as usize }, - 160usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad2) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>())).__pad3 as *const _ as usize }, - 168usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad3) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>())).__pad4 as *const _ as usize }, - 176usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad4) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>())).__pad5 as *const _ as usize }, - 184usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(__pad5) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._mode as *const _ as usize }, - 192usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_mode) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<_IO_FILE>()))._unused2 as *const _ as usize }, - 196usize, - concat!( - "Offset of field: ", - stringify!(_IO_FILE), - "::", - stringify!(_unused2) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _IO_FILE_plus { - _unused: [u8; 0], -} -extern "C" { - pub static mut _IO_2_1_stdin_: _IO_FILE_plus; -} -extern "C" { - pub static mut _IO_2_1_stdout_: _IO_FILE_plus; -} -extern "C" { - pub static mut _IO_2_1_stderr_: _IO_FILE_plus; -} -pub type __io_read_fn = ::std::option::Option< - unsafe extern "C" fn( - __cookie: *mut ::std::os::raw::c_void, - __buf: *mut ::std::os::raw::c_char, - __nbytes: size_t, - ) -> __ssize_t, ->; -pub type __io_write_fn = ::std::option::Option< - unsafe extern "C" fn( - __cookie: *mut ::std::os::raw::c_void, - __buf: *const ::std::os::raw::c_char, - __n: size_t, - ) -> __ssize_t, ->; -pub type __io_seek_fn = ::std::option::Option< - unsafe extern "C" fn( - __cookie: *mut ::std::os::raw::c_void, - __pos: *mut __off64_t, - __w: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int, ->; -pub type __io_close_fn = ::std::option::Option< - unsafe extern "C" fn( - __cookie: *mut ::std::os::raw::c_void, - ) -> ::std::os::raw::c_int, ->; -extern "C" { - pub fn __underflow(arg1: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn __uflow(arg1: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn __overflow( - arg1: *mut _IO_FILE, - arg2: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_getc(__fp: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_putc( - __c: ::std::os::raw::c_int, - __fp: *mut _IO_FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_feof(__fp: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_ferror(__fp: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_peekc_locked(__fp: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_flockfile(arg1: *mut _IO_FILE); -} -extern "C" { - pub fn _IO_funlockfile(arg1: *mut _IO_FILE); -} -extern "C" { - pub fn _IO_ftrylockfile(arg1: *mut _IO_FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_vfscanf( - arg1: *mut _IO_FILE, - arg2: *const ::std::os::raw::c_char, - arg3: *mut __va_list_tag, - arg4: *mut ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_vfprintf( - arg1: *mut _IO_FILE, - arg2: *const ::std::os::raw::c_char, - arg3: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn _IO_padn( - arg1: *mut _IO_FILE, - arg2: ::std::os::raw::c_int, - arg3: __ssize_t, - ) -> __ssize_t; -} -extern "C" { - pub fn _IO_sgetn( - arg1: *mut _IO_FILE, - arg2: *mut ::std::os::raw::c_void, - arg3: size_t, - ) -> size_t; -} -extern "C" { - pub fn _IO_seekoff( - arg1: *mut _IO_FILE, - arg2: __off64_t, - arg3: ::std::os::raw::c_int, - arg4: ::std::os::raw::c_int, - ) -> __off64_t; -} -extern "C" { - pub fn _IO_seekpos( - arg1: *mut _IO_FILE, - arg2: __off64_t, - arg3: ::std::os::raw::c_int, - ) -> __off64_t; -} -extern "C" { - pub fn _IO_free_backup_area(arg1: *mut _IO_FILE); -} -pub type off_t = __off_t; -pub type ssize_t = __ssize_t; -pub type fpos_t = _G_fpos_t; -extern "C" { - pub static mut stdin: *mut _IO_FILE; -} -extern "C" { - pub static mut stdout: *mut _IO_FILE; -} -extern "C" { - pub static mut stderr: *mut _IO_FILE; -} -extern "C" { - pub fn remove(__filename: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn rename( - __old: *const ::std::os::raw::c_char, - __new: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn renameat( - __oldfd: ::std::os::raw::c_int, - __old: *const ::std::os::raw::c_char, - __newfd: ::std::os::raw::c_int, - __new: *const ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn tmpfile() -> *mut FILE; -} -extern "C" { - pub fn tmpnam(__s: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn tmpnam_r(__s: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn tempnam( - __dir: *const ::std::os::raw::c_char, - __pfx: *const ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn fclose(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fflush(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fflush_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fopen( - __filename: *const ::std::os::raw::c_char, - __modes: *const ::std::os::raw::c_char, - ) -> *mut FILE; -} -extern "C" { - pub fn freopen( - __filename: *const ::std::os::raw::c_char, - __modes: *const ::std::os::raw::c_char, - __stream: *mut FILE, - ) -> *mut FILE; -} -extern "C" { - pub fn fdopen( - __fd: ::std::os::raw::c_int, - __modes: *const ::std::os::raw::c_char, - ) -> *mut FILE; -} -extern "C" { - pub fn fmemopen( - __s: *mut ::std::os::raw::c_void, - __len: size_t, - __modes: *const ::std::os::raw::c_char, - ) -> *mut FILE; -} -extern "C" { - pub fn open_memstream( - __bufloc: *mut *mut ::std::os::raw::c_char, - __sizeloc: *mut size_t, - ) -> *mut FILE; -} -extern "C" { - pub fn setbuf(__stream: *mut FILE, __buf: *mut ::std::os::raw::c_char); -} -extern "C" { - pub fn setvbuf( - __stream: *mut FILE, - __buf: *mut ::std::os::raw::c_char, - __modes: ::std::os::raw::c_int, - __n: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn setbuffer( - __stream: *mut FILE, - __buf: *mut ::std::os::raw::c_char, - __size: size_t, - ); -} -extern "C" { - pub fn setlinebuf(__stream: *mut FILE); -} -extern "C" { - pub fn fprintf( - __stream: *mut FILE, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn printf( - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn sprintf( - __s: *mut ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vfprintf( - __s: *mut FILE, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vprintf( - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vsprintf( - __s: *mut ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn snprintf( - __s: *mut ::std::os::raw::c_char, - __maxlen: ::std::os::raw::c_ulong, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vsnprintf( - __s: *mut ::std::os::raw::c_char, - __maxlen: ::std::os::raw::c_ulong, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vdprintf( - __fd: ::std::os::raw::c_int, - __fmt: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn dprintf( - __fd: ::std::os::raw::c_int, - __fmt: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fscanf( - __stream: *mut FILE, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn scanf( - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn sscanf( - __s: *const ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_fscanf"] - pub fn fscanf1( - __stream: *mut FILE, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_scanf"] - pub fn scanf1( - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_sscanf"] - pub fn sscanf1( - __s: *const ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - ... - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vfscanf( - __s: *mut FILE, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vscanf( - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn vsscanf( - __s: *const ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_vfscanf"] - pub fn vfscanf1( - __s: *mut FILE, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_vscanf"] - pub fn vscanf1( - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__isoc99_vsscanf"] - pub fn vsscanf1( - __s: *const ::std::os::raw::c_char, - __format: *const ::std::os::raw::c_char, - __arg: *mut __va_list_tag, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fgetc(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getc(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getchar() -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getc_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getchar_unlocked() -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fgetc_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fputc( - __c: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn putc( - __c: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn putchar(__c: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fputc_unlocked( - __c: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn putc_unlocked( - __c: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn putchar_unlocked(__c: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getw(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn putw( - __w: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fgets( - __s: *mut ::std::os::raw::c_char, - __n: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn __getdelim( - __lineptr: *mut *mut ::std::os::raw::c_char, - __n: *mut size_t, - __delimiter: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> __ssize_t; -} -extern "C" { - pub fn getdelim( - __lineptr: *mut *mut ::std::os::raw::c_char, - __n: *mut size_t, - __delimiter: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> __ssize_t; -} -extern "C" { - pub fn getline( - __lineptr: *mut *mut ::std::os::raw::c_char, - __n: *mut size_t, - __stream: *mut FILE, - ) -> __ssize_t; -} -extern "C" { - pub fn fputs( - __s: *const ::std::os::raw::c_char, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn puts(__s: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ungetc( - __c: ::std::os::raw::c_int, - __stream: *mut FILE, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fread( - __ptr: *mut ::std::os::raw::c_void, - __size: size_t, - __n: size_t, - __stream: *mut FILE, - ) -> size_t; -} -extern "C" { - pub fn fwrite( - __ptr: *const ::std::os::raw::c_void, - __size: size_t, - __n: size_t, - __s: *mut FILE, - ) -> size_t; -} -extern "C" { - pub fn fread_unlocked( - __ptr: *mut ::std::os::raw::c_void, - __size: size_t, - __n: size_t, - __stream: *mut FILE, - ) -> size_t; -} -extern "C" { - pub fn fwrite_unlocked( - __ptr: *const ::std::os::raw::c_void, - __size: size_t, - __n: size_t, - __stream: *mut FILE, - ) -> size_t; -} -extern "C" { - pub fn fseek( - __stream: *mut FILE, - __off: ::std::os::raw::c_long, - __whence: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ftell(__stream: *mut FILE) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn rewind(__stream: *mut FILE); -} -extern "C" { - pub fn fseeko( - __stream: *mut FILE, - __off: __off_t, - __whence: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ftello(__stream: *mut FILE) -> __off_t; -} -extern "C" { - pub fn fgetpos(__stream: *mut FILE, __pos: *mut fpos_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fsetpos(__stream: *mut FILE, __pos: *const fpos_t) - -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clearerr(__stream: *mut FILE); -} -extern "C" { - pub fn feof(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ferror(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clearerr_unlocked(__stream: *mut FILE); -} -extern "C" { - pub fn feof_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ferror_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn perror(__s: *const ::std::os::raw::c_char); -} -extern "C" { - pub static mut sys_nerr: ::std::os::raw::c_int; -} -extern "C" { - pub static mut sys_errlist: [*const ::std::os::raw::c_char; 0usize]; -} -extern "C" { - pub fn fileno(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fileno_unlocked(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn popen( - __command: *const ::std::os::raw::c_char, - __modes: *const ::std::os::raw::c_char, - ) -> *mut FILE; -} -extern "C" { - pub fn pclose(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn ctermid(__s: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn flockfile(__stream: *mut FILE); -} -extern "C" { - pub fn ftrylockfile(__stream: *mut FILE) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn funlockfile(__stream: *mut FILE); -} -pub type wchar_t = ::std::os::raw::c_int; -pub const idtype_t_P_ALL: idtype_t = 0; -pub const idtype_t_P_PID: idtype_t = 1; -pub const idtype_t_P_PGID: idtype_t = 2; -pub type idtype_t = ::std::os::raw::c_uint; -pub type _Float32 = f32; -pub type _Float64 = f64; -pub type _Float32x = f64; -pub type _Float64x = u128; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct div_t { - pub quot: ::std::os::raw::c_int, - pub rem: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_div_t() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(div_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(div_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(div_t), - "::", - stringify!(quot) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(div_t), - "::", - stringify!(rem) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct ldiv_t { - pub quot: ::std::os::raw::c_long, - pub rem: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_ldiv_t() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(ldiv_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(ldiv_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(ldiv_t), - "::", - stringify!(quot) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(ldiv_t), - "::", - stringify!(rem) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct lldiv_t { - pub quot: ::std::os::raw::c_longlong, - pub rem: ::std::os::raw::c_longlong, -} -#[test] -fn bindgen_test_layout_lldiv_t() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(lldiv_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(lldiv_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(lldiv_t), - "::", - stringify!(quot) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(lldiv_t), - "::", - stringify!(rem) - ) - ); -} -extern "C" { - pub fn __ctype_get_mb_cur_max() -> size_t; -} -extern "C" { - pub fn atof(__nptr: *const ::std::os::raw::c_char) -> f64; -} -extern "C" { - pub fn atoi(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn atol(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn atoll(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_longlong; -} -extern "C" { - pub fn strtod( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - ) -> f64; -} -extern "C" { - pub fn strtof( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - ) -> f32; -} -extern "C" { - pub fn strtold( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - ) -> u128; -} -extern "C" { - pub fn strtol( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn strtoul( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_ulong; -} -extern "C" { - pub fn strtoq( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_longlong; -} -extern "C" { - pub fn strtouq( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_ulonglong; -} -extern "C" { - pub fn strtoll( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_longlong; -} -extern "C" { - pub fn strtoull( - __nptr: *const ::std::os::raw::c_char, - __endptr: *mut *mut ::std::os::raw::c_char, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_ulonglong; -} -extern "C" { - pub fn l64a(__n: ::std::os::raw::c_long) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn a64l(__s: *const ::std::os::raw::c_char) -> ::std::os::raw::c_long; -} -pub type u_char = __u_char; -pub type u_short = __u_short; -pub type u_int = __u_int; -pub type u_long = __u_long; -pub type quad_t = __quad_t; -pub type u_quad_t = __u_quad_t; -pub type fsid_t = __fsid_t; -pub type loff_t = __loff_t; -pub type ino_t = __ino_t; -pub type dev_t = __dev_t; -pub type gid_t = __gid_t; -pub type mode_t = __mode_t; -pub type nlink_t = __nlink_t; -pub type uid_t = __uid_t; -pub type pid_t = __pid_t; -pub type id_t = __id_t; -pub type daddr_t = __daddr_t; -pub type caddr_t = __caddr_t; -pub type key_t = __key_t; -pub type clock_t = __clock_t; -pub type clockid_t = __clockid_t; -pub type time_t = __time_t; -pub type timer_t = __timer_t; -pub type ulong = ::std::os::raw::c_ulong; -pub type ushort = ::std::os::raw::c_ushort; -pub type uint = ::std::os::raw::c_uint; -pub type u_int8_t = ::std::os::raw::c_uchar; -pub type u_int16_t = ::std::os::raw::c_ushort; -pub type u_int32_t = ::std::os::raw::c_uint; -pub type u_int64_t = ::std::os::raw::c_ulong; -pub type register_t = ::std::os::raw::c_long; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __sigset_t { - pub __val: [::std::os::raw::c_ulong; 16usize], -} -#[test] -fn bindgen_test_layout___sigset_t() { - assert_eq!( - ::std::mem::size_of::<__sigset_t>(), - 128usize, - concat!("Size of: ", stringify!(__sigset_t)) - ); - assert_eq!( - ::std::mem::align_of::<__sigset_t>(), - 8usize, - concat!("Alignment of ", stringify!(__sigset_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__sigset_t>())).__val as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__sigset_t), - "::", - stringify!(__val) - ) - ); -} -pub type sigset_t = __sigset_t; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct timeval { - pub tv_sec: __time_t, - pub tv_usec: __suseconds_t, -} -#[test] -fn bindgen_test_layout_timeval() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(timeval)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(timeval)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tv_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(timeval), - "::", - stringify!(tv_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tv_usec as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(timeval), - "::", - stringify!(tv_usec) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct timespec { - pub tv_sec: __time_t, - pub tv_nsec: __syscall_slong_t, -} -#[test] -fn bindgen_test_layout_timespec() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(timespec)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(timespec)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tv_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(timespec), - "::", - stringify!(tv_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).tv_nsec as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(timespec), - "::", - stringify!(tv_nsec) - ) - ); -} -pub type suseconds_t = __suseconds_t; -pub type __fd_mask = ::std::os::raw::c_long; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct fd_set { - pub __fds_bits: [__fd_mask; 16usize], -} -#[test] -fn bindgen_test_layout_fd_set() { - assert_eq!( - ::std::mem::size_of::(), - 128usize, - concat!("Size of: ", stringify!(fd_set)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(fd_set)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__fds_bits as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(fd_set), - "::", - stringify!(__fds_bits) - ) - ); -} -pub type fd_mask = __fd_mask; -extern "C" { - pub fn select( - __nfds: ::std::os::raw::c_int, - __readfds: *mut fd_set, - __writefds: *mut fd_set, - __exceptfds: *mut fd_set, - __timeout: *mut timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn pselect( - __nfds: ::std::os::raw::c_int, - __readfds: *mut fd_set, - __writefds: *mut fd_set, - __exceptfds: *mut fd_set, - __timeout: *const timespec, - __sigmask: *const __sigset_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn gnu_dev_major(__dev: __dev_t) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn gnu_dev_minor(__dev: __dev_t) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn gnu_dev_makedev( - __major: ::std::os::raw::c_uint, - __minor: ::std::os::raw::c_uint, - ) -> __dev_t; -} -pub type blksize_t = __blksize_t; -pub type blkcnt_t = __blkcnt_t; -pub type fsblkcnt_t = __fsblkcnt_t; -pub type fsfilcnt_t = __fsfilcnt_t; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_rwlock_arch_t { - pub __readers: ::std::os::raw::c_uint, - pub __writers: ::std::os::raw::c_uint, - pub __wrphase_futex: ::std::os::raw::c_uint, - pub __writers_futex: ::std::os::raw::c_uint, - pub __pad3: ::std::os::raw::c_uint, - pub __pad4: ::std::os::raw::c_uint, - pub __cur_writer: ::std::os::raw::c_int, - pub __shared: ::std::os::raw::c_int, - pub __rwelision: ::std::os::raw::c_schar, - pub __pad1: [::std::os::raw::c_uchar; 7usize], - pub __pad2: ::std::os::raw::c_ulong, - pub __flags: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout___pthread_rwlock_arch_t() { - assert_eq!( - ::std::mem::size_of::<__pthread_rwlock_arch_t>(), - 56usize, - concat!("Size of: ", stringify!(__pthread_rwlock_arch_t)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_rwlock_arch_t>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_rwlock_arch_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__readers as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__readers) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__writers as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__writers) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__wrphase_futex - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__wrphase_futex) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__writers_futex - as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__writers_futex) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__pad3 as *const _ - as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__pad3) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__pad4 as *const _ - as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__pad4) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__cur_writer - as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__cur_writer) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__shared as *const _ - as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__shared) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__rwelision as *const _ - as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__rwelision) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__pad1 as *const _ - as usize - }, - 33usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__pad1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__pad2 as *const _ - as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__pad2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_rwlock_arch_t>())).__flags as *const _ - as usize - }, - 48usize, - concat!( - "Offset of field: ", - stringify!(__pthread_rwlock_arch_t), - "::", - stringify!(__flags) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_internal_list { - pub __prev: *mut __pthread_internal_list, - pub __next: *mut __pthread_internal_list, -} -#[test] -fn bindgen_test_layout___pthread_internal_list() { - assert_eq!( - ::std::mem::size_of::<__pthread_internal_list>(), - 16usize, - concat!("Size of: ", stringify!(__pthread_internal_list)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_internal_list>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_internal_list)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_internal_list>())).__prev as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_internal_list), - "::", - stringify!(__prev) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_internal_list>())).__next as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__pthread_internal_list), - "::", - stringify!(__next) - ) - ); -} -pub type __pthread_list_t = __pthread_internal_list; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_mutex_s { - pub __lock: ::std::os::raw::c_int, - pub __count: ::std::os::raw::c_uint, - pub __owner: ::std::os::raw::c_int, - pub __nusers: ::std::os::raw::c_uint, - pub __kind: ::std::os::raw::c_int, - pub __spins: ::std::os::raw::c_short, - pub __elision: ::std::os::raw::c_short, - pub __list: __pthread_list_t, -} -#[test] -fn bindgen_test_layout___pthread_mutex_s() { - assert_eq!( - ::std::mem::size_of::<__pthread_mutex_s>(), - 40usize, - concat!("Size of: ", stringify!(__pthread_mutex_s)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_mutex_s>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_mutex_s)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__lock as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__lock) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__count as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__count) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__owner as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__owner) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__nusers as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__nusers) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__kind as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__kind) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__spins as *const _ as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__spins) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__elision as *const _ - as usize - }, - 22usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__elision) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_mutex_s>())).__list as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(__pthread_mutex_s), - "::", - stringify!(__list) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct __pthread_cond_s { - pub __bindgen_anon_1: __pthread_cond_s__bindgen_ty_1, - pub __bindgen_anon_2: __pthread_cond_s__bindgen_ty_2, - pub __g_refs: [::std::os::raw::c_uint; 2usize], - pub __g_size: [::std::os::raw::c_uint; 2usize], - pub __g1_orig_size: ::std::os::raw::c_uint, - pub __wrefs: ::std::os::raw::c_uint, - pub __g_signals: [::std::os::raw::c_uint; 2usize], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union __pthread_cond_s__bindgen_ty_1 { - pub __wseq: ::std::os::raw::c_ulonglong, - pub __wseq32: __pthread_cond_s__bindgen_ty_1__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_cond_s__bindgen_ty_1__bindgen_ty_1 { - pub __low: ::std::os::raw::c_uint, - pub __high: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout___pthread_cond_s__bindgen_ty_1__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<__pthread_cond_s__bindgen_ty_1__bindgen_ty_1>(), - 8usize, - concat!( - "Size of: ", - stringify!(__pthread_cond_s__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_cond_s__bindgen_ty_1__bindgen_ty_1>(), - 4usize, - concat!( - "Alignment of ", - stringify!(__pthread_cond_s__bindgen_ty_1__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_1__bindgen_ty_1>())) - .__low as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(__low) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_1__bindgen_ty_1>())) - .__high as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_1__bindgen_ty_1), - "::", - stringify!(__high) - ) - ); -} -#[test] -fn bindgen_test_layout___pthread_cond_s__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<__pthread_cond_s__bindgen_ty_1>(), - 8usize, - concat!("Size of: ", stringify!(__pthread_cond_s__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_cond_s__bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_cond_s__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_1>())).__wseq - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_1), - "::", - stringify!(__wseq) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_1>())).__wseq32 - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_1), - "::", - stringify!(__wseq32) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union __pthread_cond_s__bindgen_ty_2 { - pub __g1_start: ::std::os::raw::c_ulonglong, - pub __g1_start32: __pthread_cond_s__bindgen_ty_2__bindgen_ty_1, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_cond_s__bindgen_ty_2__bindgen_ty_1 { - pub __low: ::std::os::raw::c_uint, - pub __high: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout___pthread_cond_s__bindgen_ty_2__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<__pthread_cond_s__bindgen_ty_2__bindgen_ty_1>(), - 8usize, - concat!( - "Size of: ", - stringify!(__pthread_cond_s__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_cond_s__bindgen_ty_2__bindgen_ty_1>(), - 4usize, - concat!( - "Alignment of ", - stringify!(__pthread_cond_s__bindgen_ty_2__bindgen_ty_1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_2__bindgen_ty_1>())) - .__low as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(__low) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_2__bindgen_ty_1>())) - .__high as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_2__bindgen_ty_1), - "::", - stringify!(__high) - ) - ); -} -#[test] -fn bindgen_test_layout___pthread_cond_s__bindgen_ty_2() { - assert_eq!( - ::std::mem::size_of::<__pthread_cond_s__bindgen_ty_2>(), - 8usize, - concat!("Size of: ", stringify!(__pthread_cond_s__bindgen_ty_2)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_cond_s__bindgen_ty_2>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_cond_s__bindgen_ty_2)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_2>())).__g1_start - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_2), - "::", - stringify!(__g1_start) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s__bindgen_ty_2>())).__g1_start32 - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s__bindgen_ty_2), - "::", - stringify!(__g1_start32) - ) - ); -} -#[test] -fn bindgen_test_layout___pthread_cond_s() { - assert_eq!( - ::std::mem::size_of::<__pthread_cond_s>(), - 48usize, - concat!("Size of: ", stringify!(__pthread_cond_s)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_cond_s>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_cond_s)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s>())).__g_refs as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s), - "::", - stringify!(__g_refs) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s>())).__g_size as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s), - "::", - stringify!(__g_size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s>())).__g1_orig_size as *const _ - as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s), - "::", - stringify!(__g1_orig_size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s>())).__wrefs as *const _ as usize - }, - 36usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s), - "::", - stringify!(__wrefs) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__pthread_cond_s>())).__g_signals as *const _ - as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(__pthread_cond_s), - "::", - stringify!(__g_signals) - ) - ); -} -pub type pthread_t = ::std::os::raw::c_ulong; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_mutexattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_pthread_mutexattr_t() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pthread_mutexattr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pthread_mutexattr_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutexattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutexattr_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_condattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_pthread_condattr_t() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pthread_condattr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pthread_condattr_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_condattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_condattr_t), - "::", - stringify!(__align) - ) - ); -} -pub type pthread_key_t = ::std::os::raw::c_uint; -pub type pthread_once_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_attr_t { - pub __size: [::std::os::raw::c_char; 56usize], - pub __align: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_pthread_attr_t() { - assert_eq!( - ::std::mem::size_of::(), - 56usize, - concat!("Size of: ", stringify!(pthread_attr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_attr_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_attr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_attr_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_mutex_t { - pub __data: __pthread_mutex_s, - pub __size: [::std::os::raw::c_char; 40usize], - pub __align: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_pthread_mutex_t() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(pthread_mutex_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_mutex_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__data as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_cond_t { - pub __data: __pthread_cond_s, - pub __size: [::std::os::raw::c_char; 48usize], - pub __align: ::std::os::raw::c_longlong, -} -#[test] -fn bindgen_test_layout_pthread_cond_t() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(pthread_cond_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_cond_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__data as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_rwlock_t { - pub __data: __pthread_rwlock_arch_t, - pub __size: [::std::os::raw::c_char; 56usize], - pub __align: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_pthread_rwlock_t() { - assert_eq!( - ::std::mem::size_of::(), - 56usize, - concat!("Size of: ", stringify!(pthread_rwlock_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_rwlock_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__data as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_rwlockattr_t { - pub __size: [::std::os::raw::c_char; 8usize], - pub __align: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_pthread_rwlockattr_t() { - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(pthread_rwlockattr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_rwlockattr_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlockattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlockattr_t), - "::", - stringify!(__align) - ) - ); -} -pub type pthread_spinlock_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_barrier_t { - pub __size: [::std::os::raw::c_char; 32usize], - pub __align: ::std::os::raw::c_long, -} -#[test] -fn bindgen_test_layout_pthread_barrier_t() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(pthread_barrier_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pthread_barrier_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrier_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrier_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_barrierattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_pthread_barrierattr_t() { - assert_eq!( - ::std::mem::size_of::(), - 4usize, - concat!("Size of: ", stringify!(pthread_barrierattr_t)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pthread_barrierattr_t)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__size as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrierattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__align as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrierattr_t), - "::", - stringify!(__align) - ) - ); -} -extern "C" { - pub fn random() -> ::std::os::raw::c_long; -} -extern "C" { - pub fn srandom(__seed: ::std::os::raw::c_uint); -} -extern "C" { - pub fn initstate( - __seed: ::std::os::raw::c_uint, - __statebuf: *mut ::std::os::raw::c_char, - __statelen: size_t, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn setstate( - __statebuf: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct random_data { - pub fptr: *mut i32, - pub rptr: *mut i32, - pub state: *mut i32, - pub rand_type: ::std::os::raw::c_int, - pub rand_deg: ::std::os::raw::c_int, - pub rand_sep: ::std::os::raw::c_int, - pub end_ptr: *mut i32, -} -#[test] -fn bindgen_test_layout_random_data() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(random_data)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(random_data)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).fptr as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(fptr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).rptr as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(rptr) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).state as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(state) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).rand_type as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(rand_type) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).rand_deg as *const _ as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(rand_deg) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).rand_sep as *const _ as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(rand_sep) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).end_ptr as *const _ as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(random_data), - "::", - stringify!(end_ptr) - ) - ); -} -extern "C" { - pub fn random_r( - __buf: *mut random_data, - __result: *mut i32, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn srandom_r( - __seed: ::std::os::raw::c_uint, - __buf: *mut random_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn initstate_r( - __seed: ::std::os::raw::c_uint, - __statebuf: *mut ::std::os::raw::c_char, - __statelen: size_t, - __buf: *mut random_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn setstate_r( - __statebuf: *mut ::std::os::raw::c_char, - __buf: *mut random_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn rand() -> ::std::os::raw::c_int; -} -extern "C" { - pub fn srand(__seed: ::std::os::raw::c_uint); -} -extern "C" { - pub fn rand_r(__seed: *mut ::std::os::raw::c_uint) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn drand48() -> f64; -} -extern "C" { - pub fn erand48(__xsubi: *mut ::std::os::raw::c_ushort) -> f64; -} -extern "C" { - pub fn lrand48() -> ::std::os::raw::c_long; -} -extern "C" { - pub fn nrand48(__xsubi: *mut ::std::os::raw::c_ushort) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn mrand48() -> ::std::os::raw::c_long; -} -extern "C" { - pub fn jrand48(__xsubi: *mut ::std::os::raw::c_ushort) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn srand48(__seedval: ::std::os::raw::c_long); -} -extern "C" { - pub fn seed48( - __seed16v: *mut ::std::os::raw::c_ushort, - ) -> *mut ::std::os::raw::c_ushort; -} -extern "C" { - pub fn lcong48(__param: *mut ::std::os::raw::c_ushort); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct drand48_data { - pub __x: [::std::os::raw::c_ushort; 3usize], - pub __old_x: [::std::os::raw::c_ushort; 3usize], - pub __c: ::std::os::raw::c_ushort, - pub __init: ::std::os::raw::c_ushort, - pub __a: ::std::os::raw::c_ulonglong, -} -#[test] -fn bindgen_test_layout_drand48_data() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(drand48_data)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(drand48_data)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__x as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(drand48_data), - "::", - stringify!(__x) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__old_x as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(drand48_data), - "::", - stringify!(__old_x) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__c as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(drand48_data), - "::", - stringify!(__c) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).__init as *const _ as usize - }, - 14usize, - concat!( - "Offset of field: ", - stringify!(drand48_data), - "::", - stringify!(__init) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::())).__a as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(drand48_data), - "::", - stringify!(__a) - ) - ); -} -extern "C" { - pub fn drand48_r( - __buffer: *mut drand48_data, - __result: *mut f64, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn erand48_r( - __xsubi: *mut ::std::os::raw::c_ushort, - __buffer: *mut drand48_data, - __result: *mut f64, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn lrand48_r( - __buffer: *mut drand48_data, - __result: *mut ::std::os::raw::c_long, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn nrand48_r( - __xsubi: *mut ::std::os::raw::c_ushort, - __buffer: *mut drand48_data, - __result: *mut ::std::os::raw::c_long, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mrand48_r( - __buffer: *mut drand48_data, - __result: *mut ::std::os::raw::c_long, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn jrand48_r( - __xsubi: *mut ::std::os::raw::c_ushort, - __buffer: *mut drand48_data, - __result: *mut ::std::os::raw::c_long, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn srand48_r( - __seedval: ::std::os::raw::c_long, - __buffer: *mut drand48_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn seed48_r( - __seed16v: *mut ::std::os::raw::c_ushort, - __buffer: *mut drand48_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn lcong48_r( - __param: *mut ::std::os::raw::c_ushort, - __buffer: *mut drand48_data, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn malloc(__size: ::std::os::raw::c_ulong) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn calloc( - __nmemb: ::std::os::raw::c_ulong, - __size: ::std::os::raw::c_ulong, - ) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn realloc( - __ptr: *mut ::std::os::raw::c_void, - __size: ::std::os::raw::c_ulong, - ) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn free(__ptr: *mut ::std::os::raw::c_void); -} -extern "C" { - pub fn alloca(__size: ::std::os::raw::c_ulong) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn valloc(__size: size_t) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn posix_memalign( - __memptr: *mut *mut ::std::os::raw::c_void, - __alignment: size_t, - __size: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn aligned_alloc( - __alignment: size_t, - __size: size_t, - ) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn abort(); -} -extern "C" { - pub fn atexit( - __func: ::std::option::Option, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn at_quick_exit( - __func: ::std::option::Option, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn on_exit( - __func: ::std::option::Option< - unsafe extern "C" fn( - __status: ::std::os::raw::c_int, - __arg: *mut ::std::os::raw::c_void, - ), - >, - __arg: *mut ::std::os::raw::c_void, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn exit(__status: ::std::os::raw::c_int); -} -extern "C" { - pub fn quick_exit(__status: ::std::os::raw::c_int); -} -extern "C" { - pub fn _Exit(__status: ::std::os::raw::c_int); -} -extern "C" { - pub fn getenv( - __name: *const ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn putenv(__string: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn setenv( - __name: *const ::std::os::raw::c_char, - __value: *const ::std::os::raw::c_char, - __replace: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn unsetenv(__name: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clearenv() -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mktemp( - __template: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn mkstemp(__template: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mkstemps( - __template: *mut ::std::os::raw::c_char, - __suffixlen: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mkdtemp( - __template: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn system(__command: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn realpath( - __name: *const ::std::os::raw::c_char, - __resolved: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -pub type __compar_fn_t = ::std::option::Option< - unsafe extern "C" fn( - arg1: *const ::std::os::raw::c_void, - arg2: *const ::std::os::raw::c_void, - ) -> ::std::os::raw::c_int, ->; -extern "C" { - pub fn bsearch( - __key: *const ::std::os::raw::c_void, - __base: *const ::std::os::raw::c_void, - __nmemb: size_t, - __size: size_t, - __compar: __compar_fn_t, - ) -> *mut ::std::os::raw::c_void; -} -extern "C" { - pub fn qsort( - __base: *mut ::std::os::raw::c_void, - __nmemb: size_t, - __size: size_t, - __compar: __compar_fn_t, - ); -} -extern "C" { - pub fn abs(__x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn labs(__x: ::std::os::raw::c_long) -> ::std::os::raw::c_long; -} -extern "C" { - pub fn llabs(__x: ::std::os::raw::c_longlong) -> ::std::os::raw::c_longlong; -} -extern "C" { - pub fn div( - __numer: ::std::os::raw::c_int, - __denom: ::std::os::raw::c_int, - ) -> div_t; -} -extern "C" { - pub fn ldiv( - __numer: ::std::os::raw::c_long, - __denom: ::std::os::raw::c_long, - ) -> ldiv_t; -} -extern "C" { - pub fn lldiv( - __numer: ::std::os::raw::c_longlong, - __denom: ::std::os::raw::c_longlong, - ) -> lldiv_t; -} -extern "C" { - pub fn ecvt( - __value: f64, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn fcvt( - __value: f64, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn gcvt( - __value: f64, - __ndigit: ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn qecvt( - __value: u128, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn qfcvt( - __value: u128, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn qgcvt( - __value: u128, - __ndigit: ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn ecvt_r( - __value: f64, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - __len: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn fcvt_r( - __value: f64, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - __len: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn qecvt_r( - __value: u128, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - __len: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn qfcvt_r( - __value: u128, - __ndigit: ::std::os::raw::c_int, - __decpt: *mut ::std::os::raw::c_int, - __sign: *mut ::std::os::raw::c_int, - __buf: *mut ::std::os::raw::c_char, - __len: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mblen( - __s: *const ::std::os::raw::c_char, - __n: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mbtowc( - __pwc: *mut wchar_t, - __s: *const ::std::os::raw::c_char, - __n: size_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn wctomb( - __s: *mut ::std::os::raw::c_char, - __wchar: wchar_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn mbstowcs( - __pwcs: *mut wchar_t, - __s: *const ::std::os::raw::c_char, - __n: size_t, - ) -> size_t; -} -extern "C" { - pub fn wcstombs( - __s: *mut ::std::os::raw::c_char, - __pwcs: *const wchar_t, - __n: size_t, - ) -> size_t; -} -extern "C" { - pub fn rpmatch(__response: *const ::std::os::raw::c_char) - -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getsubopt( - __optionp: *mut *mut ::std::os::raw::c_char, - __tokens: *const *mut ::std::os::raw::c_char, - __valuep: *mut *mut ::std::os::raw::c_char, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn getloadavg( - __loadavg: *mut f64, - __nelem: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -pub type int_least8_t = ::std::os::raw::c_schar; -pub type int_least16_t = ::std::os::raw::c_short; -pub type int_least32_t = ::std::os::raw::c_int; -pub type int_least64_t = ::std::os::raw::c_long; -pub type uint_least8_t = ::std::os::raw::c_uchar; -pub type uint_least16_t = ::std::os::raw::c_ushort; -pub type uint_least32_t = ::std::os::raw::c_uint; -pub type uint_least64_t = ::std::os::raw::c_ulong; -pub type int_fast8_t = ::std::os::raw::c_schar; -pub type int_fast16_t = ::std::os::raw::c_long; -pub type int_fast32_t = ::std::os::raw::c_long; -pub type int_fast64_t = ::std::os::raw::c_long; -pub type uint_fast8_t = ::std::os::raw::c_uchar; -pub type uint_fast16_t = ::std::os::raw::c_ulong; -pub type uint_fast32_t = ::std::os::raw::c_ulong; -pub type uint_fast64_t = ::std::os::raw::c_ulong; -pub type intmax_t = __intmax_t; -pub type uintmax_t = __uintmax_t; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_END: libpostal_token_type_t = 0; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_WORD: libpostal_token_type_t = 1; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_ABBREVIATION: - libpostal_token_type_t = 2; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_IDEOGRAPHIC_CHAR: - libpostal_token_type_t = 3; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_HANGUL_SYLLABLE: - libpostal_token_type_t = 4; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_ACRONYM: libpostal_token_type_t = - 5; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_PHRASE: libpostal_token_type_t = - 10; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_EMAIL: libpostal_token_type_t = - 20; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_URL: libpostal_token_type_t = 21; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_US_PHONE: - libpostal_token_type_t = 22; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_INTL_PHONE: - libpostal_token_type_t = 23; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_NUMERIC: libpostal_token_type_t = - 50; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_ORDINAL: libpostal_token_type_t = - 51; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_ROMAN_NUMERAL: - libpostal_token_type_t = 52; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_IDEOGRAPHIC_NUMBER: - libpostal_token_type_t = 53; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_PERIOD: libpostal_token_type_t = - 100; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_EXCLAMATION: - libpostal_token_type_t = 101; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_QUESTION_MARK: - libpostal_token_type_t = 102; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_COMMA: libpostal_token_type_t = - 103; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_COLON: libpostal_token_type_t = - 104; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_SEMICOLON: - libpostal_token_type_t = 105; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_PLUS: libpostal_token_type_t = - 106; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_AMPERSAND: - libpostal_token_type_t = 107; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_AT_SIGN: libpostal_token_type_t = - 108; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_POUND: libpostal_token_type_t = - 109; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_ELLIPSIS: - libpostal_token_type_t = 110; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_DASH: libpostal_token_type_t = - 111; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_BREAKING_DASH: - libpostal_token_type_t = 112; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_HYPHEN: libpostal_token_type_t = - 113; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_PUNCT_OPEN: - libpostal_token_type_t = 114; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_PUNCT_CLOSE: - libpostal_token_type_t = 115; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_DOUBLE_QUOTE: - libpostal_token_type_t = 119; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_SINGLE_QUOTE: - libpostal_token_type_t = 120; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_OPEN_QUOTE: - libpostal_token_type_t = 121; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_CLOSE_QUOTE: - libpostal_token_type_t = 122; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_SLASH: libpostal_token_type_t = - 124; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_BACKSLASH: - libpostal_token_type_t = 125; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_GREATER_THAN: - libpostal_token_type_t = 126; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_LESS_THAN: - libpostal_token_type_t = 127; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_OTHER: libpostal_token_type_t = - 200; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_WHITESPACE: - libpostal_token_type_t = 300; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_NEWLINE: libpostal_token_type_t = - 301; -pub const libpostal_token_type_t_LIBPOSTAL_TOKEN_TYPE_INVALID_CHAR: - libpostal_token_type_t = 500; -pub type libpostal_token_type_t = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_normalize_options { - pub languages: *mut *mut ::std::os::raw::c_char, - pub num_languages: size_t, - pub address_components: u16, - pub latin_ascii: bool, - pub transliterate: bool, - pub strip_accents: bool, - pub decompose: bool, - pub lowercase: bool, - pub trim_string: bool, - pub drop_parentheticals: bool, - pub replace_numeric_hyphens: bool, - pub delete_numeric_hyphens: bool, - pub split_alpha_from_numeric: bool, - pub replace_word_hyphens: bool, - pub delete_word_hyphens: bool, - pub delete_final_periods: bool, - pub delete_acronym_periods: bool, - pub drop_english_possessives: bool, - pub delete_apostrophes: bool, - pub expand_numex: bool, - pub roman_numerals: bool, -} -#[test] -fn bindgen_test_layout_libpostal_normalize_options() { - assert_eq!( - ::std::mem::size_of::(), - 40usize, - concat!("Size of: ", stringify!(libpostal_normalize_options)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(libpostal_normalize_options)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).languages - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).num_languages - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(num_languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).address_components - as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(address_components) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).latin_ascii - as *const _ as usize - }, - 18usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(latin_ascii) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).transliterate - as *const _ as usize - }, - 19usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(transliterate) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).strip_accents - as *const _ as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(strip_accents) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).decompose - as *const _ as usize - }, - 21usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(decompose) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).lowercase - as *const _ as usize - }, - 22usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(lowercase) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).trim_string - as *const _ as usize - }, - 23usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(trim_string) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).drop_parentheticals - as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(drop_parentheticals) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .replace_numeric_hyphens as *const _ as usize - }, - 25usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(replace_numeric_hyphens) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .delete_numeric_hyphens as *const _ as usize - }, - 26usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(delete_numeric_hyphens) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .split_alpha_from_numeric as *const _ as usize - }, - 27usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(split_alpha_from_numeric) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .replace_word_hyphens as *const _ as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(replace_word_hyphens) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).delete_word_hyphens - as *const _ as usize - }, - 29usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(delete_word_hyphens) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .delete_final_periods as *const _ as usize - }, - 30usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(delete_final_periods) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .delete_acronym_periods as *const _ as usize - }, - 31usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(delete_acronym_periods) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .drop_english_possessives as *const _ as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(drop_english_possessives) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).delete_apostrophes - as *const _ as usize - }, - 33usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(delete_apostrophes) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).expand_numex - as *const _ as usize - }, - 34usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(expand_numex) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).roman_numerals - as *const _ as usize - }, - 35usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalize_options), - "::", - stringify!(roman_numerals) - ) - ); -} -pub type libpostal_normalize_options_t = libpostal_normalize_options; -extern "C" { - pub fn libpostal_get_default_options() -> libpostal_normalize_options_t; -} -extern "C" { - pub fn libpostal_expand_address( - input: *mut ::std::os::raw::c_char, - options: libpostal_normalize_options_t, - n: *mut size_t, - ) -> *mut *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn libpostal_expand_address_root( - input: *mut ::std::os::raw::c_char, - options: libpostal_normalize_options_t, - n: *mut size_t, - ) -> *mut *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn libpostal_expansion_array_destroy( - expansions: *mut *mut ::std::os::raw::c_char, - n: size_t, - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_address_parser_response { - pub num_components: size_t, - pub components: *mut *mut ::std::os::raw::c_char, - pub labels: *mut *mut ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_libpostal_address_parser_response() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(libpostal_address_parser_response)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_address_parser_response) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .num_components as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_address_parser_response), - "::", - stringify!(num_components) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).components - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_address_parser_response), - "::", - stringify!(components) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).labels - as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_address_parser_response), - "::", - stringify!(labels) - ) - ); -} -pub type libpostal_address_parser_response_t = libpostal_address_parser_response; -pub type libpostal_parsed_address_components_t = libpostal_address_parser_response_t; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_address_parser_options { - pub language: *mut ::std::os::raw::c_char, - pub country: *mut ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_libpostal_address_parser_options() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(libpostal_address_parser_options)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_address_parser_options) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).language - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_address_parser_options), - "::", - stringify!(language) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).country - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_address_parser_options), - "::", - stringify!(country) - ) - ); -} -pub type libpostal_address_parser_options_t = libpostal_address_parser_options; -extern "C" { - pub fn libpostal_address_parser_response_destroy( - self_: *mut libpostal_address_parser_response_t, - ); -} -extern "C" { - pub fn libpostal_get_address_parser_default_options( - ) -> libpostal_address_parser_options_t; -} -extern "C" { - pub fn libpostal_parse_address( - address: *mut ::std::os::raw::c_char, - options: libpostal_address_parser_options_t, - ) -> *mut libpostal_address_parser_response_t; -} -extern "C" { - pub fn libpostal_parser_print_features(print_features: bool) -> bool; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_language_classifier_response { - pub num_languages: size_t, - pub languages: *mut *mut ::std::os::raw::c_char, - pub probs: *mut f64, -} -#[test] -fn bindgen_test_layout_libpostal_language_classifier_response() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!( - "Size of: ", - stringify!(libpostal_language_classifier_response) - ) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_language_classifier_response) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .num_languages as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_language_classifier_response), - "::", - stringify!(num_languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .languages as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_language_classifier_response), - "::", - stringify!(languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).probs - as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_language_classifier_response), - "::", - stringify!(probs) - ) - ); -} -pub type libpostal_language_classifier_response_t = - libpostal_language_classifier_response; -extern "C" { - pub fn libpostal_classify_language( - address: *mut ::std::os::raw::c_char, - ) -> *mut libpostal_language_classifier_response_t; -} -extern "C" { - pub fn libpostal_language_classifier_response_destroy( - self_: *mut libpostal_language_classifier_response_t, - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_near_dupe_hash_options { - pub with_name: bool, - pub with_address: bool, - pub with_unit: bool, - pub with_city_or_equivalent: bool, - pub with_small_containing_boundaries: bool, - pub with_postal_code: bool, - pub with_latlon: bool, - pub latitude: f64, - pub longitude: f64, - pub geohash_precision: u32, - pub name_and_address_keys: bool, - pub name_only_keys: bool, - pub address_only_keys: bool, -} -#[test] -fn bindgen_test_layout_libpostal_near_dupe_hash_options() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(libpostal_near_dupe_hash_options)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_near_dupe_hash_options) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).with_name - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_name) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).with_address - as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_address) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).with_unit - as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_unit) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .with_city_or_equivalent as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_city_or_equivalent) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .with_small_containing_boundaries as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_small_containing_boundaries) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .with_postal_code as *const _ as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_postal_code) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).with_latlon - as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(with_latlon) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).latitude - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(latitude) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).longitude - as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(longitude) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .geohash_precision as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(geohash_precision) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .name_and_address_keys as *const _ as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(name_and_address_keys) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).name_only_keys - as *const _ as usize - }, - 29usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(name_only_keys) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .address_only_keys as *const _ as usize - }, - 30usize, - concat!( - "Offset of field: ", - stringify!(libpostal_near_dupe_hash_options), - "::", - stringify!(address_only_keys) - ) - ); -} -pub type libpostal_near_dupe_hash_options_t = libpostal_near_dupe_hash_options; -extern "C" { - pub fn libpostal_get_near_dupe_hash_default_options( - ) -> libpostal_near_dupe_hash_options_t; -} -extern "C" { - pub fn libpostal_near_dupe_hashes( - num_components: size_t, - labels: *mut *mut ::std::os::raw::c_char, - values: *mut *mut ::std::os::raw::c_char, - options: libpostal_near_dupe_hash_options_t, - num_hashes: *mut size_t, - ) -> *mut *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn libpostal_near_dupe_hashes_languages( - num_components: size_t, - labels: *mut *mut ::std::os::raw::c_char, - values: *mut *mut ::std::os::raw::c_char, - options: libpostal_near_dupe_hash_options_t, - num_languages: size_t, - languages: *mut *mut ::std::os::raw::c_char, - num_hashes: *mut size_t, - ) -> *mut *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn libpostal_place_languages( - num_components: size_t, - labels: *mut *mut ::std::os::raw::c_char, - values: *mut *mut ::std::os::raw::c_char, - num_languages: *mut size_t, - ) -> *mut *mut ::std::os::raw::c_char; -} -pub const libpostal_duplicate_status_t_LIBPOSTAL_NULL_DUPLICATE_STATUS: - libpostal_duplicate_status_t = -1; -pub const libpostal_duplicate_status_t_LIBPOSTAL_NON_DUPLICATE: - libpostal_duplicate_status_t = 0; -pub const libpostal_duplicate_status_t_LIBPOSTAL_POSSIBLE_DUPLICATE_NEEDS_REVIEW: - libpostal_duplicate_status_t = 3; -pub const libpostal_duplicate_status_t_LIBPOSTAL_LIKELY_DUPLICATE: - libpostal_duplicate_status_t = 6; -pub const libpostal_duplicate_status_t_LIBPOSTAL_EXACT_DUPLICATE: - libpostal_duplicate_status_t = 9; -pub type libpostal_duplicate_status_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_duplicate_options { - pub num_languages: size_t, - pub languages: *mut *mut ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_libpostal_duplicate_options() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(libpostal_duplicate_options)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(libpostal_duplicate_options)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).num_languages - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_duplicate_options), - "::", - stringify!(num_languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).languages - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_duplicate_options), - "::", - stringify!(languages) - ) - ); -} -pub type libpostal_duplicate_options_t = libpostal_duplicate_options; -extern "C" { - pub fn libpostal_get_default_duplicate_options() -> libpostal_duplicate_options_t; -} -extern "C" { - pub fn libpostal_get_duplicate_options_with_languages( - num_languages: size_t, - languages: *mut *mut ::std::os::raw::c_char, - ) -> libpostal_duplicate_options_t; -} -extern "C" { - pub fn libpostal_is_name_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_street_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_house_number_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_po_box_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_unit_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_floor_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_postal_code_duplicate( - value1: *mut ::std::os::raw::c_char, - value2: *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_toponym_duplicate( - num_components1: size_t, - labels1: *mut *mut ::std::os::raw::c_char, - values1: *mut *mut ::std::os::raw::c_char, - num_components2: size_t, - labels2: *mut *mut ::std::os::raw::c_char, - values2: *mut *mut ::std::os::raw::c_char, - options: libpostal_duplicate_options_t, - ) -> libpostal_duplicate_status_t; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_fuzzy_duplicate_options { - pub num_languages: size_t, - pub languages: *mut *mut ::std::os::raw::c_char, - pub needs_review_threshold: f64, - pub likely_dupe_threshold: f64, -} -#[test] -fn bindgen_test_layout_libpostal_fuzzy_duplicate_options() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(libpostal_fuzzy_duplicate_options)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_fuzzy_duplicate_options) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).num_languages - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_options), - "::", - stringify!(num_languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).languages - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_options), - "::", - stringify!(languages) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .needs_review_threshold as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_options), - "::", - stringify!(needs_review_threshold) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())) - .likely_dupe_threshold as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_options), - "::", - stringify!(likely_dupe_threshold) - ) - ); -} -pub type libpostal_fuzzy_duplicate_options_t = libpostal_fuzzy_duplicate_options; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_fuzzy_duplicate_status { - pub status: libpostal_duplicate_status_t, - pub similarity: f64, -} -#[test] -fn bindgen_test_layout_libpostal_fuzzy_duplicate_status() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(libpostal_fuzzy_duplicate_status)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(libpostal_fuzzy_duplicate_status) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).status - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_status), - "::", - stringify!(status) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).similarity - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_fuzzy_duplicate_status), - "::", - stringify!(similarity) - ) - ); -} -pub type libpostal_fuzzy_duplicate_status_t = libpostal_fuzzy_duplicate_status; -extern "C" { - pub fn libpostal_get_default_fuzzy_duplicate_options( - ) -> libpostal_fuzzy_duplicate_options_t; -} -extern "C" { - pub fn libpostal_get_default_fuzzy_duplicate_options_with_languages( - num_languages: size_t, - languages: *mut *mut ::std::os::raw::c_char, - ) -> libpostal_fuzzy_duplicate_options_t; -} -extern "C" { - pub fn libpostal_is_name_duplicate_fuzzy( - num_tokens1: size_t, - tokens1: *mut *mut ::std::os::raw::c_char, - token_scores1: *mut f64, - num_tokens2: size_t, - tokens2: *mut *mut ::std::os::raw::c_char, - token_scores2: *mut f64, - options: libpostal_fuzzy_duplicate_options_t, - ) -> libpostal_fuzzy_duplicate_status_t; -} -extern "C" { - pub fn libpostal_is_street_duplicate_fuzzy( - num_tokens1: size_t, - tokens1: *mut *mut ::std::os::raw::c_char, - token_scores1: *mut f64, - num_tokens2: size_t, - tokens2: *mut *mut ::std::os::raw::c_char, - token_scores2: *mut f64, - options: libpostal_fuzzy_duplicate_options_t, - ) -> libpostal_fuzzy_duplicate_status_t; -} -extern "C" { - pub fn libpostal_setup() -> bool; -} -extern "C" { - pub fn libpostal_setup_datadir(datadir: *mut ::std::os::raw::c_char) -> bool; -} -extern "C" { - pub fn libpostal_teardown(); -} -extern "C" { - pub fn libpostal_setup_parser() -> bool; -} -extern "C" { - pub fn libpostal_setup_parser_datadir( - datadir: *mut ::std::os::raw::c_char, - ) -> bool; -} -extern "C" { - pub fn libpostal_teardown_parser(); -} -extern "C" { - pub fn libpostal_setup_language_classifier() -> bool; -} -extern "C" { - pub fn libpostal_setup_language_classifier_datadir( - datadir: *mut ::std::os::raw::c_char, - ) -> bool; -} -extern "C" { - pub fn libpostal_teardown_language_classifier(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_token { - pub offset: size_t, - pub len: size_t, - pub type_: u16, -} -#[test] -fn bindgen_test_layout_libpostal_token() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(libpostal_token)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(libpostal_token)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).offset as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_token), - "::", - stringify!(offset) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).len as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_token), - "::", - stringify!(len) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).type_ as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libpostal_token), - "::", - stringify!(type_) - ) - ); -} -pub type libpostal_token_t = libpostal_token; -extern "C" { - pub fn libpostal_tokenize( - input: *mut ::std::os::raw::c_char, - whitespace: bool, - n: *mut size_t, - ) -> *mut libpostal_token_t; -} -extern "C" { - pub fn libpostal_normalize_string_languages( - input: *mut ::std::os::raw::c_char, - options: u64, - num_languages: size_t, - languages: *mut *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn libpostal_normalize_string( - input: *mut ::std::os::raw::c_char, - options: u64, - ) -> *mut ::std::os::raw::c_char; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libpostal_normalized_token { - pub str_: *mut ::std::os::raw::c_char, - pub token: libpostal_token_t, -} -#[test] -fn bindgen_test_layout_libpostal_normalized_token() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(libpostal_normalized_token)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(libpostal_normalized_token)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).str_ as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalized_token), - "::", - stringify!(str_) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::())).token as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libpostal_normalized_token), - "::", - stringify!(token) - ) - ); -} -pub type libpostal_normalized_token_t = libpostal_normalized_token; -extern "C" { - pub fn libpostal_normalized_tokens( - input: *mut ::std::os::raw::c_char, - string_options: u64, - token_options: u64, - whitespace: bool, - n: *mut size_t, - ) -> *mut libpostal_normalized_token_t; -} -extern "C" { - pub fn libpostal_normalized_tokens_languages( - input: *mut ::std::os::raw::c_char, - string_options: u64, - token_options: u64, - whitespace: bool, - num_languages: size_t, - languages: *mut *mut ::std::os::raw::c_char, - n: *mut size_t, - ) -> *mut libpostal_normalized_token_t; -} -pub type __builtin_va_list = [__va_list_tag; 1usize]; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __va_list_tag { - pub gp_offset: ::std::os::raw::c_uint, - pub fp_offset: ::std::os::raw::c_uint, - pub overflow_arg_area: *mut ::std::os::raw::c_void, - pub reg_save_area: *mut ::std::os::raw::c_void, -} -#[test] -fn bindgen_test_layout___va_list_tag() { - assert_eq!( - ::std::mem::size_of::<__va_list_tag>(), - 24usize, - concat!("Size of: ", stringify!(__va_list_tag)) - ); - assert_eq!( - ::std::mem::align_of::<__va_list_tag>(), - 8usize, - concat!("Alignment of ", stringify!(__va_list_tag)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__va_list_tag>())).gp_offset as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__va_list_tag), - "::", - stringify!(gp_offset) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__va_list_tag>())).fp_offset as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(__va_list_tag), - "::", - stringify!(fp_offset) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__va_list_tag>())).overflow_arg_area as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__va_list_tag), - "::", - stringify!(overflow_arg_area) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<__va_list_tag>())).reg_save_area as *const _ - as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(__va_list_tag), - "::", - stringify!(reg_save_area) - ) - ); -} diff --git a/crates/libpostal-sys/src/lib.rs b/crates/libpostal-sys/src/lib.rs index 765b131..68335b1 100644 --- a/crates/libpostal-sys/src/lib.rs +++ b/crates/libpostal-sys/src/lib.rs @@ -6,6 +6,10 @@ // Ignore test-only warnings caused by // https://github.com/rust-lang/rust-bindgen/issues/1651. #![cfg_attr(test, allow(deref_nullptr))] +// Allow clippy warnings in generated bindgen code +#![allow(clippy::missing_safety_doc)] +#![allow(clippy::ptr_offset_with_cast)] +#![allow(clippy::useless_transmute)] use std::sync::{Arc, Mutex}; @@ -39,15 +43,8 @@ lazy_static! { })); } -// We could use build.rs to automatically generate these bindings, then include -//them like this. include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -// Assume our bindings were generated using: -// -// bindgen wrapper.h -o src/bindings.rs -// -// See the README.md file. -include!("bindings.rs"); +// Use build.rs to automatically generate these bindings +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); #[cfg(test)] mod tests { @@ -97,7 +94,7 @@ mod tests { CString::new("Quatre-vingt-douze Ave des Champs-ƉlysĆ©es") .expect("CString::new failed"); let normalization_options = libpostal_get_default_options(); - let mut num_expansions: size_t = 0; + let mut num_expansions: usize = 0; let expansions = libpostal_expand_address( street_address.as_ptr() as *mut _, normalization_options, diff --git a/crates/metrics-exporter-newrelic/Cargo.toml b/crates/metrics-exporter-newrelic/Cargo.toml index 02bcb7a..20657db 100644 --- a/crates/metrics-exporter-newrelic/Cargo.toml +++ b/crates/metrics-exporter-newrelic/Cargo.toml @@ -13,8 +13,8 @@ documentation = "https://docs.rs/metrics-exporter-newrelic" [dependencies] http = "0.2.6" -metrics = "0.20.1" -metrics-util = "0.14.0" +metrics = "0.24.2" +metrics-util = "0.20.0" reqwest = { version = "0.11.9", default-features = false, features = ["json", "rustls-tls"] } serde = "1.0.136" serde_derive = "1.0.136" diff --git a/crates/metrics-exporter-newrelic/src/errors.rs b/crates/metrics-exporter-newrelic/src/errors.rs index 354d0c8..e0be3e4 100644 --- a/crates/metrics-exporter-newrelic/src/errors.rs +++ b/crates/metrics-exporter-newrelic/src/errors.rs @@ -3,6 +3,8 @@ use metrics::SetRecorderError; use thiserror::Error; +use crate::NewRelicRecorder; + /// An error occurred building or installing our metrics recorder. #[derive(Debug, Error)] #[non_exhaustive] @@ -11,7 +13,7 @@ pub enum BuildError { #[non_exhaustive] SetRecorderError { #[from] - source: SetRecorderError, + source: SetRecorderError, }, } diff --git a/crates/metrics-exporter-newrelic/src/lib.rs b/crates/metrics-exporter-newrelic/src/lib.rs index 9aceb25..1c0402f 100644 --- a/crates/metrics-exporter-newrelic/src/lib.rs +++ b/crates/metrics-exporter-newrelic/src/lib.rs @@ -287,7 +287,7 @@ impl NewRelicRecorder { /// Install this recorder as the global default recorder. pub fn install(self) -> Result { let handle = self.handle(); - metrics::set_boxed_recorder(Box::new(self))?; + metrics::set_global_recorder(self)?; Ok(handle) } } @@ -320,19 +320,27 @@ impl Recorder for NewRelicRecorder { // NewRelic does not use this information. } - fn register_counter(&self, key: &Key) -> Counter { + fn register_counter( + &self, + key: &Key, + _metadata: &metrics::Metadata<'_>, + ) -> Counter { self.inner .registry .get_or_create_counter(key, |c| c.clone().into()) } - fn register_gauge(&self, key: &Key) -> Gauge { + fn register_gauge(&self, key: &Key, _metadata: &metrics::Metadata<'_>) -> Gauge { self.inner .registry .get_or_create_gauge(key, |c| c.clone().into()) } - fn register_histogram(&self, key: &Key) -> Histogram { + fn register_histogram( + &self, + key: &Key, + _metadata: &metrics::Metadata<'_>, + ) -> Histogram { self.inner .registry .get_or_create_histogram(key, |c| c.clone().into()) diff --git a/crates/opinionated_metrics/Cargo.toml b/crates/opinionated_metrics/Cargo.toml index a3215a3..b51ee22 100644 --- a/crates/opinionated_metrics/Cargo.toml +++ b/crates/opinionated_metrics/Cargo.toml @@ -12,9 +12,9 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://docs.rs/opinionated_metrics" [dependencies] -metrics = "0.20.1" +metrics = "0.24.2" metrics-exporter-newrelic = { version = "0.2.0", path = "../metrics-exporter-newrelic" } # We'll add back Prometheus features like http-listener as we support them. -metrics-exporter-prometheus = { version = "0.11.0", default-features = false } +metrics-exporter-prometheus = { version = "0.17.2", default-features = false } thiserror = "1.0.30" tracing = "0.1.29" \ No newline at end of file diff --git a/deny.toml b/deny.toml index cf1dcac..9b1b321 100644 --- a/deny.toml +++ b/deny.toml @@ -3,15 +3,11 @@ # These policies can be enforced using `cargo deny check`. [advisories] +version = 2 ignore = [] [licenses] -# Don't allow code with an unclear license. -unlicensed = "deny" - -# Don't allow "copylefted" licenses unless they're listed below. -copyleft = "deny" - +version = 2 # Allow common non-restrictive licenses. allow = [ "MIT", @@ -22,13 +18,10 @@ allow = [ "ISC", "MPL-2.0", "OpenSSL", - "Unicode-DFS-2016", + "Unicode-3.0", + "Zlib" ] -# Many organizations ban AGPL-licensed code -# https://opensource.google/docs/using/agpl-policy/ -deny = ["AGPL-3.0"] - [[licenses.clarify]] # Ring has a messy license. We should either commit 100% to ring everywhere, or # to native-tls everywhere, and not mix the two. @@ -53,10 +46,10 @@ deny = [ { name = "serde_derive", version = ">1.0.171,<1.0.184" }, ] -skip = [ - # This seems to be included by portable-atomic 0.3.20 for some reason. - { name = "portable-atomic", version = "1.6.0" }, -] +#skip = [ +# # This seems to be included by portable-atomic 0.3.20 for some reason. +# { name = "portable-atomic", version = "1.6.0" }, +#] skip-tree = [ # This has a bunch of old dependencies. diff --git a/src/geocoders/cache/compression.rs b/src/geocoders/cache/compression.rs index c4743d8..16fcdf9 100644 --- a/src/geocoders/cache/compression.rs +++ b/src/geocoders/cache/compression.rs @@ -44,17 +44,21 @@ impl CacheCompressor { /// Compress `input` and append to `output`. pub fn compress(&self, input: &[u8], output: &mut Vec) -> Result<()> { - counter!("geocodecsv.compressor_input.bytes_total", input.len() as u64, "compressor" => "none"); + counter!("geocodecsv.compressor_input.bytes_total", "compressor" => "none") + .increment(input.len() as u64); output.extend_from_slice(input); - counter!("geocodecsv.compressor_output.bytes_total", output.len() as u64, "compressor" => "none"); + counter!("geocodecsv.compressor_output.bytes_total", "compressor" => "none") + .increment(output.len() as u64); Ok(()) } /// Decompress `input` and store in `output`. pub fn decompress(&self, input: &[u8], output: &mut Vec) -> Result<()> { - counter!("geocodecsv.decompressor_input.bytes_total", input.len() as u64, "compressor" => "none"); + counter!("geocodecsv.decompressor_input.bytes_total", "compressor" => "none") + .increment(input.len() as u64); output.extend_from_slice(input); - counter!("geocodecsv.decompressor_output.bytes_total", output.len() as u64, "compressor" => "none"); + counter!("geocodecsv.decompressor_output.bytes_total", "compressor" => "none") + .increment(output.len() as u64); Ok(()) } } diff --git a/src/geocoders/cache/mod.rs b/src/geocoders/cache/mod.rs index a2af9a6..b31fc65 100644 --- a/src/geocoders/cache/mod.rs +++ b/src/geocoders/cache/mod.rs @@ -167,25 +167,16 @@ impl Geocoder for Cache { // miss. cache_misses.push(addresses[i].clone()); cache_miss_offsets.push(i); - counter!( - "geocodecsv.cache_hits.total", - 1, - "geocoding_result" => "invalid_data" - ); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "invalid_data") + .increment(1); } else { geocoded[i] = Some(candidate); - counter!( - "geocodecsv.cache_hits.total", - 1, - "geocoding_result" => "found" - ); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "found") + .increment(1); } } else { - counter!( - "geocodecsv.cache_hits.total", - 1, - "geocoding_result" => "unknown_address" - ); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "unknown_address") + .increment(1); } } else { // We need to forward this result. @@ -193,7 +184,7 @@ impl Geocoder for Cache { cache_miss_offsets.push(i); } } - counter!("geocodecsv.cache_misses.total", cache_misses.len() as u64); + counter!("geocodecsv.cache_misses.total").increment(cache_misses.len() as u64); drop(cache_results); // If we have any cache misses, deal with them. diff --git a/src/geocoders/invalid_record_skipper.rs b/src/geocoders/invalid_record_skipper.rs index 9cfd138..44dcf9a 100644 --- a/src/geocoders/invalid_record_skipper.rs +++ b/src/geocoders/invalid_record_skipper.rs @@ -54,7 +54,7 @@ impl Geocoder for InvalidRecordSkipper { valid_addresses.push(address.clone()); original_indices.push(i); } else { - counter!("geocodecsv.invalid_records.total", 1); + counter!("geocodecsv.invalid_records.total").increment(1); } } diff --git a/src/geocoders/libpostal.rs b/src/geocoders/libpostal.rs index fa998c5..afc1450 100644 --- a/src/geocoders/libpostal.rs +++ b/src/geocoders/libpostal.rs @@ -127,7 +127,8 @@ impl Geocoder for LibPostal { debug_assert_eq!(geocoded.column_values.len(), self.column_names().len()); result.push(Some(geocoded)); } - counter!("geocodecsv.addresses_parsed.total", result.len() as u64, "parser" => "libpostal"); + counter!("geocodecsv.addresses_parsed.total", "parser" => "libpostal") + .increment(result.len() as u64); Ok(result) } } diff --git a/src/geocoders/mod.rs b/src/geocoders/mod.rs index 23540c0..394b58d 100644 --- a/src/geocoders/mod.rs +++ b/src/geocoders/mod.rs @@ -1,6 +1,6 @@ //! Geocoding backends. -use std::{fmt, iter::repeat, str::FromStr, sync::Arc}; +use std::{fmt, str::FromStr, sync::Arc}; use anyhow::format_err; use async_trait::async_trait; @@ -177,6 +177,6 @@ pub trait Geocoder: Send + Sync + 'static { /// Copy empty values into `geocoded`, one for each column that this /// geocoder would produce. fn add_empty_columns_to_row(&self, out_row: &mut StringRecord) { - out_row.extend(repeat("").take(self.column_names().len())); + out_row.extend(std::iter::repeat_n("", self.column_names().len())); } } diff --git a/src/geocoders/normalizer.rs b/src/geocoders/normalizer.rs index be6241e..2ec7dd7 100644 --- a/src/geocoders/normalizer.rs +++ b/src/geocoders/normalizer.rs @@ -84,11 +84,8 @@ impl Geocoder for Normalizer { if !normalized_address.eq_ignore_ascii_case(&addresses[i]) { // Only count addresses that we've actually changed in // some way. - counter!( - "geocodecsv.addresses_normalized.total", - 1, - "normalizer" => "libpostal" - ); + counter!("geocodecsv.addresses_normalized.total", "normalizer" => "libpostal") + .increment(1); trace!( "normalized {:?} to {:?}", &addresses[i], diff --git a/src/geocoders/smarty/client.rs b/src/geocoders/smarty/client.rs index ea00000..825168f 100644 --- a/src/geocoders/smarty/client.rs +++ b/src/geocoders/smarty/client.rs @@ -137,7 +137,7 @@ async fn street_addresses_impl( // Errors that occur here are being reported by our local HTTP // stack, not the remote server. let desc = hyper_error_description_for_metrics(&err); - counter!("geocodecsv.selected_errors.count", 1, "component" => "smarty", "cause" => desc); + counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => desc).increment(1); return Err(err.into()); } }; @@ -149,10 +149,8 @@ async fn street_addresses_impl( body_data.extend(&chunk[..]); } - histogram!( - "geocodecsv.smarty.geocode_request.duration_seconds", - (Instant::now() - start).as_secs_f64(), - ); + histogram!("geocodecsv.smarty.geocode_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); // Check the request status. if status.is_success() { @@ -162,7 +160,7 @@ async fn street_addresses_impl( // This error was reported by the remote server. // Add error to metrics. - counter!("geocodecsv.selected_errors.count", 1, "component" => "smarty", "cause" => status.to_string()); + counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => status.to_string()).increment(1); // Log information about bad street fields, if we can. if status == 422 { diff --git a/src/geocoders/smarty/mod.rs b/src/geocoders/smarty/mod.rs index 9f6c992..083ddc5 100644 --- a/src/geocoders/smarty/mod.rs +++ b/src/geocoders/smarty/mod.rs @@ -117,8 +117,8 @@ impl Geocoder for Smarty { .await?; let hits = response.iter().filter(|g| g.is_some()).count(); - counter!("geocodecsv.addresses_geocoded.total", hits as u64, "geocoder" => "smarty", "geocode_result" => "found"); - counter!("geocodecsv.addresses_geocoded.total", (addresses.len() - hits) as u64, "geocoder" => "smarty", "geocode_result" => "unknown_address"); + counter!("geocodecsv.addresses_geocoded.total", "geocoder" => "smarty", "geocode_result" => "found").increment(hits as u64); + counter!("geocodecsv.addresses_geocoded.total", "geocoder" => "smarty", "geocode_result" => "unknown_address").increment((addresses.len() - hits) as u64); // Response with only the addresses that actually geocoded successfully. // We need make sure we map outputs back to their original positions. diff --git a/src/key_value_stores/bigtable.rs b/src/key_value_stores/bigtable.rs index 6050843..07be6ef 100644 --- a/src/key_value_stores/bigtable.rs +++ b/src/key_value_stores/bigtable.rs @@ -236,7 +236,7 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { Ok(response) => response, Err(err) => { let cause = bigtable_error_cause_for_metrics(&err); - counter!("geocodecsv.selected_errors.count", 1, "component" => "bigtable", "cause" => cause); + counter!("geocodecsv.selected_errors.count", "component" => "bigtable", "cause" => cause).increment(1); return Err(err).context("error checking BigTable for cached values"); } }; @@ -253,10 +253,8 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { ); } - histogram!( - "geocodecsv.bigtable.get_request.duration_seconds", - (Instant::now() - start).as_secs_f64(), - ); + histogram!("geocodecsv.bigtable.get_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); // Build a vec to store our result, and a `HashMap` mapping keys to vec // indices. We have to be careful because keys might appear more than @@ -325,9 +323,9 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { if should_evict { counter!( - "geocodecsv.bigtable.random_eviction.evicted_entries.total", - 1 - ); + "geocodecsv.bigtable.random_eviction.evicted_entries.total" + ) + .increment(1); trace!( "evicting cache entry for key {:?}, age: {} seconds", String::from_utf8_lossy(&key), @@ -351,7 +349,7 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { let age_seconds = age_micros / 1_000_000; if age_seconds >= config.min_age_seconds as i64 { - counter!("geocodecsv.bigtable.random_eviction.eligible_entries.total", 1); + counter!("geocodecsv.bigtable.random_eviction.eligible_entries.total").increment(1); } } @@ -402,18 +400,17 @@ impl<'store> PipelinedSet<'store> for BigTablePipelinedSet<'store> { let request = MutateRowsRequest { table_name: client.get_full_table_name(&self.bigtable.table_name), app_profile_id: "".to_owned(), // Dave says this is what we want. + authorized_view_name: "".to_owned(), entries: self.entries.clone(), }; if let Err(err) = client.mutate_rows(request).await { let cause = bigtable_error_cause_for_metrics(&err); - counter!("geocodecsv.selected_errors.count", 1, "component" => "bigtable", "cause" => cause); + counter!("geocodecsv.selected_errors.count", "component" => "bigtable", "cause" => cause).increment(1); return Err(err).context("error writing cached values to BigTable"); } - histogram!( - "geocodecsv.bigtable.set_request.duration_seconds", - (Instant::now() - start).as_secs_f64(), - ); + histogram!("geocodecsv.bigtable.set_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); Ok(()) } } @@ -438,5 +435,6 @@ fn bigtable_error_cause_for_metrics(err: &bigtable::Error) -> Cow<'static, str> bigtable::Error::TimeoutError(_) => Cow::Borrowed("timeout"), bigtable::Error::ChunkError(_) => Cow::Borrowed("chunk"), bigtable::Error::GCPAuthError(_) => Cow::Borrowed("gcp auth"), + bigtable::Error::MetadataError(_) => Cow::Borrowed("metadata error"), } } diff --git a/src/key_value_stores/mod.rs b/src/key_value_stores/mod.rs index beeb4dd..4343ac8 100644 --- a/src/key_value_stores/mod.rs +++ b/src/key_value_stores/mod.rs @@ -36,6 +36,7 @@ pub trait KeyValueStore: Send + Sync + 'static { impl dyn KeyValueStore { /// Create an appropriate `KeyValueStore` instance based on `url`. + #[allow(dead_code)] pub async fn new_from_url( url: Url, key_prefix: String, diff --git a/src/key_value_stores/redis.rs b/src/key_value_stores/redis.rs index ffd9855..95f3c6e 100644 --- a/src/key_value_stores/redis.rs +++ b/src/key_value_stores/redis.rs @@ -104,10 +104,8 @@ impl<'store> PipelinedGet<'store> for RedisPipelinedGet<'store> { .await .context("could not fetch keys from Redis")?; - histogram!( - "geocodecsv.redis.get_request.duration_seconds", - (Instant::now() - start).as_secs_f64(), - ); + histogram!("geocodecsv.redis.get_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); Ok(result) } @@ -137,10 +135,8 @@ impl<'store> PipelinedSet<'store> for RedisPipelinedSet<'store> { .await .context("could not fetch keys from Redis")?; - histogram!( - "geocodecsv.redis.set_request.duration_seconds", - (Instant::now() - start).as_secs_f64(), - ); + histogram!("geocodecsv.redis.set_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); Ok(result) } diff --git a/src/main.rs b/src/main.rs index dfe3ecb..2d90dad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use clap::{Parser, Subcommand, ValueEnum}; use leaky_bucket::RateLimiter; use metrics::describe_counter; use opinionated_metrics::Mode; + use std::cmp::max; use std::path::PathBuf; use std::str::FromStr; @@ -191,6 +192,11 @@ enum Command { // with an error. #[tokio::main] async fn main() -> Result<()> { + // Initialize rustls crypto provider before any TLS operations. + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .map_err(|_| anyhow::anyhow!("Failed to install rustls crypto provider"))?; + // Configure tracing. let filter = EnvFilter::from_default_env(); Subscriber::builder() diff --git a/src/pipeline.rs b/src/pipeline.rs index e614bee..52812e8 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -447,21 +447,21 @@ pub async fn geocode_chunk( retry_wait.as_secs(), err ); - counter!("geocodecsv.chunks_retried.total", 1); + counter!("geocodecsv.chunks_retried.total").increment(1); sleep(retry_wait); retry_wait *= 2; } Err(err) => { - counter!("geocodecsv.chunks_failed.total", 1); + counter!("geocodecsv.chunks_failed.total").increment(1); return Err(err).context("geocoder error"); } Ok(geocoded) => { - counter!("geocodecsv.chunks.total", 1); + counter!("geocodecsv.chunks.total").increment(1); break geocoded; } } }; - counter!("geocodecsv.addresses.total", addresses_len as u64); + counter!("geocodecsv.addresses.total").increment(addresses_len as u64); trace!("geocoded {} addresses", addresses_len); // Add address information to our output rows. diff --git a/tests/bigtable_eviction.rs b/tests/bigtable_eviction.rs index 7f4243f..0634029 100644 --- a/tests/bigtable_eviction.rs +++ b/tests/bigtable_eviction.rs @@ -164,6 +164,7 @@ impl MetricsData { struct GeocodingAnalysis { total_rows: usize, rows_with_gc_data: usize, + #[allow(dead_code)] raw_output: String, } From 8cc74011b1d6d34135c7a04855ab24651adb337b Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 12:41:29 -0400 Subject: [PATCH 04/16] new ci --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd81472..ca2cb3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,13 +26,13 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Extract release version id: extract_release_version run: | release_version="$(echo '${{ github.ref }}' | sed 's,^.*/\([^/]*\)$,\1,; s,^v,,' )" echo Release version: $release_version - echo "::set-output name=release_version::$release_version" + echo "release_version=$release_version" >> $GITHUB_OUTPUT - name: Extract release body from CHANGELOG.md id: extract_release_body if: ${{ startsWith(github.ref, 'refs/tags/v') }} @@ -49,12 +49,12 @@ jobs: - name: "Make release" id: create_release if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/create-release@v1 + uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} - release_name: "${{ steps.extract_release_version.outputs.release_version }}" + name: "${{ steps.extract_release_version.outputs.release_version }}" body_path: RELEASE_BODY.md # We use a matrix to run our build on every supported platform. @@ -88,24 +88,36 @@ jobs: steps: # See https://github.com/r-lib/actions/issues/243 - - name: Install automake + - name: Install automake and libpostal (macOS) if: runner.os == 'macOS' run: | - brew install automake - - uses: abelfodil/protoc-action@v1 + brew install automake libpostal + - name: Install libpostal (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y curl autotools-dev autoconf libtool pkg-config libicu-dev + # Install libpostal from source since it's not in apt + git clone https://github.com/openvenues/libpostal + cd libpostal + ./bootstrap.sh + ./configure + make -j4 + sudo make install + sudo ldconfig + - uses: arduino/setup-protoc@v3 with: - protoc-version: "3.0.0" + version: "25.1" - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - profile: minimal # We track latest stable Rust instead of hardcoding it because it # virtually never breaks old code. toolchain: stable - components: rustfmt, clippy - target: ${{ matrix.target }} + components: rustfmt, clippy, rust-src + targets: ${{ matrix.target }} # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive - name: Install Just @@ -118,7 +130,7 @@ jobs: rm -rf $basename.tar.gz - name: Install cargo-deny run: | - version=0.14.20 + version=0.16.1 basename=cargo-deny-$version-${{ matrix.host }} curl -fLO https://github.com/EmbarkStudios/cargo-deny/releases/download/$version/$basename.tar.gz tar xf $basename.tar.gz @@ -151,14 +163,11 @@ jobs: run: | release_file=geocode-csv_${{ needs.create_release.outputs.release_version }}_${{ matrix.target }}.zip zip -j $release_file target/${{ matrix.target }}/release/geocode-csv - echo "::set-output name=release_file::$release_file" + echo "release_file=$release_file" >> $GITHUB_OUTPUT - name: Upload Release Asset if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/upload-release-asset@v1 + uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ needs.create_release.outputs.upload_url }} - asset_path: ./${{ steps.build_release.outputs.release_file }} - asset_name: ${{ steps.build_release.outputs.release_file }} - asset_content_type: application/zip + files: ./${{ steps.build_release.outputs.release_file }} From 6c6b88e4cc1d4210d9ff22ed4e779832eca4c28e Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 12:47:50 -0400 Subject: [PATCH 05/16] get rid of mac for now --- .github/workflows/ci.yml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca2cb3d..35481b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,25 +75,11 @@ jobs: host: x86_64-unknown-linux-musl cargo: cross os: ubuntu-latest - - target: x86_64-apple-darwin - host: x86_64-apple-darwin - cargo: cargo - os: macos-latest - - target: aarch64-apple-darwin - host: x86_64-apple-darwin - cargo: cargo - os: macos-latest runs-on: ${{ matrix.os }} steps: - # See https://github.com/r-lib/actions/issues/243 - - name: Install automake and libpostal (macOS) - if: runner.os == 'macOS' - run: | - brew install automake libpostal - - name: Install libpostal (Linux) - if: runner.os == 'Linux' + - name: Install libpostal dependencies run: | sudo apt-get update sudo apt-get install -y curl autotools-dev autoconf libtool pkg-config libicu-dev From 15de16dc72ef5b3cb1d39718b964aa66169cffe2 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 12:55:15 -0400 Subject: [PATCH 06/16] maybe --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35481b3..0b2a79f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,10 +87,13 @@ jobs: git clone https://github.com/openvenues/libpostal cd libpostal ./bootstrap.sh - ./configure + ./configure --prefix=/usr/local make -j4 sudo make install sudo ldconfig + # Ensure proper permissions for libpostal data directory + sudo mkdir -p /usr/local/share/libpostal + sudo chmod 755 /usr/local/share/libpostal - uses: arduino/setup-protoc@v3 with: version: "25.1" From 3ae56715d722f7a8fb03d01d2ae6f9e4eb1587c9 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 13:41:47 -0400 Subject: [PATCH 07/16] thing --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b2a79f..d77d048 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,8 @@ jobs: run: | sudo apt-get update sudo apt-get install -y curl autotools-dev autoconf libtool pkg-config libicu-dev - # Install libpostal from source since it's not in apt + sudo mkdir -p /usr/local/share/libpostal + sudo chmod 755 /usr/local/share/libpostal git clone https://github.com/openvenues/libpostal cd libpostal ./bootstrap.sh @@ -92,8 +93,6 @@ jobs: sudo make install sudo ldconfig # Ensure proper permissions for libpostal data directory - sudo mkdir -p /usr/local/share/libpostal - sudo chmod 755 /usr/local/share/libpostal - uses: arduino/setup-protoc@v3 with: version: "25.1" From 227ab5f6c45723fad4c9fc85bdfce564d2e5944c Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 14:28:10 -0400 Subject: [PATCH 08/16] sudo --- .github/workflows/ci.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d77d048..82d051b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,14 +85,13 @@ jobs: sudo apt-get install -y curl autotools-dev autoconf libtool pkg-config libicu-dev sudo mkdir -p /usr/local/share/libpostal sudo chmod 755 /usr/local/share/libpostal - git clone https://github.com/openvenues/libpostal + sudo git clone https://github.com/openvenues/libpostal cd libpostal - ./bootstrap.sh - ./configure --prefix=/usr/local - make -j4 + sudo ./bootstrap.sh + sudo ./configure --prefix=/usr/local + sudo make -j4 sudo make install sudo ldconfig - # Ensure proper permissions for libpostal data directory - uses: arduino/setup-protoc@v3 with: version: "25.1" From 2c7df7a0a7e3adc35caa96fe3de2ad4e821349b9 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 15:20:44 -0400 Subject: [PATCH 09/16] back --- .github/workflows/ci.yml | 49 +++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82d051b..851fde7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,12 +49,12 @@ jobs: - name: "Make release" id: create_release if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: softprops/action-gh-release@v2 + uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} - name: "${{ steps.extract_release_version.outputs.release_version }}" + release_name: "${{ steps.extract_release_version.outputs.release_version }}" body_path: RELEASE_BODY.md # We use a matrix to run our build on every supported platform. @@ -75,41 +75,41 @@ jobs: host: x86_64-unknown-linux-musl cargo: cross os: ubuntu-latest + # - target: x86_64-apple-darwin + # host: x86_64-apple-darwin + # cargo: cargo + # os: macos-latest + # - target: aarch64-apple-darwin + # host: x86_64-apple-darwin + # cargo: cargo + # os: macos-latest runs-on: ${{ matrix.os }} steps: - - name: Install libpostal dependencies + # See https://github.com/r-lib/actions/issues/243 + - name: Install automake + if: runner.os == 'macOS' run: | - sudo apt-get update - sudo apt-get install -y curl autotools-dev autoconf libtool pkg-config libicu-dev - sudo mkdir -p /usr/local/share/libpostal - sudo chmod 755 /usr/local/share/libpostal - sudo git clone https://github.com/openvenues/libpostal - cd libpostal - sudo ./bootstrap.sh - sudo ./configure --prefix=/usr/local - sudo make -j4 - sudo make install - sudo ldconfig - - uses: arduino/setup-protoc@v3 - with: - version: "25.1" + brew install automake + - name: Install protoc + uses: arduino/setup-protoc@v3 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: actions-rs/toolchain@v1 with: + profile: minimal # We track latest stable Rust instead of hardcoding it because it # virtually never breaks old code. toolchain: stable - components: rustfmt, clippy, rust-src - targets: ${{ matrix.target }} + components: rustfmt, clippy + target: ${{ matrix.target }} # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v4 with: submodules: recursive - name: Install Just run: | - version=1.13.0 + version=1.42.4 basename=just-$version-${{ matrix.host }} curl -fLO https://github.com/casey/just/releases/download/$version/$basename.tar.gz tar xf $basename.tar.gz just @@ -117,7 +117,7 @@ jobs: rm -rf $basename.tar.gz - name: Install cargo-deny run: | - version=0.16.1 + version=0.18.4 basename=cargo-deny-$version-${{ matrix.host }} curl -fLO https://github.com/EmbarkStudios/cargo-deny/releases/download/$version/$basename.tar.gz tar xf $basename.tar.gz @@ -157,4 +157,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - files: ./${{ steps.build_release.outputs.release_file }} + upload_url: ${{ needs.create_release.outputs.upload_url }} + asset_path: ./${{ steps.build_release.outputs.release_file }} + asset_name: ${{ steps.build_release.outputs.release_file }} + asset_content_type: application/zip From afdb71b04f526dadc1d1782d2d648fd3b91ba367 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 15:25:02 -0400 Subject: [PATCH 10/16] back --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 851fde7..187ef4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,7 @@ jobs: echo "release_file=$release_file" >> $GITHUB_OUTPUT - name: Upload Release Asset if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: softprops/action-gh-release@v2 + uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From b5e69ccf7642bb1295c5b425ea89af018eefcbbd Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 15:33:51 -0400 Subject: [PATCH 11/16] new --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- Cargo.toml | 4 ++-- crates/libpostal-rust/Cargo.toml | 4 ++-- crates/libpostal-sys/Cargo.toml | 4 ++-- crates/metrics-exporter-newrelic/Cargo.toml | 4 ++-- crates/opinionated_metrics/Cargo.toml | 4 ++-- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f7791b..53ac159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.4.1] - 2025-09-02 + +### Added + +- Added `--bigtable-random-eviction-[age,rate]` + ## [1.4.0] - 2024-04-26 ### Added diff --git a/Cargo.lock b/Cargo.lock index 487a1f5..a7fc58c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "geocode-csv" -version = "1.4.0" +version = "1.4.1" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index ee6d09e..ec33607 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "geocode-csv" -version = "1.4.0" -authors = ["Eric Kidd "] +version = "1.4.1" +authors = ["Eric Kidd ", "Seamus Abshere ] edition = "2018" description = "CLI tool to bulk geocode CSV data using the Smarty API or libpostal" diff --git a/crates/libpostal-rust/Cargo.toml b/crates/libpostal-rust/Cargo.toml index 88a5659..24c18fe 100644 --- a/crates/libpostal-rust/Cargo.toml +++ b/crates/libpostal-rust/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libpostal-rust" -version = "0.1.1" -authors = ["Eric Kidd "] +version = "0.1.2" +authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2021" description = "High-level wrappers for libpostal address normalization (with locks to support thread-safe initialization)" diff --git a/crates/libpostal-sys/Cargo.toml b/crates/libpostal-sys/Cargo.toml index 22c6400..374bf07 100644 --- a/crates/libpostal-sys/Cargo.toml +++ b/crates/libpostal-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libpostal-sys" -version = "0.1.1" -authors = ["Eric Kidd "] +version = "0.1.2" +authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2021" links = "postal" diff --git a/crates/metrics-exporter-newrelic/Cargo.toml b/crates/metrics-exporter-newrelic/Cargo.toml index 20657db..6808316 100644 --- a/crates/metrics-exporter-newrelic/Cargo.toml +++ b/crates/metrics-exporter-newrelic/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "metrics-exporter-newrelic" -version = "0.2.0" -authors = ["Eric Kidd "] +version = "0.2.1" +authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2021" description = "Basic `metrics` exporter for use with NewRelic" diff --git a/crates/opinionated_metrics/Cargo.toml b/crates/opinionated_metrics/Cargo.toml index b51ee22..aa7f0b8 100644 --- a/crates/opinionated_metrics/Cargo.toml +++ b/crates/opinionated_metrics/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "opinionated_metrics" -version = "0.2.0" -authors = ["Eric Kidd "] +version = "0.2.1" +authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2021" description = "Automatic configuration of exporters for `metrics`" From f5a75d1108387a2dcfb0dd2a20ed55b9edaaa52c Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 2 Sep 2025 15:53:13 -0400 Subject: [PATCH 12/16] fix --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7fc58c..25329fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1598,7 +1598,7 @@ dependencies = [ [[package]] name = "libpostal-rust" -version = "0.1.1" +version = "0.1.2" dependencies = [ "lazy_static", "libpostal-sys", @@ -1608,7 +1608,7 @@ dependencies = [ [[package]] name = "libpostal-sys" -version = "0.1.1" +version = "0.1.2" dependencies = [ "autotools", "bindgen 0.72.1", @@ -1688,7 +1688,7 @@ dependencies = [ [[package]] name = "metrics-exporter-newrelic" -version = "0.2.0" +version = "0.2.1" dependencies = [ "http 0.2.12", "metrics", @@ -1846,7 +1846,7 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "opinionated_metrics" -version = "0.2.0" +version = "0.2.1" dependencies = [ "metrics", "metrics-exporter-newrelic", diff --git a/Cargo.toml b/Cargo.toml index ec33607..9d7fdee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "geocode-csv" version = "1.4.1" -authors = ["Eric Kidd ", "Seamus Abshere ] +authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2018" description = "CLI tool to bulk geocode CSV data using the Smarty API or libpostal" From 220b618cef984243e26dc831efc7fac432c2d4a3 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 1 Sep 2026 21:32:51 -0400 Subject: [PATCH 13/16] Release 1.4.1-alpha.1. Replace calendar cache refresh with per-entry backoff and a daily rate cap, keep cache writes readable by older binaries, and mark GitHub prereleases so an alpha does not become Latest. Co-authored-by: Cursor --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 23 +- Cargo.lock | 2677 +++++++---------- Cargo.toml | 72 +- README.md | 26 + crates/libpostal-rust/CHANGELOG.md | 7 + crates/libpostal-rust/Cargo.toml | 5 +- crates/libpostal-rust/src/probe.rs | 9 +- crates/libpostal-sys/CHANGELOG.md | 7 + crates/libpostal-sys/Cargo.toml | 3 +- crates/libpostal-sys/libpostal | 2 +- crates/libpostal-sys/src/lib.rs | 27 +- crates/metrics-exporter-newrelic/CHANGELOG.md | 8 + crates/metrics-exporter-newrelic/Cargo.toml | 19 +- .../metrics-exporter-newrelic/src/client.rs | 2 +- crates/opinionated_metrics/CHANGELOG.md | 6 + crates/opinionated_metrics/Cargo.toml | 8 +- deny.toml | 8 +- run_tests_with_secrets.py | 153 + src/errors.rs | 12 - src/geocoders/cache/compression.rs | 90 - src/geocoders/cache/entry.rs | 287 ++ src/geocoders/cache/mod.rs | 190 +- src/geocoders/cache/refresh.rs | 305 ++ src/geocoders/libpostal.rs | 42 +- src/geocoders/mod.rs | 24 +- src/geocoders/normalizer.rs | 15 +- src/geocoders/smarty/client.rs | 162 +- src/geocoders/smarty/mod.rs | 4 +- src/key_value_stores/bigtable.rs | 137 +- src/key_value_stores/mod.rs | 32 +- src/key_value_stores/redis.rs | 15 +- src/main.rs | 162 +- src/pipeline.rs | 2 +- src/server.rs | 15 +- tests/bigtable_eviction.rs | 376 --- tests/bigtable_refresh.rs | 86 + tests/libpostal.rs | 39 +- tests/server.rs | 8 +- tests/specs.rs | 5 +- 40 files changed, 2518 insertions(+), 2553 deletions(-) create mode 100755 run_tests_with_secrets.py delete mode 100644 src/geocoders/cache/compression.rs create mode 100644 src/geocoders/cache/entry.rs create mode 100644 src/geocoders/cache/refresh.rs delete mode 100644 tests/bigtable_eviction.rs create mode 100644 tests/bigtable_refresh.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 187ef4d..5751db8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: tag_name: ${{ github.ref }} release_name: "${{ steps.extract_release_version.outputs.release_version }}" body_path: RELEASE_BODY.md + prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }} # We use a matrix to run our build on every supported platform. build: diff --git a/CHANGELOG.md b/CHANGELOG.md index 53ac159..9d1807f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.4.1] - 2025-09-02 +## [Unreleased] + +## [1.4.1-alpha.1] - 2026-09-01 ### Added -- Added `--bigtable-random-eviction-[age,rate]` +- `libpostal` output now includes the `building` and `metro_station` columns, which the address parser can produce but which we previously discarded. +- `--refresh-failures-after-days`, `--refresh-failures-max-attempts`, optional `--refresh-successes-after-days`, and `--refresh-rate` re-geocode stale BigTable cache entries on the read path. Failures back off exponentially (`period * 2^attempts`) and stop after max attempts. A per-key-per-day rate cap bounds spend so a bulk-loaded backlog does not all come due on one day. New rows keep the legacy `N` payload so older binaries can still read them; refresh metadata is appended after that payload. If a success refresh comes back as no match, the prior success is kept. + +### Changed + +- Reworked the set of `libpostal` output columns to match the labels the address parser can actually emit (per `address_parser.h`). This removes ten columns that were always empty (`archipelago`, `continent`, `country_code`, `county`, `hamlet`, `municipality`, `neighbourhood`, `postal_city`, `region`, `village`), because they came from OpenCage's address-_formatting_ vocabulary rather than libpostal's parser vocabulary. This changes the columns emitted by `--include-libpostal`. +- Upgraded all dependencies to latest versions, including `bigtable_rs` 0.4, `reqwest` 0.13, `sha2` 0.11, `strum` 0.28, `clap` 4.6, `tikv-jemallocator` 0.7. +- Replaced hand-rolled `hyper`/`hyper-util`/`http-body-util`/`hyper-rustls` HTTP client for Smarty API with `reqwest`, removing four direct dependencies. +- Replaced `jemallocator` with `tikv-jemallocator`, the actively maintained fork. +- Replaced `lazy_static` with `std::sync::LazyLock` in `libpostal-sys` and `libpostal-rust`. +- Consolidated `strum` + `strum_macros` into `strum` with `derive` feature. +- Removed standalone `serde_derive` dependency (already re-exported by `serde` with `derive` feature). +- Bumped Rust edition from 2018 to 2021. + +### Fixed + +- When normalizing addresses, we no longer drop the secondary-unit designators `level` (e.g. "2nd Floor"), `staircase`, and `entrance` that libpostal parses out. These are now appended to the street, alongside `building`, so they reach the downstream geocoder instead of being silently discarded (the same class of bug as the earlier "city parsed as suburb" fix). +- `island` (e.g. "Maui") is now kept as part of the city during normalization instead of being dropped. ## [1.4.0] - 2024-04-26 diff --git a/Cargo.lock b/Cargo.lock index 25329fb..d76d937 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,62 +2,29 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] [[package]] name = "anstream" -version = "0.6.20" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -70,57 +37,71 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arcstr" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d" + +[[package]] +name = "async-lock" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "backtrace", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -131,9 +112,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "autotools" @@ -146,99 +127,54 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.13.3" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" +checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" dependencies = [ "aws-lc-sys", + "untrusted 0.7.1", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.30.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" +checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" dependencies = [ - "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] name = "axum" -version = "0.6.20" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", + "axum-core", "bytes", "futures-util", - "headers", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", "itoa", - "matchit 0.7.3", + "matchit", "memchr", "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" -dependencies = [ - "axum-core 0.5.2", - "bytes", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "itoa", - "matchit 0.8.4", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 1.0.2", - "tower 0.5.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", + "tower", "tower-layer", "tower-service", "tracing", @@ -246,44 +182,23 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", - "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", + "tracing", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -292,51 +207,47 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bb8" -version = "0.8.6" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89aabfae550a5c44b43ab941844ffcd2e993cb6900b342debf59e9ea74acdb8" +checksum = "457d7ed3f888dfd2c7af56d4975cade43c622f74bdcddfed6d4352f57acc6310" dependencies = [ - "async-trait", "futures-util", "parking_lot", + "portable-atomic", "tokio", ] [[package]] name = "bb8-redis" -version = "0.13.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd456361ba8e4e7f5fe58e1697ce078a149c85ebce13bf9c6b483d3f566fc9c3" +checksum = "dc1063effc7f6cf848bcbcc6e31b5962be75215835587d3109607c643d616f66" dependencies = [ - "async-trait", "bb8", "redis", ] [[package]] name = "bigtable_rs" -version = "0.2.18" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "082de99888de62e9c7e09f0f3df3d3208ab06db327ad307033d6b36171b160e0" +checksum = "935e1cc0582ff23989286ba57333b4acf7522912cd65ce4f0dc0756619646980" dependencies = [ "futures-util", "gcp_auth", - "http 1.3.1", + "googleapis-tonic-google-bigtable-v2", + "http", "hyper-util", "log", - "prost", "prost-build", - "prost-types", - "prost-wkt", "prost-wkt-build", - "prost-wkt-types", - "serde", - "serde_with", - "thiserror 2.0.16", + "thiserror", "tokio", "tonic", - "tonic-build", - "tower 0.5.2", + "tonic-prost", + "tonic-prost-build", + "tower", + "urlencoding", ] [[package]] @@ -359,92 +270,63 @@ dependencies = [ "virtue", ] -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.9.4", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn", - "which", -] - [[package]] name = "bindgen" version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.9.4", + "bitflags", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", "quote", "regex", - "rustc-hash 2.1.1", - "shlex", - "syn", + "rustc-hash", + "shlex 1.3.0", + "syn 2.0.119", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytes" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.2.35" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3" +checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -458,17 +340,33 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", @@ -479,9 +377,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" dependencies = [ "glob", "libc", @@ -490,9 +388,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.46" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -500,9 +398,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.46" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -513,21 +411,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cli_test_dir" @@ -537,24 +435,24 @@ checksum = "cc7e8a289c9ba144ed96a2f5776b320192ccb2f22212b9aabf61fd15dedb4b3a" [[package]] name = "cmake" -version = "0.1.54" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ "cc", ] [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" -version = "4.6.7" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ "bytes", "futures-core", @@ -565,14 +463,10 @@ dependencies = [ ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "const-oid" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "core-foundation" @@ -592,123 +486,78 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "generic-array", - "typenum", + "hybrid-array", ] [[package]] name = "csv" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "deranged" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" -dependencies = [ - "powerfmt", - "serde", -] - [[package]] name = "digest" -version = "0.10.7" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer", + "const-oid", "crypto-common", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] @@ -717,26 +566,11 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - [[package]] name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" [[package]] name = "endian-type" @@ -751,36 +585,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "erased-serde" -version = "0.4.6" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "serde", - "typeid", + "libc", + "windows-sys 0.61.2", ] [[package]] -name = "errno" -version = "0.3.13" +name = "event-listener" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "libc", - "windows-sys 0.60.2", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "evmap" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8874945f036109c72242964c1174cf99434e30cfa45bf45fedc983f50046f8" +dependencies = [ + "hashbag", + "left-right", + "smallvec", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.0" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" [[package]] name = "fixedbitset" @@ -800,6 +655,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -817,9 +678,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", @@ -832,9 +693,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -842,15 +703,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ "futures-core", "futures-task", @@ -859,38 +720,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-channel", "futures-core", @@ -900,31 +761,30 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "gcp_auth" -version = "0.12.3" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf67f30198e045a039264c01fb44659ce82402d7771c50938beb41a5ac87733" +checksum = "26d27dbcc645b60b8e7f6e2868a9d7102ece97d1bb49c1288b5321fcc67f7260" dependencies = [ "async-trait", - "base64 0.22.1", + "aws-lc-rs", + "base64", "bytes", "chrono", - "home", - "http 1.3.1", + "http", "http-body-util", - "hyper 1.7.0", - "hyper-rustls 0.27.7", + "hyper", + "hyper-rustls", "hyper-util", - "ring", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-pki-types", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", "tracing-futures", @@ -932,22 +792,27 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "generator" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "b3b854b0e584ead1a33f18b2fcad7cf7be18b3875c78816b753639aa501513ae" dependencies = [ - "typenum", - "version_check", + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows-link", + "windows-result", ] [[package]] name = "geocode-csv" -version = "1.4.1" +version = "1.4.1-alpha.1" dependencies = [ "anyhow", "async-trait", - "axum 0.6.20", + "axum", "bb8", "bb8-redis", "bigtable_rs", @@ -956,24 +821,20 @@ dependencies = [ "cli_test_dir", "csv", "futures", - "hyper 0.14.32", - "hyper-rustls 0.24.2", - "jemallocator", + "googleapis-tonic-google-bigtable-v2", "leaky-bucket", "libpostal-rust", "metrics", "metrics-util", "opinionated_metrics", - "rand 0.8.5", "redis", "reqwest", - "rustls 0.23.31", + "rustls", "serde", - "serde_derive", "serde_json", "sha2", "strum", - "strum_macros", + "tikv-jemallocator", "tokio", "tokio-stream", "tracing", @@ -983,71 +844,113 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.3+wasi-0.2.4", + "r-efi 5.3.0", + "wasip2", ] [[package]] -name = "gimli" -version = "0.31.1" +name = "getrandom" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] -name = "h2" -version = "0.3.27" +name = "googleapis-tonic-google-api" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +checksum = "fca39f3577e656ca9ad97737fc1a397f45c46f54d047a43af1fb680287b5ace8" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.11.0", - "slab", - "tokio", - "tokio-util", - "tracing", + "prost", + "prost-types", + "tonic", + "tonic-prost", ] [[package]] -name = "h2" -version = "0.4.12" +name = "googleapis-tonic-google-bigtable-v2" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a7cb407adead1bd3b623453ecc47556e07377a514793c0df52e9845caefadb" +dependencies = [ + "googleapis-tonic-google-api", + "googleapis-tonic-google-rpc", + "googleapis-tonic-google-type", + "prost", + "prost-types", + "tonic", + "tonic-prost", +] + +[[package]] +name = "googleapis-tonic-google-rpc" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f8922a81782e57325a059334bcec9730f7865eea2a1a1453896efe53a65b6af" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tonic-prost", +] + +[[package]] +name = "googleapis-tonic-google-type" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc35fc04d6bb84eab8fff7c6a40357bfd647af0d5dfc41597a4ae6d8e0d84a2d" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tonic-prost", +] + +[[package]] +name = "h2" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.3.1", - "indexmap 2.11.0", + "http", + "indexmap", "slab", "tokio", "tokio-util", @@ -1055,10 +958,10 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "hashbag" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "7040a10f52cba493ddb09926e15d10a9d8a28043708a405931fe4c6f19fac064" [[package]] name = "hashbrown" @@ -1066,38 +969,23 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", -] - -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.7", - "bytes", - "headers-core", - "http 0.2.12", - "httpdate", - "mime", - "sha1", + "foldhash 0.1.5", ] [[package]] -name = "headers-core" -version = "0.2.0" +name = "hashbrown" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "http 0.2.12", + "foldhash 0.2.0", ] [[package]] -name = "heck" -version = "0.4.1" +name = "hashbrown" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1105,74 +993,36 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", - "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -1189,47 +1039,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] -name = "hyper" -version = "0.14.32" +name = "hybrid-array" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", + "typenum", ] [[package]] name = "hyper" -version = "1.7.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", - "h2 0.4.12", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1237,34 +1071,17 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ - "http 1.3.1", - "hyper 1.7.0", + "http", + "hyper", "hyper-util", - "rustls 0.23.31", - "rustls-native-certs 0.8.1", - "rustls-pki-types", + "rustls", + "rustls-native-certs", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower-service", ] @@ -1274,7 +1091,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.7.0", + "hyper", "hyper-util", "pin-project-lite", "tokio", @@ -1283,20 +1100,22 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ + "base64", "bytes", "futures-channel", - "futures-core", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.7.0", + "http", + "http-body", + "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tower-service", "tracing", @@ -1304,9 +1123,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1328,12 +1147,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1341,9 +1161,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", @@ -1354,11 +1174,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1369,42 +1188,39 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" dependencies = [ "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1412,12 +1228,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -1431,9 +1241,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1441,63 +1251,31 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.11.0" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" dependencies = [ "equivalent", - "hashbrown 0.15.5", - "serde", -] - -[[package]] -name = "inventory" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" -dependencies = [ - "rustversion", -] - -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", + "hashbrown 0.17.1", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -1513,47 +1291,77 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" +name = "jni" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cc", - "libc", + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror", + "walkdir", + "windows-link", ] [[package]] -name = "jemallocator" -version = "0.5.4" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0de374a9f8e63150e6f5e8a60cc14c668226d7a347d8aee1a45766e3c4dd3bc" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jemalloc-sys", - "libc", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", ] [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.4.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -1563,12 +1371,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "leaky-bucket" version = "1.1.2" @@ -1580,29 +1382,39 @@ dependencies = [ "tokio", ] +[[package]] +name = "left-right" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bc015ded5d9b3054dbbdb63332cdd6ee42352ccef19e911e25117490e2f48ee" +dependencies = [ + "crossbeam-utils", + "loom", + "slab", +] + [[package]] name = "libc" -version = "0.2.175" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] [[package]] name = "libpostal-rust" version = "0.1.2" dependencies = [ - "lazy_static", "libpostal-sys", - "thiserror 1.0.69", + "thiserror", "tracing", ] @@ -1611,43 +1423,54 @@ name = "libpostal-sys" version = "0.1.2" dependencies = [ "autotools", - "bindgen 0.72.1", - "lazy_static", + "bindgen", ] [[package]] name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "matchers" @@ -1658,12 +1481,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "matchit" version = "0.8.4" @@ -1672,67 +1489,68 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "metrics" -version = "0.24.2" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5" +checksum = "89550ee9f79e88fef3119de263694973a8adb26c21d75322164fb8c493039fe2" dependencies = [ - "ahash", "portable-atomic", + "rapidhash", ] [[package]] name = "metrics-exporter-newrelic" version = "0.2.1" dependencies = [ - "http 0.2.12", + "http", "metrics", "metrics-util", "reqwest", "serde", - "serde_derive", "serde_json", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", ] [[package]] name = "metrics-exporter-prometheus" -version = "0.17.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15" +checksum = "1db0d8f1fc9e62caebd0319e11eaec5822b0186c171568f0480b46a0137f9108" dependencies = [ - "base64 0.22.1", - "indexmap 2.11.0", + "base64", + "evmap", + "indexmap", "metrics", "metrics-util", "quanta", - "thiserror 2.0.16", + "thiserror", ] [[package]] name = "metrics-util" -version = "0.20.0" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986" +checksum = "96f8722f8562635f92f8ed992f26df0532266eb03d5202607c20c0d7e9745e13" dependencies = [ "aho-corasick", "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.15.5", - "indexmap 2.11.0", + "hashbrown 0.16.1", + "indexmap", "metrics", "ordered-float", "quanta", "radix_trie", - "rand 0.9.2", + "rand 0.9.5", "rand_xoshiro", + "rapidhash", "sketches-ddsketch", ] @@ -1748,24 +1566,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "mio" -version = "1.0.4" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -1795,19 +1604,13 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-traits" version = "0.2.19" @@ -1817,32 +1620,23 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "opinionated_metrics" @@ -1851,24 +1645,30 @@ dependencies = [ "metrics", "metrics-exporter-newrelic", "metrics-exporter-prometheus", - "thiserror 1.0.69", + "thiserror", "tracing", ] [[package]] name = "ordered-float" -version = "4.6.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" dependencies = [ "num-traits", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1876,15 +1676,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -1895,67 +1695,62 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" -version = "0.7.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", - "indexmap 2.11.0", + "hashbrown 0.15.5", + "indexmap", ] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] -name = "pin-utils" -version = "0.1.0" +name = "pkg-config" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ "zerovec", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1972,23 +1767,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.119", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.13.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes", "prost-derive", @@ -1996,15 +1791,14 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ - "heck 0.5.0", + "heck", "itertools 0.14.0", "log", "multimap", - "once_cell", "petgraph", "prettyplease", "prost", @@ -2012,94 +1806,61 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn", + "syn 2.0.119", "tempfile", ] [[package]] name = "prost-derive" -version = "0.13.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", "itertools 0.14.0", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "prost-types" -version = "0.13.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ "prost", ] [[package]] -name = "prost-wkt" -version = "0.6.1" +name = "prost-wkt-build" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497e1e938f0c09ef9cabe1d49437b4016e03e8f82fbbe5d1c62a9b61b9decae1" +checksum = "cb5cd191fad9142d096efc97c64715db73db4adb60c38ebdf22f5b54cd6ea712" dependencies = [ - "chrono", - "inventory", - "prost", - "serde", - "serde_derive", - "serde_json", - "typetag", -] - -[[package]] -name = "prost-wkt-build" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b8bf115b70a7aa5af1fd5d6e9418492e9ccb6e4785e858c938e28d132a884b" -dependencies = [ - "heck 0.5.0", + "heck", "prost", "prost-build", "prost-types", "quote", ] -[[package]] -name = "prost-wkt-types" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cdde6df0a98311c839392ca2f2f0bcecd545f86a62b4e3c6a49c336e970fe5" -dependencies = [ - "chrono", - "prost", - "prost-build", - "prost-types", - "prost-wkt", - "prost-wkt-build", - "regex", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "pulldown-cmark" -version = "0.12.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" +checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ - "bitflags 2.9.4", + "bitflags", "memchr", "unicase", ] [[package]] name = "pulldown-cmark-to-cmark" -version = "20.0.1" +version = "22.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c0f333311d2d8fda65bcf76af35054e9f38e253332a0289746156a59656988b" +checksum = "ab1ad36992cead65f02aa399a373a42730922f1525d988172634fdefdecb8a60" dependencies = [ "pulldown-cmark", ] @@ -2114,16 +1875,73 @@ dependencies = [ "libc", "once_cell", "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "web-sys", "winapi", ] +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + [[package]] name = "quote" -version = "1.0.40" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -2134,6 +1952,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radix_trie" version = "0.2.1" @@ -2146,33 +1970,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", + "rand_chacha", + "rand_core 0.9.5", ] [[package]] name = "rand" -version = "0.9.2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -2182,25 +1996,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" dependencies = [ - "getrandom 0.3.3", + "rand_core 0.10.1", ] [[package]] @@ -2209,71 +2029,64 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rapidhash" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da7e78a036ce858e8d55b7e7dc8ba3a88b78350fd2155d3591bbd966b58589e" +dependencies = [ + "rustversion", ] [[package]] name = "raw-cpuid" -version = "11.5.0" +version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.9.4", + "bitflags", ] [[package]] name = "redis" -version = "0.23.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba" +checksum = "e37a4ca5c6ca42aa3e6df2fd32b987a65d32a4c2159a6f3fe0fd1df306a2658f" dependencies = [ - "async-trait", + "arcstr", + "async-lock", "bytes", + "cfg-if", "combine", "futures-util", "itoa", "percent-encoding", "pin-project-lite", "ryu", + "socket2", "tokio", "tokio-util", "url", + "xxhash-rust", ] [[package]] name = "redox_syscall" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" -dependencies = [ - "bitflags 2.9.4", -] - -[[package]] -name = "ref-cast" -version = "1.0.24" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "bitflags", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -2283,9 +2096,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -2294,49 +2107,47 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.11.27" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ - "base64 0.21.7", + "base64", "bytes", - "encoding_rs", + "futures-channel", "futures-core", "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-rustls 0.24.2", - "ipnet", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", "js-sys", "log", - "mime", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", + "sync_wrapper", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", + "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", - "winreg", ] [[package]] @@ -2347,201 +2158,151 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] -name = "rustix" -version = "0.38.44" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "bitflags 2.9.4", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "semver", ] [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.4", + "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.21.12" +version = "0.23.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.23.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" dependencies = [ "aws-lc-rs", "log", "once_cell", - "ring", "rustls-pki-types", - "rustls-webpki 0.103.4", + "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework 2.11.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.3.0", + "security-framework", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" +name = "rustls-pki-types" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ - "rustls-pki-types", + "web-time", + "zeroize", ] [[package]] -name = "rustls-pki-types" -version = "1.12.0" +name = "rustls-platform-verifier" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "zeroize", + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", ] [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "rustls-platform-verifier-android" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] -name = "schannel" -version = "0.1.27" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "windows-sys 0.59.0", + "winapi-util", ] [[package]] -name = "schemars" -version = "0.9.0" +name = "schannel" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", + "windows-sys 0.61.2", ] [[package]] -name = "schemars" -version = "1.0.4" +name = "scoped-tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -2549,155 +2310,95 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.9.4", + "bitflags", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] -name = "security-framework" -version = "3.3.0" +name = "security-framework-sys" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.10.1", "core-foundation-sys", "libc", - "security-framework-sys", ] [[package]] -name = "security-framework-sys" -version = "2.14.0" +name = "semver" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ - "core-foundation-sys", - "libc", + "serde_core", + "serde_derive", ] [[package]] -name = "serde" -version = "1.0.219" +name = "serde_core" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ - "indexmap 2.11.0", + "indexmap", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.11.0", - "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", + "serde_core", ] [[package]] name = "sha2" -version = "0.10.9" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures", @@ -2720,48 +2421,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "sketches-ddsketch" -version = "0.3.0" +name = "shlex" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] -name = "slab" -version = "0.4.11" +name = "simd_cesu8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] -name = "smallvec" -version = "1.15.1" +name = "simdutf8" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] -name = "socket2" -version = "0.5.10" +name = "sketches-ddsketch" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -2771,21 +2484,23 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.25.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros", +] [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2", "quote", - "rustversion", - "syn", + "syn 2.0.119", ] [[package]] @@ -2796,9 +2511,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.106" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -2806,216 +2521,175 @@ dependencies = [ ] [[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - -[[package]] -name = "synstructure" -version = "0.13.2" +name = "syn" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", - "syn", + "unicode-ident", ] [[package]] -name = "system-configuration" -version = "0.5.1" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "system-configuration-sys", + "futures-core", ] [[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "core-foundation-sys", - "libc", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] name = "tempfile" -version = "3.21.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.3", "once_cell", - "rustix 1.0.8", - "windows-sys 0.60.2", + "rustix", + "windows-sys 0.61.2", ] [[package]] name = "terminal_size" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" -dependencies = [ - "rustix 1.0.8", - "windows-sys 0.60.2", -] - -[[package]] -name = "thiserror" -version = "1.0.69" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ - "thiserror-impl 1.0.69", + "rustix", + "windows-sys 0.61.2", ] [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.69" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] -name = "thiserror-impl" -version = "2.0.16" +name = "thread_local" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ - "proc-macro2", - "quote", - "syn", + "cfg-if", ] [[package]] -name = "thread_local" -version = "1.1.9" +name = "tikv-jemalloc-sys" +version = "0.7.1+5.3.1-0-g81034ce1f1373e37dc865038e1bc8eeecf559ce8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1a2825c78386b4ae0314074867860ba9577875de945f05992c38815cbec327f0" dependencies = [ - "cfg-if", + "cc", + "libc", ] [[package]] -name = "time" -version = "0.3.42" +name = "tikv-jemallocator" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3" +checksum = "249f09e49ab1609436f34c776e84231bead18d6a955f119f939bdc1d847561bd" dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", + "libc", + "tikv-jemalloc-sys", ] [[package]] -name = "time-core" -version = "0.1.5" +name = "tinystr" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] [[package]] -name = "time-macros" -version = "0.2.23" +name = "tinyvec" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ - "num-conv", - "time-core", + "tinyvec_macros", ] [[package]] -name = "tinystr" -version = "0.8.1" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", - "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", + "syn 3.0.4", ] [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.31", + "rustls", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" dependencies = [ "futures-core", "pin-project-lite", @@ -3024,42 +2698,43 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" dependencies = [ "bytes", "futures-core", "futures-sink", + "libc", "pin-project-lite", "tokio", ] [[package]] name = "tonic" -version = "0.13.1" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", - "axum 0.8.4", - "base64 0.22.1", + "axum", + "base64", "bytes", - "h2 0.4.12", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.7.0", + "hyper", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", - "prost", - "socket2 0.5.10", + "socket2", + "sync_wrapper", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tokio-stream", - "tower 0.5.2", + "tower", "tower-layer", "tower-service", "tracing", @@ -3067,51 +2742,78 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.13.1" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", "prost-build", "prost-types", "quote", - "syn", + "syn 2.0.119", + "tempfile", + "tonic-build", ] [[package]] name = "tower" -version = "0.4.13" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "pin-project", + "indexmap", "pin-project-lite", + "slab", + "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", ] [[package]] -name = "tower" -version = "0.5.2" +name = "tower-http" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "futures-core", + "bitflags", + "bytes", "futures-util", - "indexmap 2.11.0", + "http", + "http-body", "pin-project-lite", - "slab", - "sync_wrapper 1.0.2", - "tokio", - "tokio-util", + "tower", "tower-layer", "tower-service", - "tracing", + "url", ] [[package]] @@ -3128,9 +2830,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -3140,20 +2842,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3182,9 +2884,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -3204,53 +2906,29 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - [[package]] name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "typetag" -version = "0.2.20" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f22b40dd7bfe8c14230cf9702081366421890435b2d625fa92b4acc4c3de6f" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] -name = "typetag-impl" -version = "0.2.20" +name = "unicase" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] -name = "unicase" -version = "2.8.1" +name = "unicode-ident" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] -name = "unicode-ident" -version = "1.0.18" +name = "untrusted" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "untrusted" @@ -3266,9 +2944,9 @@ checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -3276,6 +2954,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -3294,18 +2978,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "virtue" version = "0.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3322,58 +3010,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.3+wasi-0.2.4" +name = "wasip2" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3381,52 +3053,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn", - "wasm-bindgen-backend", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] -name = "webpki-roots" -version = "0.25.4" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] -name = "which" -version = "4.4.2" +name = "webpki-root-certs" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", + "rustls-pki-types", ] [[package]] @@ -3445,6 +3118,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3453,9 +3135,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -3466,99 +3148,66 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "windows-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.3", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-link", ] [[package]] @@ -3567,159 +3216,58 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3727,40 +3275,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winreg" -version = "0.50.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] -name = "wit-bindgen" -version = "0.45.0" +name = "writeable" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] -name = "writeable" -version = "0.6.1" +name = "xxhash-rust" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "aee1b19627c7c60102ab80d3a9cbe18de90bfe03bfa6c3715447681f0e8c8af6" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -3768,68 +3305,68 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -3838,9 +3375,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ "yoke", "zerofrom", @@ -3849,11 +3386,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 9d7fdee..c100b3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "geocode-csv" -version = "1.4.1" +version = "1.4.1-alpha.1" authors = ["Eric Kidd ", "Seamus Abshere "] -edition = "2018" +edition = "2021" description = "CLI tool to bulk geocode CSV data using the Smarty API or libpostal" license = "Apache-2.0 OR MIT" @@ -11,68 +11,58 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://github.com/faradayio/geocode-csv" [dev-dependencies] -cli_test_dir = "^0.1.7" -reqwest = { version = "^0.11.18", default-features = false, features = [ - "blocking", -] } +cli_test_dir = "^0.1.8" +reqwest = { version = "^0.13.4", default-features = false, features = ["blocking", "json", "rustls"] } [dependencies] -anyhow = { version = "^1.0.40", features = ["backtrace"] } -async-trait = "^0.1.52" -axum = { version = "^0.6.19", default-features = false, features = [ +anyhow = { version = "^1.0.104", features = ["backtrace"] } +async-trait = "^0.1.92" +axum = { version = "^0.8.9", default-features = false, features = [ "http1", "tokio", "tower-log", "tracing", - "headers", "json", ] } -bb8 = "^0.8.0" -bb8-redis = "^0.13.1" -bigtable_rs = "^0.2.5" -bincode = { version = "2.0.0-rc.2", features = ["serde"] } -clap = { version = "^4.3.0", features = ["derive", "wrap_help"] } -csv = "^1.0.7" -futures = "^0.3.4" -hyper = { version = "^0.14.7", features = ["client", "http2", "stream"] } -hyper-rustls = { version = "^0.24.1", features = [ - "rustls-native-certs", - "http2", -] } -leaky-bucket = "^1.0.1" +bb8 = "^0.9.1" +bb8-redis = "^0.26.0" +bigtable_rs = "^0.4.1" +googleapis-tonic-google-bigtable-v2 = "0.39.0" +# bincode 3.0.0 on crates.io is a tombstone that only emits compile_error!. +bincode = { version = "2.0.1", features = ["serde"] } +clap = { version = "^4.6.6", features = ["derive", "wrap_help"] } +csv = "^1.4.0" +futures = "^0.3.34" +leaky-bucket = "^1.1.2" libpostal-rust = { version = "0.1.1", path = "crates/libpostal-rust" } -metrics = "^0.24.2" -metrics-util = "^0.20.0" +metrics = "^0.24.6" +metrics-util = "^0.20.4" opinionated_metrics = { version = "0.2.0", path = "crates/opinionated_metrics" } -rand = "^0.8.5" -redis = { version = "^0.23.2", default-features = false, features = [ +reqwest = { version = "^0.13.4", default-features = false, features = ["json", "rustls"] } +redis = { version = "^1.6.0", default-features = false, features = [ "aio", "tokio-comp", ] } rustls = { version = "^0.23", default-features = false, features = ["aws-lc-rs"] } -serde = { version = "^1.0.92", features = ["derive"] } -# Last version of `serde_derive` that can be built from source. See -# https://github.com/serde-rs/serde/issues/2538. -serde_derive = "^1.0.184" +serde = { version = "^1.0.229", features = ["derive"] } # IMPORTANT: We require `preserve_order` to correctly handle "structure" JSON # specifications in a way that puts the right data in the right output columns. -serde_json = { version = "^1.0.39", features = ["preserve_order"] } -sha2 = "^0.10.1" -strum = "^0.25.0" -strum_macros = "^0.25.2" -tokio = { version = "^1.6.0", features = [ +serde_json = { version = "^1.0.151", features = ["preserve_order"] } +sha2 = "^0.11.0" +strum = { version = "^0.28.0", features = ["derive"] } +tokio = { version = "^1.53.1", features = [ "io-util", "macros", "rt-multi-thread", "sync", ] } -tokio-stream = "^0.1.6" -tracing = "^0.1.29" -tracing-subscriber = { version = "^0.3.7", features = ["env-filter"] } -url = "^2.1.1" +tokio-stream = "^0.1.19" +tracing = "^0.1.44" +tracing-subscriber = { version = "^0.3.23", features = ["env-filter"] } +url = "^2.5.8" [target.'cfg(not(target_env = "msvc"))'.dependencies] -jemallocator = { version = "^0.5.4", features = ["profiling"], optional = true } +tikv-jemallocator = { version = "^0.7.0", features = ["profiling"], optional = true } # [profile.release] # debug = true diff --git a/README.md b/README.md index 5173a49..7dd02b0 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,32 @@ You can geocode multiple addresses per row as follows: This will insert two sets of columns, one beginning with `geocoded_shipping_` and the other with `geocoded_billing_`. +## Caching + +Pass `--cache=redis://...` or `--cache=bigtable://PROJECT/INSTANCE/TABLE` to store every geocoding result, including "no match" results, in a key/value store. Later runs read from the cache first and only call Smarty for addresses they have not seen. + +### Refreshing stale cache entries + +Smarty's coverage improves over time, so an address that failed to match last year may match today. With a BigTable cache, you can ask `geocode-csv` to re-geocode cached results as it reads them: + +```sh +geocode-csv --spec address_spec.json \ + --cache=bigtable://PROJECT/INSTANCE/TABLE \ + --refresh-failures-after-days=90 \ + --refresh-failures-max-attempts=4 \ + --refresh-rate=0.1 \ + < in.csv > out.csv +``` + +- `--refresh-failures-after-days=N` re-checks a cached "no match" once it is `N` days old. Each failed re-check doubles the wait (`N`, `2N`, `4N`, ...). +- `--refresh-failures-max-attempts=M` stops re-checking a failure after `M` refreshes. +- `--refresh-successes-after-days=N` (optional) re-checks a successful geocode once it is `N` days old. If Smarty then returns no match, the old result is kept. +- `--refresh-rate=F`, with `F` in `(0, 1]`, is required whenever a refresh period is set. Of the cache entries this run reads that are due for refresh, only fraction `F` are actually re-geocoded on any given day. The decision is derived from the cache key and the date, so the same entry gets the same answer all day. Use this to stop a cache that was loaded all at once from coming due all at once. + +Refresh only works with BigTable, because Redis does not record when a key was written. `--cache-hits-only` disables refresh. + +Rows written by this version can still be read by older versions of `geocode-csv`. + ## Build You'll need to run: diff --git a/crates/libpostal-rust/CHANGELOG.md b/crates/libpostal-rust/CHANGELOG.md index bd31b22..cd0f5ea 100644 --- a/crates/libpostal-rust/CHANGELOG.md +++ b/crates/libpostal-rust/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Replaced `lazy_static` with `std::sync::LazyLock`. +- Updated `thiserror` to 2.x. + ## [0.1.1] - 2022-02-17 ### Fixed diff --git a/crates/libpostal-rust/Cargo.toml b/crates/libpostal-rust/Cargo.toml index 24c18fe..408d186 100644 --- a/crates/libpostal-rust/Cargo.toml +++ b/crates/libpostal-rust/Cargo.toml @@ -12,7 +12,6 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://docs.rs/libpostal-rust" [dependencies] -lazy_static = "1.4.0" libpostal-sys = { version = "0.1.1", path = "../libpostal-sys" } -thiserror = "1.0.30" -tracing = "0.1.29" +thiserror = "2.0.20" +tracing = "0.1.44" diff --git a/crates/libpostal-rust/src/probe.rs b/crates/libpostal-rust/src/probe.rs index d03309f..bbeac4c 100644 --- a/crates/libpostal-rust/src/probe.rs +++ b/crates/libpostal-rust/src/probe.rs @@ -2,11 +2,11 @@ use std::{ fs, + ops::Deref, path::{Path, PathBuf}, - sync::RwLock, + sync::{LazyLock, RwLock}, }; -use lazy_static::{__Deref, lazy_static}; use tracing::{debug, error, trace}; use crate::{Error, Result}; @@ -18,9 +18,8 @@ const EXPECTED_DATA_VERSION: &str = "v1"; static DATA_DIR_PATHS: &[&str] = &["/usr/local/share/libpostal", "/usr/share/libpostal"]; -lazy_static! { - static ref DATA_DIRECTORY: RwLock> = RwLock::new(None); -} +static DATA_DIRECTORY: LazyLock>> = + LazyLock::new(|| RwLock::new(None)); /// Probe for a libpostal data directory, returning the path, if any. pub(crate) fn probe_data_directory() -> Result { diff --git a/crates/libpostal-sys/CHANGELOG.md b/crates/libpostal-sys/CHANGELOG.md index bd31b22..00085b7 100644 --- a/crates/libpostal-sys/CHANGELOG.md +++ b/crates/libpostal-sys/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Replaced `lazy_static` with `std::sync::LazyLock`. +- Updated `autotools` to 0.2.7. + ## [0.1.1] - 2022-02-17 ### Fixed diff --git a/crates/libpostal-sys/Cargo.toml b/crates/libpostal-sys/Cargo.toml index 374bf07..978cfae 100644 --- a/crates/libpostal-sys/Cargo.toml +++ b/crates/libpostal-sys/Cargo.toml @@ -19,10 +19,9 @@ exclude = [ ] [build-dependencies] -autotools = "0.2" +autotools = "0.2.7" # Updated bindgen to latest version to fix null pointer dereference issues bindgen = "0.72.1" [dependencies] -lazy_static = "1.4.0" diff --git a/crates/libpostal-sys/libpostal b/crates/libpostal-sys/libpostal index 56c4a5d..70c79af 160000 --- a/crates/libpostal-sys/libpostal +++ b/crates/libpostal-sys/libpostal @@ -1 +1 @@ -Subproject commit 56c4a5daf747343cd192490d05c35df693f314a3 +Subproject commit 70c79af0fecf21864854824179bd228c8532ce80 diff --git a/crates/libpostal-sys/src/lib.rs b/crates/libpostal-sys/src/lib.rs index 68335b1..d9c41fd 100644 --- a/crates/libpostal-sys/src/lib.rs +++ b/crates/libpostal-sys/src/lib.rs @@ -11,9 +11,7 @@ #![allow(clippy::ptr_offset_with_cast)] #![allow(clippy::useless_transmute)] -use std::sync::{Arc, Mutex}; - -use lazy_static::lazy_static; +use std::sync::{Arc, LazyLock, Mutex}; /// Which portions of this library have been initialized? /// @@ -31,17 +29,18 @@ pub struct InitializationState { pub language_classifier_initialized: bool, } -lazy_static! { - /// You _must_ take this lock before doing _anything_ with this library. - /// `libpostal` is [not thread safe][threads]. - /// - /// [threads]: https://github.com/openvenues/libpostal/issues/34 - pub static ref GLOBAL_LOCK: Arc> = Arc::new(Mutex::new(InitializationState { - initialized: false, - parser_initialized: false, - language_classifier_initialized: false, - })); -} +/// You _must_ take this lock before doing _anything_ with this library. +/// `libpostal` is [not thread safe][threads]. +/// +/// [threads]: https://github.com/openvenues/libpostal/issues/34 +pub static GLOBAL_LOCK: LazyLock>> = + LazyLock::new(|| { + Arc::new(Mutex::new(InitializationState { + initialized: false, + parser_initialized: false, + language_classifier_initialized: false, + })) + }); // Use build.rs to automatically generate these bindings include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/crates/metrics-exporter-newrelic/CHANGELOG.md b/crates/metrics-exporter-newrelic/CHANGELOG.md index bbe406b..0d3d870 100644 --- a/crates/metrics-exporter-newrelic/CHANGELOG.md +++ b/crates/metrics-exporter-newrelic/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Updated `reqwest` to 0.13 (replaced `rustls-tls` feature with `rustls`). +- Removed standalone `serde_derive` dependency in favor of `serde` with `derive` feature. +- Updated `thiserror` to 2.x, `tokio` to 1.51. + ## [0.2.0] - 2022-10-26 ### Changed diff --git a/crates/metrics-exporter-newrelic/Cargo.toml b/crates/metrics-exporter-newrelic/Cargo.toml index 6808316..63f4ca9 100644 --- a/crates/metrics-exporter-newrelic/Cargo.toml +++ b/crates/metrics-exporter-newrelic/Cargo.toml @@ -12,13 +12,12 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://docs.rs/metrics-exporter-newrelic" [dependencies] -http = "0.2.6" -metrics = "0.24.2" -metrics-util = "0.20.0" -reqwest = { version = "0.11.9", default-features = false, features = ["json", "rustls-tls"] } -serde = "1.0.136" -serde_derive = "1.0.136" -serde_json = "1.0.78" -thiserror = "1.0.30" -tokio = { version = "1.16.1", default-features = false, features = ["sync"] } -tracing = "0.1.29" +http = "1.5.0" +metrics = "0.24.6" +metrics-util = "0.20.4" +reqwest = { version = "0.13.4", default-features = false, features = ["json", "rustls"] } +serde = { version = "1.0.229", features = ["derive"] } +serde_json = "1.0.151" +thiserror = "2.0.20" +tokio = { version = "1.53.1", default-features = false, features = ["sync"] } +tracing = "0.1.44" diff --git a/crates/metrics-exporter-newrelic/src/client.rs b/crates/metrics-exporter-newrelic/src/client.rs index d88f2fd..38eea1e 100644 --- a/crates/metrics-exporter-newrelic/src/client.rs +++ b/crates/metrics-exporter-newrelic/src/client.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use serde_derive::Serialize; +use serde::Serialize; use serde_json::{json, Value}; use tracing::{instrument, trace}; diff --git a/crates/opinionated_metrics/CHANGELOG.md b/crates/opinionated_metrics/CHANGELOG.md index 1e9a8d7..f165311 100644 --- a/crates/opinionated_metrics/CHANGELOG.md +++ b/crates/opinionated_metrics/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Updated `thiserror` to 2.x. + ## [0.2.0] - 2022-10-26 ### Changed diff --git a/crates/opinionated_metrics/Cargo.toml b/crates/opinionated_metrics/Cargo.toml index aa7f0b8..1fe2d4b 100644 --- a/crates/opinionated_metrics/Cargo.toml +++ b/crates/opinionated_metrics/Cargo.toml @@ -12,9 +12,9 @@ repository = "https://github.com/faradayio/geocode-csv" documentation = "https://docs.rs/opinionated_metrics" [dependencies] -metrics = "0.24.2" +metrics = "0.24.6" metrics-exporter-newrelic = { version = "0.2.0", path = "../metrics-exporter-newrelic" } # We'll add back Prometheus features like http-listener as we support them. -metrics-exporter-prometheus = { version = "0.17.2", default-features = false } -thiserror = "1.0.30" -tracing = "0.1.29" \ No newline at end of file +metrics-exporter-prometheus = { version = "0.18.3", default-features = false } +thiserror = "2.0.20" +tracing = "0.1.44" diff --git a/deny.toml b/deny.toml index 9b1b321..e222d96 100644 --- a/deny.toml +++ b/deny.toml @@ -4,7 +4,11 @@ [advisories] version = 2 -ignore = [] +ignore = [ + # 3.0.0 is a tombstone that only emits compile_error!. 2.0.1 is the last + # real release, and our cache payload format is encoded with it. + { id = "RUSTSEC-2025-0141", reason = "bincode 3.0.0 is not a real upgrade; cache format depends on 2.0.1" }, +] [licenses] version = 2 @@ -14,7 +18,9 @@ allow = [ "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", + "BSL-1.0", "CC0-1.0", + "CDLA-Permissive-2.0", "ISC", "MPL-2.0", "OpenSSL", diff --git a/run_tests_with_secrets.py b/run_tests_with_secrets.py new file mode 100755 index 0000000..d87ba3f --- /dev/null +++ b/run_tests_with_secrets.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +"""Run the full geocode-csv test suite, including the #[ignore]d integration tests. + +The ignored tests exercise real external services: the Smarty API, a BigTable +cache, a local Redis cache, and the bundled libpostal model. We require the +necessary credentials in the environment and make sure a local Redis is +listening before handing off to `cargo test`. Nothing is skipped. +""" + +import os +import shutil +import socket +import subprocess +import sys +import time +from dataclasses import dataclass + +REDIS_HOST = "localhost" +REDIS_PORT = 6379 + +REQUIRED_ENVIRONMENT_VARIABLES = ( + "SMARTY_AUTH_ID", + "SMARTY_AUTH_TOKEN", + "BIGTABLE_CACHE_URL", +) + + +@dataclass +class CargoTest: + """A single `cargo test` invocation: arguments for cargo itself, plus + arguments passed through to the test harness after `--`.""" + + description: str + cargo_arguments: list + test_harness_arguments: list + + def run(self): + command = [ + "cargo", + "test", + *self.cargo_arguments, + "--", + *self.test_harness_arguments, + ] + print(f"\n=== {self.description} ===") + print(f"$ {' '.join(command)}", flush=True) + subprocess.run(command, check=True) + + +class RedisServer: + """The local Redis that the cache integration tests connect to.""" + + def is_listening(self): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as probe: + probe.settimeout(0.5) + return probe.connect_ex((REDIS_HOST, REDIS_PORT)) == 0 + + def ensure_listening(self): + if self.is_listening(): + print(f"Redis already listening on {REDIS_HOST}:{REDIS_PORT}.") + return + if shutil.which("redis-server") is None: + sys.exit( + "redis-server is required for the cache tests but is not installed " + "(try `brew install redis`)." + ) + print("Starting redis-server in the background...") + subprocess.run( + ["redis-server", "--daemonize", "yes", "--port", str(REDIS_PORT)], + check=True, + ) + for _ in range(50): + if self.is_listening(): + print("Redis is up.") + return + time.sleep(0.1) + sys.exit("redis-server was started but never began listening.") + + +def require_environment_variables(): + missing = [ + name + for name in REQUIRED_ENVIRONMENT_VARIABLES + if not os.environ.get(name) + ] + if missing: + sys.exit( + "the following environment variables must be set: " + + ", ".join(missing) + ) + + +def main(): + require_environment_variables() + os.environ.setdefault("RUST_LOG", "info") + + RedisServer().ensure_listening() + + print("\n=== Building workspace ===") + subprocess.run(["cargo", "build", "--workspace"], check=True) + + suites = [ + CargoTest( + description="Unit tests (binary + every crate library), including ignored", + cargo_arguments=["--workspace", "--lib", "--bins"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + description="Doc tests", + cargo_arguments=["--workspace", "--doc"], + test_harness_arguments=[], + ), + CargoTest( + description="Integration: about", + cargo_arguments=["--test", "about"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + description="Integration: duplicate_columns", + cargo_arguments=["--test", "duplicate_columns"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + description="Integration: libpostal", + cargo_arguments=["--test", "libpostal"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + description="Integration: specs (Smarty + Redis)", + cargo_arguments=["--test", "specs"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + description="Integration: server", + cargo_arguments=["--test", "server"], + test_harness_arguments=["--include-ignored"], + ), + CargoTest( + # Serialized to one thread because every test in this file writes to + # the same shared BigTable table. + description="Integration: bigtable_refresh", + cargo_arguments=["--test", "bigtable_refresh"], + test_harness_arguments=["--include-ignored", "--test-threads=1"], + ), + ] + for suite in suites: + suite.run() + + print("\nAll tests passed.") + + +if __name__ == "__main__": + main() diff --git a/src/errors.rs b/src/errors.rs index 54a609f..610898f 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,15 +7,3 @@ use anyhow::Error; pub(crate) fn display_causes_and_backtrace(err: &Error) { eprintln!("{:?}", err); } - -/// Given a [`hyper::Error`], return a human-readable description. -/// -/// This description _should_ be "low-arity", i.e., limited to only a handful of -/// values. We use it when reporting error metrics. -pub(crate) fn hyper_error_description_for_metrics(err: &hyper::Error) -> String { - // HACK: We know that the current version of `hyper` puts a low-arity - // description before ":", but follows it up with variable text. - let display_err = err.to_string(); - let cut_at = display_err.find(':').unwrap_or(display_err.len()); - display_err[..cut_at].to_owned() -} diff --git a/src/geocoders/cache/compression.rs b/src/geocoders/cache/compression.rs deleted file mode 100644 index 16fcdf9..0000000 --- a/src/geocoders/cache/compression.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Basic compression and decompression for cached data, using a custom language -//! model to build a dictionary for `zstd`. - -use metrics::{counter, describe_counter, Unit}; - -use crate::Result; - -/// Interface for compressing and decompressing cache entries. -/// -/// We want to allow alternate implementations in the future. -pub struct CacheCompressor {} - -impl CacheCompressor { - /// Create a new cache compressor and initialize our dictionaries. - pub fn new() -> CacheCompressor { - describe_counter!( - "geocodecsv.compressor_input.bytes_total", - Unit::Bytes, - "Bytes input to compressor" - ); - describe_counter!( - "geocodecsv.compressor_output.bytes_total", - Unit::Bytes, - "Bytes output by compressor" - ); - describe_counter!( - "geocodecsv.decompressor_input.bytes_total", - Unit::Bytes, - "Bytes input to decompressor" - ); - describe_counter!( - "geocodecsv.decompressor_output.bytes_total", - Unit::Bytes, - "Bytes output by decompressor" - ); - - CacheCompressor {} - } - - /// The ID of this type of compression. Must be unique. - pub fn id(&self) -> u8 { - b'N' // "N" means "none". - } - - /// Compress `input` and append to `output`. - pub fn compress(&self, input: &[u8], output: &mut Vec) -> Result<()> { - counter!("geocodecsv.compressor_input.bytes_total", "compressor" => "none") - .increment(input.len() as u64); - output.extend_from_slice(input); - counter!("geocodecsv.compressor_output.bytes_total", "compressor" => "none") - .increment(output.len() as u64); - Ok(()) - } - - /// Decompress `input` and store in `output`. - pub fn decompress(&self, input: &[u8], output: &mut Vec) -> Result<()> { - counter!("geocodecsv.decompressor_input.bytes_total", "compressor" => "none") - .increment(input.len() as u64); - output.extend_from_slice(input); - counter!("geocodecsv.decompressor_output.bytes_total", "compressor" => "none") - .increment(output.len() as u64); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn round_trip_compression() { - let examples: &[&[u8]] = &[ - b"781 Franklin Ave Crown Heights Brooklyn NYC NY 11216 USA", - b"20 W 34th St, New York, NY 10001", - b"", - b"abc123", - ]; - - let cache_compressor = CacheCompressor::new(); - for &example in examples { - let mut compressed = vec![]; - cache_compressor.compress(example, &mut compressed).unwrap(); - let mut decompressed = vec![]; - cache_compressor - .decompress(&compressed, &mut decompressed) - .unwrap(); - assert_eq!(example, decompressed); - } - } -} diff --git a/src/geocoders/cache/entry.rs b/src/geocoders/cache/entry.rs new file mode 100644 index 0000000..43976d7 --- /dev/null +++ b/src/geocoders/cache/entry.rs @@ -0,0 +1,287 @@ +//! On-disk format for a cached geocoding result. +//! +//! The first byte is a format tag. We always write `N`, the legacy tag, so +//! older binaries can still read the `Option>` payload. Refresh +//! state is appended after that payload; old `decode_from_slice` callers ignore +//! the leftover bytes. +//! +//! - `N` plus only the option payload: a pre-refresh row (`refresh_attempts = 0`). +//! - `N` plus the option payload plus metadata: a current row. + +use anyhow::{format_err, Context}; +use metrics::{counter, describe_counter, Unit}; +use serde::{Deserialize, Serialize}; + +use crate::Result; + +use super::refresh::CachedOutcome; + +/// A cached geocoding result, plus how many times we have re-checked a failure. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct CacheEntry { + /// Column values from a successful geocode, or `None` for a cached miss. + pub geocoded: Option>, + + /// How many times we have refreshed this entry and still got a failure. + /// Reset to 0 on a successful geocode. + pub refresh_attempts: u32, +} + +const FORMAT_LEGACY: u8 = b'N'; +const METADATA_VERSION: u8 = 1; + +fn bincode_config() -> impl bincode::config::Config { + bincode::config::standard() + .with_little_endian() + .with_variable_int_encoding() +} + +fn refresh_attempts_from_trailing_bytes(trailing: &[u8]) -> Result { + match trailing { + [] => Ok(0), + [METADATA_VERSION, rest @ ..] if rest.len() >= 4 => Ok(u32::from_le_bytes( + rest[..4].try_into().expect("slice is 4 bytes"), + )), + [METADATA_VERSION, ..] => Err(format_err!("truncated cache refresh metadata")), + [other, ..] => Err(format_err!( + "unknown cache refresh metadata version {other}" + )), + } +} + +impl CacheEntry { + /// Register the cache payload size counters (same names as the old + /// compressor, so existing dashboards keep working). + pub fn describe_metrics() { + describe_counter!( + "geocodecsv.compressor_input.bytes_total", + Unit::Bytes, + "Bytes input to compressor" + ); + describe_counter!( + "geocodecsv.compressor_output.bytes_total", + Unit::Bytes, + "Bytes output by compressor" + ); + describe_counter!( + "geocodecsv.decompressor_input.bytes_total", + Unit::Bytes, + "Bytes input to decompressor" + ); + describe_counter!( + "geocodecsv.decompressor_output.bytes_total", + Unit::Bytes, + "Bytes output by decompressor" + ); + } + + /// Build the entry we write after a geocode. + /// + /// A refreshed failure increments the prior attempt count. A success, or a + /// first-time miss, writes 0. If we refresh a success and the geocoder + /// returns no match, keep the prior success instead of replacing it. + pub fn for_write_back( + geocoded: Option>, + prior_entry: Option<&CacheEntry>, + ) -> CacheEntry { + match (geocoded, prior_entry) { + (None, Some(prior_entry)) if prior_entry.geocoded.is_some() => { + CacheEntry { + geocoded: prior_entry.geocoded.clone(), + refresh_attempts: 0, + } + } + (None, Some(prior_entry)) => CacheEntry { + geocoded: None, + refresh_attempts: prior_entry.refresh_attempts.saturating_add(1), + }, + (geocoded, _) => CacheEntry { + geocoded, + refresh_attempts: 0, + }, + } + } + + /// Whether this entry recorded a successful geocode or a failure to match. + pub fn outcome(&self) -> CachedOutcome { + if self.geocoded.is_some() { + CachedOutcome::Success + } else { + CachedOutcome::Failure + } + } + + /// Encode this entry as an `N`-tagged payload that older binaries can read. + pub fn encode(&self, output: &mut Vec) -> Result<()> { + let mut payload = Vec::with_capacity(256); + bincode::serde::encode_into_std_write( + &self.geocoded, + &mut payload, + bincode_config(), + ) + .context("could not encode value for caching")?; + payload.push(METADATA_VERSION); + payload.extend_from_slice(&self.refresh_attempts.to_le_bytes()); + counter!("geocodecsv.compressor_input.bytes_total", "compressor" => "none") + .increment(payload.len() as u64); + output.push(FORMAT_LEGACY); + output.extend_from_slice(&payload); + counter!("geocodecsv.compressor_output.bytes_total", "compressor" => "none") + .increment((1 + payload.len()) as u64); + Ok(()) + } + + /// Decode a tagged cache payload. + pub fn decode(bytes: &[u8]) -> Result { + let Some((format_tag, payload)) = bytes.split_first() else { + return Err(format_err!("cached value is empty")); + }; + counter!("geocodecsv.decompressor_input.bytes_total", "compressor" => "none") + .increment(payload.len() as u64); + let entry = match *format_tag { + FORMAT_LEGACY => { + let (geocoded, consumed) = bincode::serde::decode_from_slice::< + Option>, + _, + >(payload, bincode_config()) + .context("could not deserialize cached data")?; + CacheEntry { + geocoded, + refresh_attempts: refresh_attempts_from_trailing_bytes( + &payload[consumed..], + )?, + } + } + other => { + return Err(format_err!("unknown cache format {:?}", other)); + } + }; + counter!("geocodecsv.decompressor_output.bytes_total", "compressor" => "none") + .increment(payload.len() as u64); + Ok(entry) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn encode_legacy(geocoded: Option>) -> Vec { + let mut payload = Vec::new(); + bincode::serde::encode_into_std_write( + &geocoded, + &mut payload, + bincode_config(), + ) + .unwrap(); + let mut bytes = vec![FORMAT_LEGACY]; + bytes.extend_from_slice(&payload); + bytes + } + + #[test] + fn round_trip_entry() { + let original = CacheEntry { + geocoded: Some(vec!["a".to_owned(), "b".to_owned()]), + refresh_attempts: 3, + }; + let mut encoded = Vec::new(); + original.encode(&mut encoded).unwrap(); + assert_eq!(encoded[0], FORMAT_LEGACY); + assert_eq!(CacheEntry::decode(&encoded).unwrap(), original); + } + + #[test] + fn round_trip_failure() { + let original = CacheEntry { + geocoded: None, + refresh_attempts: 2, + }; + let mut encoded = Vec::new(); + original.encode(&mut encoded).unwrap(); + assert_eq!(CacheEntry::decode(&encoded).unwrap(), original); + } + + #[test] + fn new_rows_are_readable_by_the_legacy_option_decoder() { + let original = CacheEntry { + geocoded: Some(vec!["x".to_owned()]), + refresh_attempts: 4, + }; + let mut encoded = Vec::new(); + original.encode(&mut encoded).unwrap(); + let (geocoded, _consumed) = bincode::serde::decode_from_slice::< + Option>, + _, + >(&encoded[1..], bincode_config()) + .unwrap(); + assert_eq!(geocoded, Some(vec!["x".to_owned()])); + } + + #[test] + fn legacy_success_decodes_with_zero_attempts() { + let bytes = encode_legacy(Some(vec!["x".to_owned()])); + assert_eq!( + CacheEntry::decode(&bytes).unwrap(), + CacheEntry { + geocoded: Some(vec!["x".to_owned()]), + refresh_attempts: 0, + } + ); + } + + #[test] + fn legacy_failure_decodes_with_zero_attempts() { + let bytes = encode_legacy(None); + assert_eq!( + CacheEntry::decode(&bytes).unwrap(), + CacheEntry { + geocoded: None, + refresh_attempts: 0, + } + ); + } + + #[test] + fn write_back_increments_failure_attempts() { + let prior = CacheEntry { + geocoded: None, + refresh_attempts: 2, + }; + assert_eq!( + CacheEntry::for_write_back(None, Some(&prior)).refresh_attempts, + 3 + ); + assert_eq!( + CacheEntry::for_write_back(Some(vec!["ok".to_owned()]), Some(&prior)) + .refresh_attempts, + 0 + ); + assert_eq!(CacheEntry::for_write_back(None, None).refresh_attempts, 0); + } + + #[test] + fn write_back_keeps_a_success_if_refresh_fails() { + let prior = CacheEntry { + geocoded: Some(vec!["kept".to_owned()]), + refresh_attempts: 0, + }; + assert_eq!( + CacheEntry::for_write_back(None, Some(&prior)), + CacheEntry { + geocoded: Some(vec!["kept".to_owned()]), + refresh_attempts: 0, + } + ); + } + + #[test] + fn empty_payload_is_an_error() { + assert!(CacheEntry::decode(&[]).is_err()); + } + + #[test] + fn unknown_format_is_an_error() { + assert!(CacheEntry::decode(&[b'Z', 1, 2, 3]).is_err()); + } +} diff --git a/src/geocoders/cache/mod.rs b/src/geocoders/cache/mod.rs index b31fc65..24edf4e 100644 --- a/src/geocoders/cache/mod.rs +++ b/src/geocoders/cache/mod.rs @@ -2,26 +2,30 @@ //! enough to handle a cluster of geocode-csv clients running at full speed). use std::fmt::{self, Write}; +use std::time::SystemTime; -use anyhow::{format_err, Context}; +use anyhow::format_err; use async_trait::async_trait; use metrics::{counter, describe_counter}; -use crate::{addresses::Address, key_value_stores::KeyValueStore, Result}; +use crate::{ + addresses::Address, + key_value_stores::{CachedValue, KeyValueStore}, + Result, +}; -use self::compression::CacheCompressor; +use self::entry::CacheEntry; +use self::refresh::RefreshPolicy; use super::{Geocoded, Geocoder}; -mod compression; +mod entry; +pub mod refresh; /// A Redis-based caching layer. /// /// This wraps another geocoder, and caches calls in Redis. pub struct Cache { - /// Compressor we use to compress cached data. - compressor: CacheCompressor, - /// Our key/value store. key_value_store: Box, @@ -37,10 +41,20 @@ pub struct Cache { /// Should we geocode cache misses? cache_hits_only: bool, + /// Optional policy for automatically refreshing stale cache entries. + refresh_policy: Option, + /// The column names we output. column_names: Vec, } +/// An address we need to send to the inner geocoder. +struct CacheMiss { + offset: usize, + address: Address, + prior_entry: Option, +} + impl Cache { /// Create a new cache wrapping `inner`, and storing values in /// `key_value_store`. @@ -49,12 +63,22 @@ impl Cache { inner: Box, output_keys: bool, cache_hits_only: bool, + refresh_policy: Option, ) -> Result { describe_counter!("geocodecsv.cache_hits.total", "Addresses found in cache"); describe_counter!( "geocodecsv.cache_misses.total", "Addresses not found in cache" ); + describe_counter!( + "geocodecsv.cache.refreshed.total", + "Cache entries refreshed (treated as a miss) by the refresh policy" + ); + describe_counter!( + "geocodecsv.cache.refresh_results.total", + "Outcomes of a refresh, labeled by the prior and new outcome" + ); + CacheEntry::describe_metrics(); let inner_cache_prefix = inner.cache_prefix(); let mut column_names = inner.column_names().to_owned(); @@ -63,13 +87,13 @@ impl Cache { } Ok(Cache { - compressor: CacheCompressor::new(), key_value_store, inner, inner_cache_prefix, output_keys, column_names, cache_hits_only, + refresh_policy, }) } } @@ -116,72 +140,66 @@ impl Geocoder for Cache { for key in &keys { pipelined_get.add_get(key.to_owned()); } - let cache_results: Vec>> = pipelined_get.execute().await?; - - // Our standard bincode configuration. - let bincode_config = bincode::config::standard() - .with_little_endian() - .with_variable_int_encoding(); + let cache_results: Vec> = pipelined_get.execute().await?; // Unpack our results, recording any cache hits, and building a list of // the misses to forward to our inner geocoder. let mut cache_misses = Vec::with_capacity(addresses.len()); - let mut cache_miss_offsets = Vec::with_capacity(addresses.len()); - let mut decompressed = Vec::with_capacity(256); + // Compute the current time once for the whole batch, so every entry's + // refresh decision is made against a single consistent `now`. + let now = SystemTime::now(); for (i, cached_value) in cache_results.iter().enumerate() { - if let Some(cache_hit) = cached_value { - // We found this result in the cache. - decompressed.clear(); - if cache_hit[0] != self.compressor.id() { + let Some(cached_value) = cached_value else { + cache_misses.push(CacheMiss { + offset: i, + address: addresses[i].clone(), + prior_entry: None, + }); + continue; + }; + + let entry = CacheEntry::decode(&cached_value.bytes)?; + + if let (Some(refresh_policy), Some(age), false) = + (&self.refresh_policy, cached_value.age, self.cache_hits_only) + { + if refresh_policy.should_refresh(&keys[i], &entry, age, now) { + counter!("geocodecsv.cache.refreshed.total", "outcome" => entry.outcome().as_metric_label()) + .increment(1); + cache_misses.push(CacheMiss { + offset: i, + address: addresses[i].clone(), + prior_entry: Some(entry), + }); + continue; + } + } + + if let Some(column_values) = entry.geocoded { + if column_values.len() != self.inner.column_names().len() { return Err(format_err!( - "unknown compression format {:?}", - cache_hit[0] + "cannot return {:?} for columns {:?} because it has the wrong number of values", + column_values, + self.column_names(), )); } - self.compressor - .decompress(&cache_hit[1..], &mut decompressed)?; - let (cache_hit, _) = bincode::serde::decode_from_slice::< - Option>, - _, - >(&decompressed, bincode_config) - .context("could not deserialize cached data")?; - - // Here, a `None` value represents a cached geocoding _failure_. - // If a previous attempt failed, we expect that more recent ones - // may fail, too. - // - // TODO: Explain this better. - if let Some(cache_hit) = cache_hit { - if cache_hit.len() != self.inner.column_names().len() { - return Err(format_err!( - "cannot return {:?} for columns {:?} because it has the wrong number of values", - cache_hit, - self.column_names(), - )); - } - let candidate = Geocoded { - column_values: cache_hit, - }; - if candidate.contains_null_bytes() { - // This result contains old buggy data. Treat as a cache - // miss. - cache_misses.push(addresses[i].clone()); - cache_miss_offsets.push(i); - counter!("geocodecsv.cache_hits.total", "geocoding_result" => "invalid_data") - .increment(1); - } else { - geocoded[i] = Some(candidate); - counter!("geocodecsv.cache_hits.total", "geocoding_result" => "found") - .increment(1); - } + let candidate = Geocoded { column_values }; + if candidate.contains_null_bytes() { + cache_misses.push(CacheMiss { + offset: i, + address: addresses[i].clone(), + prior_entry: None, + }); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "invalid_data") + .increment(1); } else { - counter!("geocodecsv.cache_hits.total", "geocoding_result" => "unknown_address") + geocoded[i] = Some(candidate); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "found") .increment(1); } } else { - // We need to forward this result. - cache_misses.push(addresses[i].clone()); - cache_miss_offsets.push(i); + counter!("geocodecsv.cache_hits.total", "geocoding_result" => "unknown_address") + .increment(1); } } counter!("geocodecsv.cache_misses.total").increment(cache_misses.len() as u64); @@ -191,34 +209,42 @@ impl Geocoder for Cache { // Alternatively, if the caller specified --cache-hits-only, // we should avoid geocoding any remaining addresses. if !cache_misses.is_empty() && !self.cache_hits_only { - // Pass remainder through to our inner geocoder. + let cache_miss_addresses = cache_misses + .iter() + .map(|cache_miss| cache_miss.address.clone()) + .collect::>(); let cache_miss_retries = - self.inner.geocode_addresses(&cache_misses).await?; + self.inner.geocode_addresses(&cache_miss_addresses).await?; - // Record our successes (and build a Redis command to store them). let mut pipelined_set = self.key_value_store.new_pipelined_set(); let mut encoded = Vec::with_capacity(256); - for (i, retry) in cache_miss_offsets - .into_iter() - .zip(cache_miss_retries.into_iter()) + for (cache_miss, retry) in cache_misses.into_iter().zip(cache_miss_retries) { - // Encode our value for caching. - let value = retry.as_ref().map(|retry| &retry.column_values); - encoded.clear(); - bincode::encode_into_std_write(value, &mut encoded, bincode_config) - .context("could not encode value for caching")?; - - // Compress our encoded value and add it to our pipeline set. - let mut compressed = Vec::with_capacity(256); - compressed.push(self.compressor.id()); - self.compressor.compress(&encoded, &mut compressed)?; - pipelined_set.add_set(keys[i].clone(), compressed); + if let Some(prior_entry) = &cache_miss.prior_entry { + counter!( + "geocodecsv.cache.refresh_results.total", + "from" => prior_entry.outcome().as_metric_label(), + "to" => if retry.is_some() { "success" } else { "failure" } + ) + .increment(1); + } - // Add out geocoding result to our output. - geocoded[i] = retry; + let entry = CacheEntry::for_write_back( + retry.as_ref().map(|retry| retry.column_values.clone()), + cache_miss.prior_entry.as_ref(), + ); + encoded.clear(); + entry.encode(&mut encoded)?; + pipelined_set.add_set( + keys[cache_miss.offset].clone(), + std::mem::take(&mut encoded), + ); + + geocoded[cache_miss.offset] = entry + .geocoded + .map(|column_values| Geocoded { column_values }); } - // Write our new results back to our cache. pipelined_set.execute().await?; } diff --git a/src/geocoders/cache/refresh.rs b/src/geocoders/cache/refresh.rs new file mode 100644 index 0000000..e086934 --- /dev/null +++ b/src/geocoders/cache/refresh.rs @@ -0,0 +1,305 @@ +//! Policy for automatically refreshing stale cache entries. +//! +//! Each entry carries its own schedule (`refresh_attempts` plus its write age). +//! Failures back off exponentially and stop after `failure_max_attempts`. +//! Successes refresh only if `success_period` is set. A per-key-per-day rate +//! cap bounds spend so a bulk-loaded backlog does not all come due on day one. + +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use super::entry::CacheEntry; + +/// Whether a cached entry recorded a successful geocode or a failure to match. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum CachedOutcome { + Success, + Failure, +} + +impl CachedOutcome { + /// A low-arity label for use with metrics. + pub fn as_metric_label(self) -> &'static str { + match self { + CachedOutcome::Success => "success", + CachedOutcome::Failure => "failure", + } + } +} + +/// Named arguments for [`RefreshPolicy::new`]. +pub struct RefreshPolicyConfig { + /// Base wait before the first refresh of a cached failure. + pub failure_period: Option, + + /// Stop re-checking a failure after this many refreshes. + pub failure_max_attempts: u32, + + /// If set, re-check a successful geocode after this age. + pub success_period: Option, + + /// Fraction of eligible keys to refresh on a given day, in `(0, 1]`. + pub rate: f64, +} + +/// Policy for automatically refreshing stale cache entries. +#[derive(Debug, Clone, Copy)] +pub struct RefreshPolicy { + failure_period: Option, + failure_max_attempts: u32, + success_period: Option, + rate: f64, +} + +impl RefreshPolicy { + /// Build a policy. `rate` must be in `(0, 1]`. + pub fn new(config: RefreshPolicyConfig) -> RefreshPolicy { + debug_assert!( + config.rate > 0.0 && config.rate <= 1.0, + "refresh rate must be in (0, 1], got {}", + config.rate + ); + RefreshPolicy { + failure_period: config.failure_period, + failure_max_attempts: config.failure_max_attempts, + success_period: config.success_period, + rate: config.rate, + } + } + + /// Should this cached `entry` be treated as a miss at wall-clock `now`? + pub fn should_refresh( + &self, + cache_key: &str, + entry: &CacheEntry, + age: Duration, + now: SystemTime, + ) -> bool { + if !self.is_eligible(entry, age) { + return false; + } + let day_number = now + .duration_since(UNIX_EPOCH) + .expect("now is after the UNIX epoch") + .as_secs() + / (24 * 60 * 60); + stable_fraction(&format!("{cache_key}:{day_number}")) < self.rate + } + + fn is_eligible(&self, entry: &CacheEntry, age: Duration) -> bool { + match entry.outcome() { + CachedOutcome::Success => self + .success_period + .map(|period| age >= period) + .unwrap_or(false), + CachedOutcome::Failure => { + let Some(period) = self.failure_period else { + return false; + }; + if entry.refresh_attempts >= self.failure_max_attempts { + return false; + } + age >= backoff_wait(period, entry.refresh_attempts) + } + } + } +} + +/// Wait before the next refresh: `period * 2^refresh_attempts`. +fn backoff_wait(period: Duration, refresh_attempts: u32) -> Duration { + period.saturating_mul(1u32 << refresh_attempts.min(31)) +} + +/// Map a string to a stable pseudo-random fraction in `[0.0, 1.0)`. +/// +/// Deriving the decision from the key (and, at the call site, the day) means +/// the same entry makes the same decision on every read that day. +fn stable_fraction(material: &str) -> f64 { + use sha2::{Digest, Sha256}; + let digest = Sha256::digest(material.as_bytes()); + let leading = + u64::from_be_bytes(digest[..8].try_into().expect("SHA-256 is 32 bytes")); + leading as f64 / 2f64.powi(64) +} + +#[cfg(test)] +mod tests { + use super::*; + + const DAY: Duration = Duration::from_secs(24 * 60 * 60); + + fn now() -> SystemTime { + UNIX_EPOCH + 20_000 * DAY + } + + fn failure(refresh_attempts: u32) -> CacheEntry { + CacheEntry { + geocoded: None, + refresh_attempts, + } + } + + fn success() -> CacheEntry { + CacheEntry { + geocoded: Some(vec!["ok".to_owned()]), + refresh_attempts: 0, + } + } + + fn policy(config: RefreshPolicyConfig) -> RefreshPolicy { + RefreshPolicy::new(config) + } + + fn failures_only(rate: f64) -> RefreshPolicy { + policy(RefreshPolicyConfig { + failure_period: Some(90 * DAY), + failure_max_attempts: 4, + success_period: None, + rate, + }) + } + + #[test] + fn failure_not_eligible_before_base_period() { + let refresh_policy = failures_only(1.0); + assert!(!refresh_policy.should_refresh("k", &failure(0), 89 * DAY, now(),)); + assert!(refresh_policy.should_refresh("k", &failure(0), 90 * DAY, now(),)); + } + + #[test] + fn failure_backoff_doubles_each_attempt() { + let refresh_policy = failures_only(1.0); + assert!(!refresh_policy.should_refresh("k", &failure(1), 179 * DAY, now(),)); + assert!(refresh_policy.should_refresh("k", &failure(1), 180 * DAY, now(),)); + assert!(!refresh_policy.should_refresh("k", &failure(2), 359 * DAY, now(),)); + assert!(refresh_policy.should_refresh("k", &failure(2), 360 * DAY, now(),)); + } + + #[test] + fn failure_stops_at_max_attempts() { + let refresh_policy = failures_only(1.0); + assert!(!refresh_policy.should_refresh("k", &failure(4), 10_000 * DAY, now(),)); + } + + #[test] + fn failures_ignored_when_period_is_none() { + let refresh_policy = policy(RefreshPolicyConfig { + failure_period: None, + failure_max_attempts: 4, + success_period: Some(365 * DAY), + rate: 1.0, + }); + assert!(!refresh_policy.should_refresh("k", &failure(0), 10_000 * DAY, now(),)); + } + + #[test] + fn successes_never_refresh_without_a_period() { + let refresh_policy = failures_only(1.0); + assert!(!refresh_policy.should_refresh("k", &success(), 10_000 * DAY, now(),)); + } + + #[test] + fn successes_refresh_after_period() { + let refresh_policy = policy(RefreshPolicyConfig { + failure_period: None, + failure_max_attempts: 0, + success_period: Some(365 * DAY), + rate: 1.0, + }); + assert!(!refresh_policy.should_refresh("k", &success(), 364 * DAY, now(),)); + assert!(refresh_policy.should_refresh("k", &success(), 365 * DAY, now(),)); + } + + #[test] + fn rate_one_refreshes_every_eligible_key() { + let refresh_policy = failures_only(1.0); + let released = (0..1000) + .filter(|i| { + refresh_policy.should_refresh( + &format!("key-{i}"), + &failure(0), + 10_000 * DAY, + now(), + ) + }) + .count(); + assert_eq!(released, 1000); + } + + #[test] + fn rate_cap_bounds_spend() { + let refresh_policy = failures_only(0.1); + let released = (0..1000) + .filter(|i| { + refresh_policy.should_refresh( + &format!("key-{i}"), + &failure(0), + 10_000 * DAY, + now(), + ) + }) + .count(); + assert!( + (50..150).contains(&released), + "expected ~100/1000 at rate 0.1, got {released}" + ); + } + + #[test] + fn decision_is_stable_for_a_key_on_the_same_day() { + let refresh_policy = failures_only(0.5); + let first = refresh_policy.should_refresh( + "123 main st", + &failure(0), + 10_000 * DAY, + now(), + ); + for _ in 0..100 { + assert_eq!( + refresh_policy.should_refresh( + "123 main st", + &failure(0), + 10_000 * DAY, + now(), + ), + first, + ); + } + } + + #[test] + fn decision_can_change_on_a_new_day() { + let refresh_policy = failures_only(0.5); + let mut saw_difference = false; + for i in 0..200 { + let cache_key = format!("key-{i}"); + let today = refresh_policy.should_refresh( + &cache_key, + &failure(0), + 10_000 * DAY, + now(), + ); + let tomorrow = refresh_policy.should_refresh( + &cache_key, + &failure(0), + 10_000 * DAY, + now() + DAY, + ); + if today != tomorrow { + saw_difference = true; + break; + } + } + assert!( + saw_difference, + "hashing the day into the key should reshuffle some decisions" + ); + } + + #[test] + fn stable_fraction_is_in_range() { + for i in 0..1000 { + let fraction = stable_fraction(&format!("key-{i}:100")); + assert!((0.0..1.0).contains(&fraction)); + } + } +} diff --git a/src/geocoders/libpostal.rs b/src/geocoders/libpostal.rs index afc1450..a3516cf 100644 --- a/src/geocoders/libpostal.rs +++ b/src/geocoders/libpostal.rs @@ -10,36 +10,32 @@ use crate::{addresses::Address, Result}; use super::{Geocoded, Geocoder}; pub(crate) static COLUMN_NAMES: &[&str] = &[ - // From - // https://github.com/OpenCageData/address-formatting/blob/master/conf/components.yaml. - "archipelago", + // These are the address-component labels that libpostal's address parser can + // actually emit, as defined in + // `crates/libpostal-sys/libpostal/src/address_parser.h`. Earlier versions of + // this list were copied from OpenCage's address-_formatting_ vocabulary + // (components.yaml), which is a different vocabulary: it includes names like + // `county`, `neighbourhood`, and `hamlet` that libpostal's parser never + // produces (it aliases those to `state_district`, `suburb`, and `city` + // respectively before training). We omit the non-address parser labels + // `category`, `near`, `website`, and `phone`. + "building", "city", - "continent", - "country_code", - "country", - "county", - "hamlet", - "house_number", - "house", - "island", - "municipality", - "neighbourhood", - "postal_city", - "postcode", - "region", - "road", - "state_district", - "state", - "village", - // Additional fields from https://github.com/openvenues/libpostal. - "category", "city_district", + "country", "country_region", "entrance", + "house", + "house_number", + "island", "level", - "near", + "metro_station", "po_box", + "postcode", + "road", "staircase", + "state", + "state_district", "suburb", "unit", "world_region", diff --git a/src/geocoders/mod.rs b/src/geocoders/mod.rs index 394b58d..b095de4 100644 --- a/src/geocoders/mod.rs +++ b/src/geocoders/mod.rs @@ -1,12 +1,10 @@ //! Geocoding backends. -use std::{fmt, str::FromStr, sync::Arc}; +use std::{fmt, str::FromStr}; use anyhow::format_err; use async_trait::async_trait; use csv::StringRecord; -use hyper::{client::HttpConnector, Client}; -use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -22,21 +20,11 @@ pub mod normalizer; pub mod paired; pub mod smarty; -/// A `hyper` client shared between multiple workers. -pub type SharedHttpClient = Arc>>; - -pub fn shared_http_client(concurrency: usize) -> SharedHttpClient { - // Create a shared `hyper::Client` with a connection pool, so that we can - // use keep-alive. - Arc::new( - Client::builder().pool_max_idle_per_host(concurrency).build( - HttpsConnectorBuilder::new() - .with_native_roots() - .https_only() - .enable_http2() - .build(), - ), - ) +pub fn shared_http_client(concurrency: usize) -> reqwest::Client { + reqwest::Client::builder() + .pool_max_idle_per_host(concurrency) + .build() + .expect("failed to build HTTP client") } /// What match candidates should we output when geocoding? diff --git a/src/geocoders/normalizer.rs b/src/geocoders/normalizer.rs index 2ec7dd7..2f79c29 100644 --- a/src/geocoders/normalizer.rs +++ b/src/geocoders/normalizer.rs @@ -122,11 +122,19 @@ fn normalized_to_address( // PO boxes supposedly go before street addresses if both are present. append_component(component_indices, &mut street, normalized, "po_box"); append_component(component_indices, &mut street, normalized, "house_number"); - // "house" is supposedly things like "Empire State Building". + // "building" and "house" are both venue/building names like "Empire State + // Building". We keep them so we don't drop a meaningful part of the line. + append_component(component_indices, &mut street, normalized, "building"); append_component(component_indices, &mut street, normalized, "house"); append_component(component_indices, &mut street, normalized, "road"); - // "unit" is "appt A", or things like that. Lightly normalized. + // "unit", "level" (e.g. "3rd Floor"), "staircase", and "entrance" are all + // secondary-unit designators. libpostal parses them out, and we used to drop + // everything but "unit", which silently discarded floor/staircase/entrance + // information before it reached our downstream geocoder. append_component(component_indices, &mut street, normalized, "unit"); + append_component(component_indices, &mut street, normalized, "level"); + append_component(component_indices, &mut street, normalized, "staircase"); + append_component(component_indices, &mut street, normalized, "entrance"); // Handle our city. "city_district" may be something like // "Brooklyn", with "city" either empty, or containing something @@ -152,6 +160,9 @@ fn normalized_to_address( append_component(component_indices, &mut city, normalized, "suburb"); append_component(component_indices, &mut city, normalized, "city_district"); append_component(component_indices, &mut city, normalized, "city"); + // "island" (e.g. "Maui") is occasionally the most specific locality we have, + // so we keep it as part of the city rather than dropping it. + append_component(component_indices, &mut city, normalized, "island"); // Handle our state. let mut state = String::with_capacity(16); diff --git a/src/geocoders/smarty/client.rs b/src/geocoders/smarty/client.rs index 825168f..42110fb 100644 --- a/src/geocoders/smarty/client.rs +++ b/src/geocoders/smarty/client.rs @@ -4,16 +4,13 @@ use std::time::Instant; use std::{env, str}; use anyhow::{format_err, Context}; -use futures::stream::StreamExt; -use hyper::{Body, Request}; use metrics::{counter, describe_histogram, histogram, Unit}; use serde::{Deserialize, Serialize}; use tracing::{error, instrument}; use url::Url; use crate::addresses::Address; -use crate::errors::hyper_error_description_for_metrics; -use crate::geocoders::{MatchStrategy, SharedHttpClient}; +use crate::geocoders::MatchStrategy; use crate::unpack_vec::unpack_vec; use crate::Result; @@ -65,15 +62,13 @@ pub struct AddressResponse { pub fields: serde_json::Value, } -/// The real implementation of `S. pub struct SmartyClient { credentials: Credentials, - client: SharedHttpClient, + client: reqwest::Client, } impl SmartyClient { - /// Create a new Smarty client. - pub fn new(client: SharedHttpClient) -> Result { + pub fn new(client: reqwest::Client) -> Result { describe_histogram!( "geocodecsv.smart.geocode_request.duration_seconds", Unit::Seconds, @@ -86,7 +81,6 @@ impl SmartyClient { }) } - /// Geocode addresses using Smarty. #[instrument( name = "SmartyClient::street_addresses", level="debug", @@ -98,98 +92,74 @@ impl SmartyClient { requests: Vec, license: String, ) -> Result>> { - street_addresses_impl( - self.credentials.clone(), - self.client.clone(), - requests, - license, - ) - .await - } -} - -/// The real implementation of `street_addresses`. -async fn street_addresses_impl( - credentials: Credentials, - client: SharedHttpClient, - requests: Vec, - license: String, -) -> Result>> { - let start = Instant::now(); - - // Build our URL. - let mut url = Url::parse("https://api.smartystreets.com/street-address")?; - url.query_pairs_mut() - .append_pair("auth-id", &credentials.auth_id) - .append_pair("auth-token", &credentials.auth_token) - .append_pair("license", &license) - .finish(); - - // Make the geocoding request. - let req = Request::builder() - .method("POST") - .uri(url.as_str()) - .header("Content-Type", "application/json; charset=utf-8") - .body(Body::from(serde_json::to_string(&requests)?))?; - let res = match client.request(req).await { - Ok(res) => res, - Err(err) => { - // Errors that occur here are being reported by our local HTTP - // stack, not the remote server. - let desc = hyper_error_description_for_metrics(&err); - counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => desc).increment(1); - return Err(err.into()); - } - }; - let status = res.status(); - let mut body = res.into_body(); - let mut body_data = vec![]; - while let Some(chunk_result) = body.next().await { - let chunk = chunk_result?; - body_data.extend(&chunk[..]); - } - - histogram!("geocodecsv.smarty.geocode_request.duration_seconds") - .record((Instant::now() - start).as_secs_f64()); - - // Check the request status. - if status.is_success() { - let resps: Vec = serde_json::from_slice(&body_data)?; - Ok(unpack_vec(resps, requests.len(), |resp| resp.input_index)?) - } else { - // This error was reported by the remote server. - - // Add error to metrics. - counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => status.to_string()).increment(1); - - // Log information about bad street fields, if we can. - if status == 422 { - if let Ok(error_response) = - serde_json::from_slice::(&body_data) - { - let mut missing_street = false; - for error in error_response.errors { - if error.name == "us-street-api:query-missing-street" { - missing_street = true; - break; - } - } - if missing_street { - let streets = requests + let start = Instant::now(); + + let mut url = Url::parse("https://api.smartystreets.com/street-address")?; + url.query_pairs_mut() + .append_pair("auth-id", &self.credentials.auth_id) + .append_pair("auth-token", &self.credentials.auth_token) + .append_pair("license", &license) + .finish(); + + let res = match self.client.post(url.as_str()).json(&requests).send().await { + Ok(res) => res, + Err(err) => { + let desc = reqwest_error_description_for_metrics(&err); + counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => desc).increment(1); + return Err(err).context("smarty request failed"); + } + }; + let status = res.status(); + let body_data = res + .bytes() + .await + .context("failed to read smarty response body")?; + + histogram!("geocodecsv.smarty.geocode_request.duration_seconds") + .record((Instant::now() - start).as_secs_f64()); + + if status.is_success() { + let resps: Vec = serde_json::from_slice(&body_data)?; + Ok(unpack_vec(resps, requests.len(), |resp| resp.input_index)?) + } else { + counter!("geocodecsv.selected_errors.count", "component" => "smarty", "cause" => status.to_string()).increment(1); + + if status == 422 { + if let Ok(error_response) = + serde_json::from_slice::(&body_data) + { + if error_response + .errors .iter() - .map(|req| req.address.street.to_owned()) - .collect::>(); - error!("At least one missing street in: {:?}", streets); + .any(|e| e.name == "us-street-api:query-missing-street") + { + let streets = requests + .iter() + .map(|req| req.address.street.to_owned()) + .collect::>(); + error!("At least one missing street in: {:?}", streets); + } } } + + Err(format_err!( + "geocoding error: {}\n{}", + status, + String::from_utf8_lossy(&body_data), + )) } + } +} - // Convert to a Rust error. - Err(format_err!( - "geocoding error: {}\n{}", - status, - String::from_utf8_lossy(&body_data), - )) +fn reqwest_error_description_for_metrics(err: &reqwest::Error) -> &'static str { + if err.is_timeout() { + "timeout" + } else if err.is_connect() { + "connect" + } else if err.is_request() { + "request" + } else { + "other" } } diff --git a/src/geocoders/smarty/mod.rs b/src/geocoders/smarty/mod.rs index 083ddc5..daef95f 100644 --- a/src/geocoders/smarty/mod.rs +++ b/src/geocoders/smarty/mod.rs @@ -13,7 +13,7 @@ use self::{ structure::Structure, }; -use super::{Geocoded, Geocoder, MatchStrategy, SharedHttpClient}; +use super::{Geocoded, Geocoder, MatchStrategy}; pub mod client; mod structure; @@ -47,7 +47,7 @@ impl Smarty { match_strategy: MatchStrategy, license: String, rate_limiter: Option>, - http_client: SharedHttpClient, + http_client: reqwest::Client, ) -> Result { describe_counter!("geocodecsv.addresses_geocoded.total", "Addresses geocoded"); diff --git a/src/key_value_stores/bigtable.rs b/src/key_value_stores/bigtable.rs index 07be6ef..b6bcef6 100644 --- a/src/key_value_stores/bigtable.rs +++ b/src/key_value_stores/bigtable.rs @@ -8,22 +8,22 @@ use std::{ use anyhow::{format_err, Context}; use async_trait::async_trait; -use bigtable_rs::{ - bigtable::{self, BigTable as BigTableClient, BigTableConnection}, - google::bigtable::v2::{ - mutate_rows_request::Entry, - mutation::{self, SetCell}, - row_filter::{Chain, Filter}, - MutateRowsRequest, Mutation, ReadRowsRequest, RowFilter, RowSet, - }, +use bigtable_rs::bigtable::{self, BigTable as BigTableClient, BigTableConnection}; +use googleapis_tonic_google_bigtable_v2::google::bigtable::v2::{ + mutate_rows_request::Entry, + mutation::{self, SetCell}, + row_filter::{Chain, Filter}, + MutateRowsRequest, Mutation, ReadRowsRequest, RowFilter, RowSet, }; -use metrics::{counter, describe_counter, describe_histogram, histogram, Unit}; +use metrics::{counter, describe_histogram, histogram, Unit}; use tracing::{instrument, trace}; use url::Url; use crate::{pipeline::CONCURRENCY, Result}; -use super::{KeyValueStore, KeyValueStoreNew, PipelinedGet, PipelinedSet}; +use super::{ + CachedValue, KeyValueStore, KeyValueStoreNew, PipelinedGet, PipelinedSet, +}; const GEOCODE_CSV_FAMILY_NAME: &str = "geocode_csv"; const GEOCODE_CSV_COLUMN_NAME: &[u8] = b"v"; @@ -35,15 +35,6 @@ struct BigTableConfig { table_name: String, } -/// Configuration for BigTable cache eviction. -#[derive(Debug, Clone)] -pub struct EvictionConfig { - /// Minimum age in seconds before entries can be evicted. - pub min_age_seconds: u64, - /// Probability (0.0 to 1.0) of evicting eligible entries. - pub eviction_rate: f64, -} - impl BigTableConfig { /// Parse our own fake "bigtable:" URL schema into configuration information. fn from_url(url: &Url) -> Result { @@ -99,9 +90,6 @@ pub struct BigTable { /// The prefix to use for our keys. key_prefix: String, - - /// Optional eviction configuration. - eviction_config: Option, } impl BigTable { @@ -109,11 +97,6 @@ impl BigTable { fn client(&self) -> BigTableClient { self.connection.client() } - - /// Set the eviction configuration for this BigTable instance. - pub fn set_eviction_config(&mut self, config: EvictionConfig) { - self.eviction_config = Some(config); - } } impl KeyValueStore for BigTable { @@ -155,15 +138,6 @@ impl KeyValueStoreNew for BigTable { Unit::Seconds, "Time required for BigTable MutateRows requests" ); - describe_counter!( - "geocodecsv.bigtable.random_eviction.evicted_entries.total", - "Number of cache entries evicted due to random eviction policy" - ); - describe_counter!( - "geocodecsv.bigtable.random_eviction.eligible_entries.total", - "Number of cache entries that were eligible for eviction (met age requirement)" - ); - let config = BigTableConfig::from_url(&url)?; let connection = BigTableConnection::new( &config.project_id, @@ -179,7 +153,6 @@ impl KeyValueStoreNew for BigTable { connection, table_name: config.table_name, key_prefix, - eviction_config: None, }) } } @@ -199,9 +172,15 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { } #[instrument(name = "PipelinedGet::execute", level = "trace", skip_all, fields(row_keys.len = self.row_keys.len()))] - async fn execute(&self) -> Result>>> { + async fn execute(&self) -> Result>> { let start = Instant::now(); + // The current time, used to compute each entry's age once per batch. + let now_micros = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_micros() as i64; + // Build and run our query. let mut client = self.bigtable.client(); let request = ReadRowsRequest { @@ -260,7 +239,8 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { // indices. We have to be careful because keys might appear more than // once. Ideally our callers wouldn't do that, but if they do, we need // to handle it. - let mut result: Vec>> = vec![None; self.row_keys.len()]; + let mut result: Vec> = + (0..self.row_keys.len()).map(|_| None).collect(); let mut row_key_indices = HashMap::, Vec>::new(); for (idx, row_key) in self.row_keys.iter().enumerate() { row_key_indices @@ -296,70 +276,19 @@ impl<'store> PipelinedGet<'store> for BigTablePipelinedGet<'store> { )); } - // Check if this entry should be evicted based on age and probability. - let should_evict = if let Some(ref config) = - self.bigtable.eviction_config - { - let now_micros = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_micros() as i64; - - let age_micros = now_micros - row_cell.timestamp_micros; - let age_seconds = age_micros / 1_000_000; - - if age_seconds >= config.min_age_seconds as i64 { - // Entry is old enough, check probability - use rand::Rng; - let mut rng = rand::thread_rng(); - let random_value: f64 = rng.gen(); - random_value < config.eviction_rate - } else { - false - } - } else { - false - }; - - if should_evict { - counter!( - "geocodecsv.bigtable.random_eviction.evicted_entries.total" - ) - .increment(1); - trace!( - "evicting cache entry for key {:?}, age: {} seconds", - String::from_utf8_lossy(&key), - (std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_micros() as i64 - - row_cell.timestamp_micros) - / 1_000_000 - ); - // Don't store the value in result, effectively treating it as a cache miss - } else { - // If eviction config exists and entry was old enough, count as eligible - if let Some(ref config) = self.bigtable.eviction_config { - let now_micros = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_micros() - as i64; - let age_micros = now_micros - row_cell.timestamp_micros; - let age_seconds = age_micros / 1_000_000; - - if age_seconds >= config.min_age_seconds as i64 { - counter!("geocodecsv.bigtable.random_eviction.eligible_entries.total").increment(1); - } - } - - // Write this match to our result array. - let indices = row_key_indices - .get(&key) - .expect("we should always have a known key"); - for idx in indices { - result[*idx] = Some(row_cell.value.clone()); - } + // Record the entry's age so the cache layer can decide whether + // it is stale enough to refresh. + let age = Duration::from_micros( + (now_micros - row_cell.timestamp_micros).max(0) as u64, + ); + let indices = row_key_indices + .get(&key) + .expect("we should always have a known key"); + for idx in indices { + result[*idx] = Some(CachedValue { + bytes: row_cell.value.clone(), + age: Some(age), + }); } } } @@ -388,6 +317,7 @@ impl<'store> PipelinedSet<'store> for BigTablePipelinedSet<'store> { value, })), }], + idempotency: None, }) } @@ -436,5 +366,6 @@ fn bigtable_error_cause_for_metrics(err: &bigtable::Error) -> Cow<'static, str> bigtable::Error::ChunkError(_) => Cow::Borrowed("chunk"), bigtable::Error::GCPAuthError(_) => Cow::Borrowed("gcp auth"), bigtable::Error::MetadataError(_) => Cow::Borrowed("metadata error"), + bigtable::Error::InvalidArgument(_) => Cow::Borrowed("invalid argument"), } } diff --git a/src/key_value_stores/mod.rs b/src/key_value_stores/mod.rs index 4343ac8..7a954df 100644 --- a/src/key_value_stores/mod.rs +++ b/src/key_value_stores/mod.rs @@ -1,5 +1,7 @@ //! Common interface to key/value stores used for caching. +use std::time::Duration; + use anyhow::format_err; use async_trait::async_trait; use url::Url; @@ -9,6 +11,18 @@ use crate::Result; pub mod bigtable; mod redis; +/// A value retrieved from a key/value store, with whatever freshness metadata +/// the backend can provide. +pub struct CachedValue { + /// The stored bytes. + pub bytes: Vec, + + /// How long ago this entry was written, if the backend records write times. + /// `None` means the backend cannot tell us (e.g. Redis), in which case the + /// entry can never be considered stale for auto-refresh. + pub age: Option, +} + /// A key/value store, like Redis or BigTable. /// /// We focus only on "pipelined" operations, where many requests are sent at @@ -36,28 +50,14 @@ pub trait KeyValueStore: Send + Sync + 'static { impl dyn KeyValueStore { /// Create an appropriate `KeyValueStore` instance based on `url`. - #[allow(dead_code)] pub async fn new_from_url( url: Url, key_prefix: String, - ) -> Result> { - Self::new_from_url_with_bigtable_eviction(url, key_prefix, None).await - } - - /// Create an appropriate `KeyValueStore` instance based on `url`, with optional BigTable eviction config. - pub async fn new_from_url_with_bigtable_eviction( - url: Url, - key_prefix: String, - bigtable_eviction_config: Option, ) -> Result> { match url.scheme() { "redis" => Ok(Box::new(redis::Redis::new(url, key_prefix).await?)), "bigtable" => { - let mut bigtable = bigtable::BigTable::new(url, key_prefix).await?; - if let Some(config) = bigtable_eviction_config { - bigtable.set_eviction_config(config); - } - Ok(Box::new(bigtable)) + Ok(Box::new(bigtable::BigTable::new(url, key_prefix).await?)) } scheme => { Err(format_err!("don't know how to connect to {}: URLs", scheme)) @@ -85,7 +85,7 @@ pub trait PipelinedGet<'store>: Send + Sync { /// Execute all our requests and return the results in order. We return /// `None` when a value can't be found. - async fn execute(&self) -> Result>>>; + async fn execute(&self) -> Result>>; } /// A series of "set" requests that we'll send in a single batch. diff --git a/src/key_value_stores/redis.rs b/src/key_value_stores/redis.rs index 95f3c6e..8dc06a6 100644 --- a/src/key_value_stores/redis.rs +++ b/src/key_value_stores/redis.rs @@ -13,7 +13,9 @@ use url::Url; use crate::Result; -use super::{KeyValueStore, KeyValueStoreNew, PipelinedGet, PipelinedSet}; +use super::{ + CachedValue, KeyValueStore, KeyValueStoreNew, PipelinedGet, PipelinedSet, +}; /// A simple Redis client. pub struct Redis { @@ -94,11 +96,11 @@ impl<'store> PipelinedGet<'store> for RedisPipelinedGet<'store> { } #[instrument(name = "PipelinedGet::execute", level = "trace", skip_all)] - async fn execute(&self) -> Result>>> { + async fn execute(&self) -> Result>> { let start = Instant::now(); let mut client = self.redis.client().await?; - let result = self + let result: Vec>> = self .pipeline .query_async(&mut *client) .await @@ -107,7 +109,12 @@ impl<'store> PipelinedGet<'store> for RedisPipelinedGet<'store> { histogram!("geocodecsv.redis.get_request.duration_seconds") .record((Instant::now() - start).as_secs_f64()); - Ok(result) + // Redis does not give us a usable per-entry write time, so we can't + // support age-based auto-refresh on this backend. + Ok(result + .into_iter() + .map(|found| found.map(|bytes| CachedValue { bytes, age: None })) + .collect()) } } diff --git a/src/main.rs b/src/main.rs index 2d90dad..b1e2834 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,3 @@ -// Async HTTP boilerplate based on -// https://github.com/daboross/futures-example-2019/ - #![recursion_limit = "128"] pub use anyhow::Result; @@ -34,6 +31,7 @@ mod pipeline; mod server; mod unpack_vec; +use crate::geocoders::cache::refresh::{RefreshPolicy, RefreshPolicyConfig}; use crate::geocoders::{ cache::Cache, invalid_record_skipper::InvalidRecordSkipper, libpostal::LibPostal, normalizer::Normalizer, shared_http_client, smarty::Smarty, Geocoder, @@ -44,9 +42,9 @@ use crate::pipeline::{geocode_stdio, OnDuplicateColumns, CONCURRENCY, GEOCODE_SI use crate::server::run_server; use crate::{addresses::AddressColumnSpec, geocoders::paired::Paired}; -#[cfg(all(feature = "jemallocator", not(target_env = "msvc")))] +#[cfg(all(feature = "tikv-jemallocator", not(target_env = "msvc")))] #[global_allocator] -static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; +static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; /// Underlying geocoders we can use. (Helper struct for argument parsing.) #[derive(Clone, Copy, Debug, ValueEnum)] @@ -92,6 +90,15 @@ impl FromStr for MetricsLabel { } } +/// Convert a whole-day count from a CLI flag into a `Duration`. +fn duration_from_days(days: u64) -> Result { + Ok(Duration::from_secs( + days.checked_mul(24 * 60 * 60).ok_or_else(|| { + format_err!("day count {days} is too large to convert to a duration") + })?, + )) +} + /// Our command-line arguments. #[derive(Debug, Parser)] #[command(author, version, about = "geocode CSV files passed on standard input")] @@ -140,13 +147,34 @@ struct Opt { #[arg(long = "cache-key-prefix", requires = "cache_url")] cache_key_prefix: Option, - /// BigTable cache eviction: minimum age in seconds before entries can be evicted. - #[arg(long = "bigtable-random-eviction-age")] - bigtable_random_eviction_age: Option, + /// Re-geocode a cached failure after this many days (then 2x, 4x, …). + /// Requires `--refresh-failures-max-attempts`, `--refresh-rate`, and + /// `--cache=bigtable://`. + #[arg( + long = "refresh-failures-after-days", + value_name = "N", + requires = "refresh_failures_max_attempts" + )] + refresh_failures_after_days: Option, - /// BigTable cache eviction: probability (0.0 to 1.0) of evicting eligible entries. - #[arg(long = "bigtable-random-eviction-rate")] - bigtable_random_eviction_rate: Option, + /// Stop re-checking a cached failure after this many refreshes. Requires + /// `--refresh-failures-after-days`. + #[arg( + long = "refresh-failures-max-attempts", + value_name = "N", + requires = "refresh_failures_after_days" + )] + refresh_failures_max_attempts: Option, + + /// Re-geocode a cached success after this many days. Requires + /// `--refresh-rate` and `--cache=bigtable://`. + #[arg(long = "refresh-successes-after-days", value_name = "N")] + refresh_successes_after_days: Option, + + /// Fraction of eligible cache keys to refresh on a given day, in (0, 1]. + /// Required whenever any `--refresh-*` period is set. + #[arg(long = "refresh-rate", value_name = "F")] + refresh_rate: Option, /// Before processing addresses, normalize them using libpostal. #[arg(long = "normalize")] @@ -252,41 +280,74 @@ async fn main() -> Result<()> { ) }); - // Choose our main geocoding client. - // Validate BigTable eviction arguments - let has_age = opt.bigtable_random_eviction_age.is_some(); - let has_rate = opt.bigtable_random_eviction_rate.is_some(); - - if has_age || has_rate { - // Both age and rate must be specified together - if has_age != has_rate { + // Build our cache refresh policy, if requested. Refresh is only supported + // by the BigTable cache, which records a write time per entry. + let wants_refresh = opt.refresh_failures_after_days.is_some() + || opt.refresh_successes_after_days.is_some(); + let refresh_policy = if wants_refresh { + let Some(rate) = opt.refresh_rate else { return Err(format_err!( - "--bigtable-random-eviction-age and --bigtable-random-eviction-rate must be used together" + "--refresh-rate is required whenever a --refresh-* period is set" )); + }; + if !(rate > 0.0 && rate <= 1.0) { + return Err(format_err!("--refresh-rate must be in (0, 1], got {rate}")); } - - if let Some(cache_url) = &opt.cache_url { - if cache_url.scheme() != "bigtable" { + if let Some(days) = opt.refresh_failures_after_days { + if days == 0 { return Err(format_err!( - "--bigtable-random-eviction-age and --bigtable-random-eviction-rate can only be used with --cache=bigtable://" + "--refresh-failures-after-days must be greater than 0" )); } - } else { - return Err(format_err!( - "--bigtable-random-eviction-age and --bigtable-random-eviction-rate require --cache=bigtable://" - )); } - } - - if let Some(rate) = opt.bigtable_random_eviction_rate { - if !(0.0..=1.0).contains(&rate) { - return Err(format_err!( - "--bigtable-random-eviction-rate must be between 0.0 and 1.0, got {}", - rate - )); + if let Some(max_attempts) = opt.refresh_failures_max_attempts { + if max_attempts == 0 { + return Err(format_err!( + "--refresh-failures-max-attempts must be greater than 0" + )); + } } - } + if let Some(days) = opt.refresh_successes_after_days { + if days == 0 { + return Err(format_err!( + "--refresh-successes-after-days must be greater than 0" + )); + } + } + match &opt.cache_url { + Some(cache_url) if cache_url.scheme() == "bigtable" => {} + Some(_) => { + return Err(format_err!( + "--refresh-* flags are only supported with --cache=bigtable://" + )) + } + None => { + return Err(format_err!( + "--refresh-* flags require --cache=bigtable://" + )) + } + } + Some(RefreshPolicy::new(RefreshPolicyConfig { + failure_period: opt + .refresh_failures_after_days + .map(duration_from_days) + .transpose()?, + failure_max_attempts: opt.refresh_failures_max_attempts.unwrap_or(0), + success_period: opt + .refresh_successes_after_days + .map(duration_from_days) + .transpose()?, + rate, + })) + } else if opt.refresh_rate.is_some() { + return Err(format_err!( + "--refresh-rate requires --refresh-failures-after-days or --refresh-successes-after-days" + )); + } else { + None + }; + // Choose our main geocoding client. let mut geocoder: Box = match opt.geocoder { GeocoderName::Smarty => Box::new(Smarty::new( opt.match_strategy, @@ -304,37 +365,16 @@ async fn main() -> Result<()> { .as_deref() .unwrap_or_default() .to_owned(); - // Prepare BigTable eviction config if specified - let bigtable_eviction_config = if cache_url.scheme() == "bigtable" { - if let (Some(age), Some(rate)) = ( - opt.bigtable_random_eviction_age, - opt.bigtable_random_eviction_rate, - ) { - use crate::key_value_stores::bigtable::EvictionConfig; - Some(EvictionConfig { - min_age_seconds: age, - eviction_rate: rate, - }) - } else { - None - } - } else { - None - }; - let key_value_store = - ::new_from_url_with_bigtable_eviction( - cache_url.to_owned(), - cache_key_prefix, - bigtable_eviction_config, - ) - .await?; + ::new_from_url(cache_url.to_owned(), cache_key_prefix) + .await?; geocoder = Box::new( Cache::new( key_value_store, geocoder, opt.cache_output_keys, opt.cache_hits_only, + refresh_policy, ) .await?, ); diff --git a/src/pipeline.rs b/src/pipeline.rs index 52812e8..5190895 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -8,7 +8,7 @@ use std::sync::atomic::AtomicI64; use std::{ cmp::max, io, iter::FromIterator, sync::Arc, thread::sleep, time::Duration, }; -use strum_macros::EnumString; +use strum::EnumString; use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio_stream::wrappers::ReceiverStream; use tracing::{debug, error, instrument, trace, warn}; diff --git a/src/server.rs b/src/server.rs index 632daea..93ad528 100644 --- a/src/server.rs +++ b/src/server.rs @@ -10,9 +10,7 @@ use crate::geocoders::Geocoder; use anyhow::{format_err, Context, Result}; use axum::{ extract::DefaultBodyLimit, - headers::{HeaderMap, HeaderName}, - http::header::CONTENT_TYPE, - http::StatusCode, + http::{header::CONTENT_TYPE, HeaderMap, HeaderName, StatusCode}, routing::post, Extension, Json, Router, }; @@ -52,13 +50,14 @@ pub async fn run_server(listen_addr: &str, geocoder: Box) -> Resul // rough size of `[crate::pipeline::GEOCODE_SIZE]`. .layer(DefaultBodyLimit::max(16384)); - let listen_addr = listen_addr.parse().with_context(|| { - format!("could not parse listen address: {:?}", listen_addr) - })?; + let listener = tokio::net::TcpListener::bind(listen_addr) + .await + .with_context(|| { + format!("could not bind to listen address: {:?}", listen_addr) + })?; // Run it with axum on the given listen address. - axum::Server::bind(&listen_addr) - .serve(app.into_make_service()) + axum::serve(listener, app) .await .context("web server failed to start") } diff --git a/tests/bigtable_eviction.rs b/tests/bigtable_eviction.rs deleted file mode 100644 index 0634029..0000000 --- a/tests/bigtable_eviction.rs +++ /dev/null @@ -1,376 +0,0 @@ -//! Tests for BigTable cache eviction functionality. - -use cli_test_dir::*; -use std::collections::HashMap; - -/// A CSV file with multiple addresses for eviction testing. -const EVICTION_TEST_CSV: &str = "address_1,address_2,city,state,zip_code -20 W 34th St,,New York,NY,10118 -1224 S 760 W,,Provo,UT, -1600 Pennsylvania Ave NW,,Washington,DC,20500 -1 Microsoft Way,,Redmond,WA,98052 -1 Infinite Loop,,Cupertino,CA,95014 -"; - -/// Helper function to parse metrics from stderr output -fn parse_metrics_from_stderr(stderr: &str) -> MetricsData { - let mut metrics = HashMap::new(); - - // Look for the metrics section that starts with "Metrics:" - let lines: Vec<&str> = stderr.lines().collect(); - let mut in_metrics_section = false; - - for line in lines { - if line.contains("Metrics:") { - in_metrics_section = true; - continue; - } - - if in_metrics_section { - // Parse counter metrics (format: metric_name{labels} value) - if line.contains("geocodecsv") && !line.starts_with("#") { - if let Some(parts) = parse_prometheus_metric_line(line) { - metrics.insert(parts.0, parts.1); - } - } - } - } - - MetricsData { metrics } -} - -/// Parse a single Prometheus metric line and return (metric_name, value) -fn parse_prometheus_metric_line(line: &str) -> Option<(String, f64)> { - // Handle both formats: - // 1. metric_name value - // 2. metric_name{labels} value - - let trimmed = line.trim(); - if trimmed.is_empty() || trimmed.starts_with("#") { - return None; - } - - // Find the last space to split metric from value - let parts: Vec<&str> = trimmed.rsplitn(2, ' ').collect(); - if parts.len() != 2 { - return None; - } - - let metric_part = parts[1]; - let value_str = parts[0]; - - // Extract metric name (before any '{' if labels exist) - let metric_name = if let Some(brace_pos) = metric_part.find('{') { - metric_part[..brace_pos].to_string() - } else { - metric_part.to_string() - }; - - // Parse the value - if let Ok(value) = value_str.parse::() { - Some((metric_name, value)) - } else { - None - } -} - -/// Helper function to analyze geocoding output and extract detailed metrics -fn analyze_geocoding_output(output: &str) -> GeocodingAnalysis { - let lines: Vec<&str> = output.lines().collect(); - let data_lines: Vec<&str> = lines - .iter() - .filter(|line| { - !line.trim().is_empty() && !line.contains("INFO") && !line.contains("#") - }) - .copied() - .collect(); - - // Skip header if present - let data_lines = if !data_lines.is_empty() && data_lines[0].contains("address_1") { - &data_lines[1..] - } else { - &data_lines - }; - - let mut total_rows = 0; - let mut rows_with_gc_data = 0; - - for line in data_lines { - if line.trim().is_empty() { - continue; - } - total_rows += 1; - - // Check for geocoding data - look for latitude values or other geocoding fields - if line.contains("40.") - || line.contains("27.") - || line.contains("gc_addressee") - || line.contains("Commercial") - || line.contains("Residential") - { - rows_with_gc_data += 1; - } - } - - GeocodingAnalysis { - total_rows, - rows_with_gc_data, - raw_output: output.to_string(), - } -} - -#[derive(Debug, Clone)] -struct MetricsData { - metrics: HashMap, -} - -impl MetricsData { - fn get_metric(&self, name: &str) -> f64 { - *self.metrics.get(name).unwrap_or(&0.0) - } - - fn print_summary(&self, label: &str) { - println!("\n=== {} ===", label); - println!( - "Cache hits: {}", - self.get_metric("geocodecsv_cache_hits_total") - ); - println!( - "Cache misses: {}", - self.get_metric("geocodecsv_cache_misses_total") - ); - println!( - "Eligible for eviction: {}", - self.get_metric( - "geocodecsv_bigtable_random_eviction_eligible_entries_total" - ) - ); - println!( - "Actually evicted: {}", - self.get_metric( - "geocodecsv_bigtable_random_eviction_evicted_entries_total" - ) - ); - - let total_addresses = self.get_metric("geocodecsv_addresses_total"); - let geocoded_addresses = - self.get_metric("geocodecsv_addresses_geocoded_total"); - println!("Total addresses: {}", total_addresses); - println!("Geocoded addresses: {}", geocoded_addresses); - } -} - -#[derive(Debug, Clone)] -struct GeocodingAnalysis { - total_rows: usize, - rows_with_gc_data: usize, - #[allow(dead_code)] - raw_output: String, -} - -impl GeocodingAnalysis { - fn print_summary(&self, label: &str) { - println!("\n=== {} ===", label); - println!("Total rows: {}", self.total_rows); - println!("Rows with geocoding data: {}", self.rows_with_gc_data); - if self.total_rows > 0 { - println!( - "Geocoding coverage: {:.1}%", - (self.rows_with_gc_data as f64 / self.total_rows as f64) * 100.0 - ); - } - } -} - -#[test] -#[ignore] -fn bigtable_cache_eviction_test() { - let testdir = TestDir::new("geocode-csv", "bigtable_cache_eviction_test"); - - testdir.create_file( - "spec.json", - r#"{ - "gc": { - "house_number_and_street": [ - "address_1", - "address_2" - ], - "city": "city", - "state": "state", - "postcode": "zip_code" - } -}"#, - ); - - println!("Starting BigTable cache eviction test..."); - println!("Test CSV data:\n{}", EVICTION_TEST_CSV); - - // First run - populate the cache - println!("\nšŸ”„ Phase 1: Populating cache with initial geocoding run..."); - let bigtable_cache_url = std::env::var("BIGTABLE_CACHE_URL") - .expect("BIGTABLE_CACHE_URL environment variable must be set"); - let output1 = testdir - .cmd() - .env("RUST_LOG", "info") - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg(format!("--cache={}", bigtable_cache_url)) - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - let initial_analysis = analyze_geocoding_output(output1.stdout_str()); - let initial_metrics = parse_metrics_from_stderr(output1.stderr_str()); - - initial_analysis.print_summary("Initial Cache Population"); - initial_metrics.print_summary("Initial Metrics"); - - // Verify first run has correct data - assert!( - initial_analysis.rows_with_gc_data > 0, - "Expected some geocoded results in initial run, got {} rows with geocoding data", - initial_analysis.rows_with_gc_data - ); - - // Verify we processed 5 addresses and they all got geocoded - assert_eq!( - initial_metrics.get_metric("geocodecsv_addresses_total"), - 5.0 - ); - // Note: In this first run, we got cache hits (5) instead of misses because there's existing cached data - // This is expected behavior - the cache already has data from previous test runs - assert_eq!( - initial_metrics.get_metric("geocodecsv_cache_hits_total"), - 5.0 - ); - assert_eq!( - initial_metrics.get_metric("geocodecsv_cache_misses_total"), - 0.0 - ); - - // Test eviction by running with eviction enabled and checking metrics - println!("\nšŸ”„ Phase 2: Testing cache eviction with 50% rate..."); - - // Wait a moment to ensure cache entries are old enough - println!(" Waiting 1.1s for cache entries to age..."); - std::thread::sleep(std::time::Duration::from_millis(1100)); - - // Run with eviction enabled - let output_evict = testdir - .cmd() - .env("RUST_LOG", "info") - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg(format!("--cache={}", bigtable_cache_url)) - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=0.5") - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - let eviction_metrics = parse_metrics_from_stderr(output_evict.stderr_str()); - eviction_metrics.print_summary("Eviction Run Metrics"); - - // Check that some entries were eligible for eviction and some were actually evicted - let eligible_entries = eviction_metrics - .get_metric("geocodecsv_bigtable_random_eviction_eligible_entries_total"); - let evicted_entries = eviction_metrics - .get_metric("geocodecsv_bigtable_random_eviction_evicted_entries_total"); - - println!(" Eligible for eviction: {}", eligible_entries); - println!(" Actually evicted: {}", evicted_entries); - - // The key test is that eviction is actually happening - we should see some entries evicted - // The exact number of eligible entries can vary based on cache state from previous runs - assert!( - eligible_entries > 0.0, - "Expected some entries to be eligible for eviction, got {}", - eligible_entries - ); - - // The most important check: eviction should be happening - if evicted_entries > 0.0 { - println!( - " āœ… Eviction working: {} entries evicted out of {} eligible", - evicted_entries, eligible_entries - ); - } else { - println!(" āš ļø No entries evicted on first attempt, trying again..."); - - // Try a few more times with 50% rate - we should see eviction eventually - let mut attempts_with_eviction = 0; - for attempt in 1..=3 { - std::thread::sleep(std::time::Duration::from_millis(1100)); - - let retry_output = testdir - .cmd() - .env("RUST_LOG", "info") - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg(format!("--cache={}", bigtable_cache_url)) - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=0.5") - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - let retry_metrics = parse_metrics_from_stderr(retry_output.stderr_str()); - let retry_evicted = retry_metrics.get_metric( - "geocodecsv_bigtable_random_eviction_evicted_entries_total", - ); - - println!(" Attempt {}: {} entries evicted", attempt, retry_evicted); - - if retry_evicted > 0.0 { - attempts_with_eviction += 1; - break; // We saw eviction, that's sufficient - } - } - - assert!( - attempts_with_eviction > 0, - "Expected to see eviction in at least one of 3 attempts with 50% rate" - ); - println!(" āœ… Eviction confirmed after retry attempts"); - } - - // Validation run: Test cache behavior after eviction - println!("\nšŸ”„ Phase 3: Validation - cache hits/misses with eviction..."); - std::thread::sleep(std::time::Duration::from_millis(1100)); - - let output_cache_check = testdir - .cmd() - .env("RUST_LOG", "info") - .arg("--license=us-core-enterprise-cloud") - .arg("--spec=spec.json") - .arg(format!("--cache={}", bigtable_cache_url)) - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=0.5") - .output_with_stdin(EVICTION_TEST_CSV) - .expect_success(); - - let cache_check_metrics = - parse_metrics_from_stderr(output_cache_check.stderr_str()); - cache_check_metrics.print_summary("Cache Check Metrics"); - - // We should see a mix of cache hits and cache misses (due to eviction) - let cache_hits = cache_check_metrics.get_metric("geocodecsv_cache_hits_total"); - let cache_misses = cache_check_metrics.get_metric("geocodecsv_cache_misses_total"); - - println!(" Cache hits: {}", cache_hits); - println!(" Cache misses: {}", cache_misses); - println!( - " Cache hit rate: {:.1}%", - (cache_hits / (cache_hits + cache_misses)) * 100.0 - ); - - // We expect some cache misses due to eviction (but not necessarily all) - assert!(cache_misses > 0.0, "Expected some cache misses due to eviction, got {}. Cache eviction may not be working.", cache_misses); - assert!( - cache_hits + cache_misses == 5.0, - "Expected to process 5 addresses total, got {} hits + {} misses = {}", - cache_hits, - cache_misses, - cache_hits + cache_misses - ); - - println!("\nāœ… BigTable cache eviction test completed successfully!"); - println!(" Eviction metrics show the feature is working as expected."); -} diff --git a/tests/bigtable_refresh.rs b/tests/bigtable_refresh.rs new file mode 100644 index 0000000..2b6afb7 --- /dev/null +++ b/tests/bigtable_refresh.rs @@ -0,0 +1,86 @@ +//! Integration tests for BigTable cache refresh. +//! +//! These require a real BigTable cache (`BIGTABLE_CACHE_URL`) and a Smarty +//! license, so they are `#[ignore]`d by default. The refresh decision itself +//! is unit-tested in `src/geocoders/cache/refresh.rs`. + +use cli_test_dir::*; + +const SIMPLE_CSV: &str = "address_1,address_2,city,state,zip_code +20 W 34th St,,New York,NY,10118 +1 Infinite Loop,,Cupertino,CA,95014 +"; + +const SPEC: &str = r#"{ + "gc": { + "house_number_and_street": ["address_1", "address_2"], + "city": "city", + "state": "state", + "postcode": "zip_code" + } +}"#; + +/// Fresh successes are younger than `--refresh-successes-after-days` (and +/// successes are not refreshed at all unless that flag is set). A second run +/// with refresh enabled should still return geocoded results from the cache. +#[test] +#[ignore] +fn fresh_entries_are_served_from_cache() { + let testdir = TestDir::new("geocode-csv", "fresh_entries_are_served_from_cache"); + testdir.create_file("spec.json", SPEC); + let bigtable_cache_url = std::env::var("BIGTABLE_CACHE_URL") + .expect("BIGTABLE_CACHE_URL environment variable must be set"); + + testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg(format!("--cache={}", bigtable_cache_url)) + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + let output = testdir + .cmd() + .arg("--license=us-core-enterprise-cloud") + .arg("--spec=spec.json") + .arg(format!("--cache={}", bigtable_cache_url)) + .arg("--refresh-failures-after-days=90") + .arg("--refresh-failures-max-attempts=4") + .arg("--refresh-rate=1") + .output_with_stdin(SIMPLE_CSV) + .expect_success(); + + assert!(output.stdout_str().contains("gc_addressee")); +} + +/// Refresh only makes sense for the BigTable cache. +#[test] +fn refresh_requires_bigtable_cache() { + let testdir = TestDir::new("geocode-csv", "refresh_requires_bigtable_cache"); + testdir.create_file("spec.json", SPEC); + + testdir + .cmd() + .arg("--spec=spec.json") + .arg("--refresh-failures-after-days=90") + .arg("--refresh-failures-max-attempts=4") + .arg("--refresh-rate=1") + .output_with_stdin(SIMPLE_CSV) + .expect_failure(); +} + +#[test] +fn refresh_rate_nan_is_rejected() { + let testdir = TestDir::new("geocode-csv", "refresh_rate_nan_is_rejected"); + testdir.create_file("spec.json", SPEC); + + testdir + .cmd() + .arg("--spec=spec.json") + .arg("--cache=bigtable://project/instance/table") + .arg("--refresh-failures-after-days=90") + .arg("--refresh-failures-max-attempts=4") + .arg("--refresh-rate=nan") + .output_with_stdin(SIMPLE_CSV) + .expect_failure(); +} diff --git a/tests/libpostal.rs b/tests/libpostal.rs index 00baca0..9cbcf9a 100644 --- a/tests/libpostal.rs +++ b/tests/libpostal.rs @@ -7,6 +7,7 @@ const SIMPLE_CSV: &str = "address_1,address_2,city,state,zip_code 20 W 34th St,,New York,NY,10118 1224 S 760 W,,Provo,UT, 104 16th st,,Belleair Bch,FL, +1600 Pennsylvania Ave NW,2nd Floor,Washington,DC,20500 "; #[test] @@ -34,7 +35,39 @@ fn libpostal() { .arg("--spec=spec.json") .output_with_stdin(SIMPLE_CSV) .expect_success(); - assert!(output.stdout_str().contains("gc_city")); - assert!(output.stdout_str().contains("new york")); - assert!(output.stdout_str().contains("belleair")); + let stdout = output.stdout_str(); + assert!(stdout.contains("gc_city")); + assert!(stdout.contains("new york")); + assert!(stdout.contains("belleair")); + + // A secondary-unit designator like "2nd Floor" (a libpostal `level`) must + // survive into our output instead of being silently dropped. + assert!(stdout.contains("gc_level")); + assert!(stdout.contains("floor")); + + // We should emit columns for the labels libpostal's parser can actually + // produce, including ones we previously discarded. + assert!(stdout.contains("gc_building")); + assert!(stdout.contains("gc_metro_station")); + + // We should NOT emit columns for OpenCage formatting labels that libpostal's + // parser never produces (it aliases these to canonical labels before + // training). + for dead_column in &[ + "gc_archipelago", + "gc_continent", + "gc_country_code", + "gc_county", + "gc_hamlet", + "gc_municipality", + "gc_neighbourhood", + "gc_postal_city", + "gc_region", + "gc_village", + ] { + assert!( + !stdout.contains(dead_column), + "output should not contain dead column {dead_column}" + ); + } } diff --git a/tests/server.rs b/tests/server.rs index 19dd18a..1ed3972 100644 --- a/tests/server.rs +++ b/tests/server.rs @@ -5,8 +5,8 @@ use std::time::{Duration, Instant}; use anyhow::{Context, Result}; use cli_test_dir::*; -use hyper::header::CONTENT_TYPE; use reqwest::blocking::{Client, Response}; +use reqwest::header::CONTENT_TYPE; use serde::Serialize; #[derive(Serialize)] @@ -109,8 +109,10 @@ fn server_helper() -> Result { .context("HTTP request failed") }; - // Post a request with JSON content. - let deadline = Instant::now() + Duration::from_secs(5); + // Post a request with JSON content. In server mode we prime libpostal + // before binding the listener, which can take 5-10 seconds, so we give the + // server plenty of time to start accepting connections. + let deadline = Instant::now() + Duration::from_secs(30); loop { match connect() { Ok(res) => break Ok(res), diff --git a/tests/specs.rs b/tests/specs.rs index cd7edfc..b1880e2 100644 --- a/tests/specs.rs +++ b/tests/specs.rs @@ -34,8 +34,9 @@ fn all_fields() { .arg("--license=us-core-enterprise-cloud") .arg("--spec=spec.json") .arg(format!("--cache={}", bigtable_cache_url)) - .arg("--bigtable-random-eviction-age=1") - .arg("--bigtable-random-eviction-rate=1.0") + .arg("--refresh-failures-after-days=90") + .arg("--refresh-failures-max-attempts=4") + .arg("--refresh-rate=1") .output_with_stdin(SIMPLE_CSV) .expect_success(); assert!(output.stdout_str().contains("gc_addressee")); From 2370bff0d2ffdd718449a75baeb3cb9e6c0b260e Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 1 Sep 2026 22:09:32 -0400 Subject: [PATCH 14/16] Fix CI so the musl alpha can actually build. Install current stable Rust with dtolnay/rust-toolchain, and bump cargo-deny so it can parse CVSS 4.0 advisories. Co-authored-by: Cursor --- .github/workflows/ci.yml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5751db8..deebeca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,19 +95,16 @@ jobs: brew install automake - name: Install protoc uses: arduino/setup-protoc@v3 - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - # We track latest stable Rust instead of hardcoding it because it - # virtually never breaks old code. - toolchain: stable - components: rustfmt, clippy - target: ${{ matrix.target }} - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + # Checks-out our repository first so `rust-toolchain` is present when we + # install Rust. - uses: actions/checkout@v4 with: submodules: recursive + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + targets: ${{ matrix.target }} - name: Install Just run: | version=1.42.4 @@ -118,7 +115,7 @@ jobs: rm -rf $basename.tar.gz - name: Install cargo-deny run: | - version=0.18.4 + version=0.20.2 basename=cargo-deny-$version-${{ matrix.host }} curl -fLO https://github.com/EmbarkStudios/cargo-deny/releases/download/$version/$basename.tar.gz tar xf $basename.tar.gz From 05f9f296a737fea54bcbbb3759394284a048c051 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Tue, 1 Sep 2026 22:13:24 -0400 Subject: [PATCH 15/16] Ban OpenSSL and drop low-star GitHub Actions. Refuse openssl, openssl-sys, and native-tls, and stop allowing the OpenSSL license. Install protoc from apt/brew, create releases with softprops/action-gh-release, and upload assets with gh. Co-authored-by: Cursor --- .github/workflows/ci.yml | 32 ++++++++++++++++---------------- deny.toml | 15 +++++---------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index deebeca..f145424 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,9 @@ on: # Only run on pull requests against main. branches: [main] +permissions: + contents: write + jobs: # We run this job first, to create any GitHub release that we might need. # Creating a release can only be done once, so we need to split it out from @@ -23,9 +26,7 @@ jobs: runs-on: ubuntu-latest outputs: release_version: ${{ steps.extract_release_version.outputs.release_version }} - upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v4 - name: Extract release version id: extract_release_version @@ -49,12 +50,9 @@ jobs: - name: "Make release" id: create_release if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: softprops/action-gh-release@v2 with: - tag_name: ${{ github.ref }} - release_name: "${{ steps.extract_release_version.outputs.release_version }}" + name: ${{ steps.extract_release_version.outputs.release_version }} body_path: RELEASE_BODY.md prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }} @@ -94,7 +92,13 @@ jobs: run: | brew install automake - name: Install protoc - uses: arduino/setup-protoc@v3 + run: | + if [ "${{ runner.os }}" = "macOS" ]; then + brew install protobuf + else + sudo apt-get update + sudo apt-get install -y protobuf-compiler + fi # Checks-out our repository first so `rust-toolchain` is present when we # install Rust. - uses: actions/checkout@v4 @@ -149,13 +153,9 @@ jobs: release_file=geocode-csv_${{ needs.create_release.outputs.release_version }}_${{ matrix.target }}.zip zip -j $release_file target/${{ matrix.target }}/release/geocode-csv echo "release_file=$release_file" >> $GITHUB_OUTPUT - - name: Upload Release Asset + - name: Upload release asset if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create_release.outputs.upload_url }} - asset_path: ./${{ steps.build_release.outputs.release_file }} - asset_name: ${{ steps.build_release.outputs.release_file }} - asset_content_type: application/zip + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload "${{ github.ref_name }}" "${{ steps.build_release.outputs.release_file }}" --clobber diff --git a/deny.toml b/deny.toml index e222d96..a139840 100644 --- a/deny.toml +++ b/deny.toml @@ -12,7 +12,9 @@ ignore = [ [licenses] version = 2 -# Allow common non-restrictive licenses. +# Allow common non-restrictive licenses. Do not allow OpenSSL: we refuse the +# OpenSSL library itself, and we do not want `ring` (whose license includes +# "OpenSSL") sneaking back in next to aws-lc-rs. allow = [ "MIT", "Apache-2.0", @@ -22,19 +24,10 @@ allow = [ "CC0-1.0", "CDLA-Permissive-2.0", "ISC", - "MPL-2.0", - "OpenSSL", "Unicode-3.0", "Zlib" ] -[[licenses.clarify]] -# Ring has a messy license. We should either commit 100% to ring everywhere, or -# to native-tls everywhere, and not mix the two. -name = "ring" -expression = "ISC AND OpenSSL AND MIT" -license-files = [{ path = "LICENSE", hash = 3171872035 }] - [[licenses.clarify]] name = "encoding_rs" expression = "(MIT OR Apache-2.0) AND BSD-3-Clause AND CC0-1.0" @@ -46,7 +39,9 @@ multiple-versions = "warn" deny = [ # This never causes anything but portability misery. + { name = "openssl" }, { name = "openssl-sys" }, + { name = "native-tls" }, # `serde_derive` shipped unreproducible binary builds for a while. See # https://github.com/serde-rs/serde/issues/2538. { name = "serde_derive", version = ">1.0.171,<1.0.184" }, From 4d085afd1fe54fb0e9c9e9bd2b559613c41ccc42 Mon Sep 17 00:00:00 2001 From: Seamus Abshere Date: Mon, 14 Sep 2026 11:48:37 -0400 Subject: [PATCH 16/16] Release 1.5.0-alpha.1. Load BigTable cache credentials through google-cloud-auth so impersonated and GitHub OIDC ADC files work, and so we never fall through to gcloud. Co-authored-by: Cursor --- CHANGELOG.md | 6 + Cargo.lock | 656 +++++++++++++++++--- Cargo.toml | 13 +- crates/metrics-exporter-newrelic/Cargo.toml | 2 +- src/key_value_stores/bigtable.rs | 413 +++++++++++- 5 files changed, 983 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d1807f..dba4144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [1.5.0-alpha.1] - 2026-09-14 + +### Changed + +- The BigTable cache now loads Application Default Credentials with `google-cloud-auth` and injects them into `bigtable_rs`. Impersonated service accounts and GitHub `external_account` files work. A missing or unparseable `GOOGLE_APPLICATION_CREDENTIALS` file is an error. The process never falls through to the `gcloud` CLI. + ## [1.4.1-alpha.1] - 2026-09-01 ### Added diff --git a/Cargo.lock b/Cargo.lock index d76d937..ce64101 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,7 +101,7 @@ checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -205,6 +205,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "bb8" version = "0.9.1" @@ -276,7 +282,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags", + "bitflags 2.13.2", "cexpr", "clang-sys", "itertools 0.13.0", @@ -292,9 +298,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.13.1" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "block-buffer" @@ -305,6 +317,15 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -316,12 +337,15 @@ name = "bytes" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +dependencies = [ + "serde", +] [[package]] name = "cc" -version = "1.4.4" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4" dependencies = [ "find-msvc-tools", "jobserver", @@ -418,7 +442,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -442,6 +466,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.5" @@ -495,18 +525,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.20" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-common" @@ -538,6 +568,89 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + +[[package]] +name = "darling" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 3.0.5", +] + +[[package]] +name = "darling_macro" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" +dependencies = [ + "darling_core", + "quote", + "syn 3.0.5", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + [[package]] name = "digest" version = "0.11.3" @@ -547,6 +660,7 @@ dependencies = [ "block-buffer", "const-oid", "crypto-common", + "ctutils", ] [[package]] @@ -557,7 +671,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -566,6 +680,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" version = "1.18.0" @@ -633,9 +753,9 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" [[package]] name = "fixedbitset" @@ -732,7 +852,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -772,7 +892,7 @@ checksum = "26d27dbcc645b60b8e7f6e2868a9d7102ece97d1bb49c1288b5321fcc67f7260" dependencies = [ "async-trait", "aws-lc-rs", - "base64", + "base64 0.22.1", "bytes", "chrono", "http", @@ -808,7 +928,7 @@ dependencies = [ [[package]] name = "geocode-csv" -version = "1.4.1-alpha.1" +version = "1.5.0-alpha.1" dependencies = [ "anyhow", "async-trait", @@ -821,6 +941,8 @@ dependencies = [ "cli_test_dir", "csv", "futures", + "gcp_auth", + "google-cloud-auth", "googleapis-tonic-google-bigtable-v2", "leaky-bucket", "libpostal-rust", @@ -830,10 +952,13 @@ dependencies = [ "redis", "reqwest", "rustls", + "scoped-env", "serde", "serde_json", + "serial_test", "sha2", "strum", + "tempfile", "tikv-jemallocator", "tokio", "tokio-stream", @@ -887,6 +1012,82 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" +[[package]] +name = "google-cloud-auth" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff461519b1a948200f163574be072753bcfb462a323f0eb426629d89872dd685" +dependencies = [ + "async-trait", + "base64 0.23.1", + "bytes", + "google-cloud-gax", + "hex", + "hmac", + "http", + "jiff", + "reqwest", + "rustc_version", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "sha2", + "thiserror", + "time", + "tokio", + "url", +] + +[[package]] +name = "google-cloud-gax" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5615cff28ee59cfe52fbb4c11b8b1e77f650296e2ea4f4c2b7757ac6b19e752" +dependencies = [ + "bytes", + "futures", + "google-cloud-rpc", + "google-cloud-wkt", + "http", + "pin-project", + "rand 0.10.2", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "google-cloud-rpc" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2162c08a89118130979ba261080e960e44cdcb2d6e2ab8ca9b1da245285d353" +dependencies = [ + "bytes", + "google-cloud-wkt", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "google-cloud-wkt" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fccf98cfd5481a5f5a285181ab0c62123d7d47cd2bb7299448440649349e4e7" +dependencies = [ + "base64 0.22.1", + "bytes", + "serde", + "serde_json", + "serde_with", + "thiserror", + "time", + "url", +] + [[package]] name = "googleapis-tonic-google-api" version = "0.30.0" @@ -950,7 +1151,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap", + "indexmap 2.14.2", "slab", "tokio", "tokio-util", @@ -963,6 +1164,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7040a10f52cba493ddb09926e15d10a9d8a28043708a405931fe4c6f19fac064" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.15.5" @@ -993,6 +1200,21 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "1.5.0" @@ -1040,9 +1262,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ "typenum", ] @@ -1104,7 +1326,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-util", @@ -1228,6 +1450,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.1.0" @@ -1251,19 +1479,32 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.14.1" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] name = "ipnet" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" [[package]] name = "is_terminal_polyfill" @@ -1295,6 +1536,60 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jiff" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "jni" version = "0.22.4" @@ -1356,9 +1651,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" dependencies = [ "cfg-if", "futures-util", @@ -1468,9 +1763,9 @@ dependencies = [ [[package]] name = "lru-slab" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" [[package]] name = "matchers" @@ -1524,9 +1819,9 @@ version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db0d8f1fc9e62caebd0319e11eaec5822b0186c171568f0480b46a0137f9108" dependencies = [ - "base64", + "base64 0.22.1", "evmap", - "indexmap", + "indexmap 2.14.2", "metrics", "metrics-util", "quanta", @@ -1543,7 +1838,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.16.1", - "indexmap", + "indexmap 2.14.2", "metrics", "ordered-float", "quanta", @@ -1568,9 +1863,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi", @@ -1611,6 +1906,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-traits" version = "0.2.19" @@ -1701,7 +2002,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.14.2", ] [[package]] @@ -1742,6 +2043,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + [[package]] name = "potential_utf" version = "0.1.6" @@ -1751,6 +2061,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1851,7 +2167,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ - "bitflags", + "bitflags 2.13.2", "memchr", "unicase", ] @@ -1882,9 +2198,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11" dependencies = [ "bytes", "cfg_aliases", @@ -1902,9 +2218,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.17" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04759210543be93709136e28212294a659ef5001836ff4eab4d663e4529bba83" +checksum = "a9746dbde176634f4f2f1faf2404e30a31b2bc1e9cafb5329c95d8177a18c9fc" dependencies = [ "aws-lc-rs", "bytes", @@ -2047,14 +2363,14 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags", + "bitflags 2.13.2", ] [[package]] name = "redis" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37a4ca5c6ca42aa3e6df2fd32b987a65d32a4c2159a6f3fe0fd1df306a2658f" +checksum = "2acbc41a996f7652b2ddd9dfd98cc4ff602cfd742ae35382f07f608405ab50ed" dependencies = [ "arcstr", "async-lock", @@ -2079,7 +2395,27 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.2", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", ] [[package]] @@ -2113,11 +2449,11 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" dependencies = [ - "base64", + "base64 0.23.1", "bytes", "futures-channel", "futures-core", @@ -2138,6 +2474,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", @@ -2185,7 +2522,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.2", "errno", "libc", "linux-raw-sys", @@ -2194,9 +2531,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.43" +version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ "aws-lc-rs", "log", @@ -2298,6 +2635,36 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scoped-env" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a86338a78d9058ae1bb70bf4ec558e9c51c611b443a356f7d041d29bb6c1c026" + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2316,7 +2683,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.13.2", "core-foundation", "core-foundation-sys", "libc", @@ -2366,7 +2733,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -2375,7 +2742,7 @@ version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ - "indexmap", + "indexmap 2.14.2", "itoa", "memchr", "serde", @@ -2394,6 +2761,76 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "935177bb8c0cd8ca1a4e6d1a2ac8988bea69cab4f9d3a31311e012ad27868ea4" +dependencies = [ + "base64 0.23.1", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.2", + "jiff", + "schemars 0.9.0", + "schemars 1.2.2", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d607aa01a3cb0ad757d6fd216136910db3c97b102fe686585689615a02dbcdc" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 3.0.5", +] + +[[package]] +name = "serial_test" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6df5ed973ad8d834e09f824f9e9f449af6b9a3745f78dec7cc752770bd3bf11" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22144e767da4ddd8416dbf383700542ffd8a5dc493dfecedfe1fe3ad03c98ae" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + [[package]] name = "sha2" version = "0.11.0" @@ -2426,6 +2863,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd_cesu8" version = "1.2.0" @@ -2456,9 +2903,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" +checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" [[package]] name = "socket2" @@ -2522,9 +2969,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" dependencies = [ "proc-macro2", "quote", @@ -2591,7 +3038,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] @@ -2623,6 +3070,36 @@ dependencies = [ "tikv-jemalloc-sys", ] +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.4" @@ -2635,18 +3112,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" @@ -2659,6 +3127,7 @@ dependencies = [ "mio", "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.61.2", @@ -2672,14 +3141,14 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] name = "tokio-rustls" -version = "0.26.4" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67" dependencies = [ "rustls", "tokio", @@ -2694,6 +3163,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] @@ -2718,7 +3188,7 @@ checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", - "base64", + "base64 0.22.1", "bytes", "h2", "http", @@ -2787,7 +3257,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap", + "indexmap 2.14.2", "pin-project-lite", "slab", "sync_wrapper", @@ -2804,7 +3274,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags", + "bitflags 2.13.2", "bytes", "futures-util", "http", @@ -3020,9 +3490,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" dependencies = [ "cfg-if", "once_cell", @@ -3033,9 +3503,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928" dependencies = [ "js-sys", "wasm-bindgen", @@ -3043,9 +3513,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3053,31 +3523,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.5", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8" dependencies = [ "js-sys", "wasm-bindgen", @@ -3317,18 +3787,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" dependencies = [ "proc-macro2", "quote", @@ -3392,7 +3862,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.4", + "syn 3.0.5", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c100b3b..028cf6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "geocode-csv" -version = "1.4.1-alpha.1" +version = "1.5.0-alpha.1" authors = ["Eric Kidd ", "Seamus Abshere "] edition = "2021" @@ -12,7 +12,10 @@ documentation = "https://github.com/faradayio/geocode-csv" [dev-dependencies] cli_test_dir = "^0.1.8" -reqwest = { version = "^0.13.4", default-features = false, features = ["blocking", "json", "rustls"] } +reqwest = { version = "^0.13.5", default-features = false, features = ["blocking", "json", "rustls"] } +scoped-env = "^2.1.0" +serial_test = "^4.0.1" +tempfile = "^3.27.0" [dependencies] anyhow = { version = "^1.0.104", features = ["backtrace"] } @@ -33,13 +36,15 @@ bincode = { version = "2.0.1", features = ["serde"] } clap = { version = "^4.6.6", features = ["derive", "wrap_help"] } csv = "^1.4.0" futures = "^0.3.34" +gcp_auth = { version = "^0.12.7", default-features = false } +google-cloud-auth = { version = "^1.16", default-features = false } leaky-bucket = "^1.1.2" libpostal-rust = { version = "0.1.1", path = "crates/libpostal-rust" } metrics = "^0.24.6" metrics-util = "^0.20.4" opinionated_metrics = { version = "0.2.0", path = "crates/opinionated_metrics" } -reqwest = { version = "^0.13.4", default-features = false, features = ["json", "rustls"] } -redis = { version = "^1.6.0", default-features = false, features = [ +reqwest = { version = "^0.13.5", default-features = false, features = ["json", "rustls"] } +redis = { version = "^1.7.0", default-features = false, features = [ "aio", "tokio-comp", ] } diff --git a/crates/metrics-exporter-newrelic/Cargo.toml b/crates/metrics-exporter-newrelic/Cargo.toml index 63f4ca9..6ebdd78 100644 --- a/crates/metrics-exporter-newrelic/Cargo.toml +++ b/crates/metrics-exporter-newrelic/Cargo.toml @@ -15,7 +15,7 @@ documentation = "https://docs.rs/metrics-exporter-newrelic" http = "1.5.0" metrics = "0.24.6" metrics-util = "0.20.4" -reqwest = { version = "0.13.4", default-features = false, features = ["json", "rustls"] } +reqwest = { version = "0.13.5", default-features = false, features = ["json", "rustls"] } serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" thiserror = "2.0.20" diff --git a/src/key_value_stores/bigtable.rs b/src/key_value_stores/bigtable.rs index b6bcef6..2350e9e 100644 --- a/src/key_value_stores/bigtable.rs +++ b/src/key_value_stores/bigtable.rs @@ -3,12 +3,19 @@ use std::{ borrow::Cow, collections::HashMap, + fs, + path::{Path, PathBuf}, + sync::Arc, time::{Duration, Instant}, }; use anyhow::{format_err, Context}; use async_trait::async_trait; use bigtable_rs::bigtable::{self, BigTable as BigTableClient, BigTableConnection}; +use gcp_auth::TokenProvider; +use google_cloud_auth::credentials::{ + AccessTokenCredentials, Builder as ApplicationDefaultCredentialsBuilder, +}; use googleapis_tonic_google_bigtable_v2::google::bigtable::v2::{ mutate_rows_request::Entry, mutation::{self, SetCell}, @@ -16,7 +23,7 @@ use googleapis_tonic_google_bigtable_v2::google::bigtable::v2::{ MutateRowsRequest, Mutation, ReadRowsRequest, RowFilter, RowSet, }; use metrics::{counter, describe_histogram, histogram, Unit}; -use tracing::{instrument, trace}; +use tracing::{debug, instrument, trace}; use url::Url; use crate::{pipeline::CONCURRENCY, Result}; @@ -27,6 +34,163 @@ use super::{ const GEOCODE_CSV_FAMILY_NAME: &str = "geocode_csv"; const GEOCODE_CSV_COLUMN_NAME: &[u8] = b"v"; +const BIGTABLE_DATA_SCOPE: &str = "https://www.googleapis.com/auth/bigtable.data"; + +/// Where Application Default Credentials will be loaded from. +#[derive(Debug)] +enum ApplicationDefaultCredentialSource { + GoogleApplicationCredentials { + path: PathBuf, + credential_type: Option, + }, + WellKnownApplicationDefault { + path: PathBuf, + credential_type: Option, + }, + MetadataServer, +} + +impl ApplicationDefaultCredentialSource { + fn detect() -> Self { + if let Some(path) = std::env::var_os("GOOGLE_APPLICATION_CREDENTIALS") { + let path = PathBuf::from(path); + return Self::GoogleApplicationCredentials { + credential_type: Self::json_type_field(&path), + path, + }; + } + if let Some(path) = Self::well_known_adc_path() { + if path.is_file() { + return Self::WellKnownApplicationDefault { + credential_type: Self::json_type_field(&path), + path, + }; + } + } + Self::MetadataServer + } + + fn log(&self) { + match self { + Self::GoogleApplicationCredentials { + path, + credential_type, + } => match credential_type { + Some(credential_type) => { + debug!( + path = %path.display(), + credential_type = %credential_type, + "using GOOGLE_APPLICATION_CREDENTIALS" + ); + } + None => { + debug!( + path = %path.display(), + "using GOOGLE_APPLICATION_CREDENTIALS" + ); + } + }, + Self::WellKnownApplicationDefault { + path, + credential_type, + } => match credential_type { + Some(credential_type) => { + debug!( + path = %path.display(), + credential_type = %credential_type, + "using well-known application-default credentials" + ); + } + None => { + debug!( + path = %path.display(), + "using well-known application-default credentials" + ); + } + }, + Self::MetadataServer => { + debug!( + "using GCE/GKE metadata server for application-default credentials" + ); + } + } + } + + fn json_type_field(path: &Path) -> Option { + let json: serde_json::Value = + serde_json::from_str(&fs::read_to_string(path).ok()?).ok()?; + json.get("type")?.as_str().map(str::to_owned) + } + + fn well_known_adc_path() -> Option { + #[cfg(target_os = "windows")] + { + std::env::var_os("APPDATA").map(|root| { + PathBuf::from(root).join("gcloud/application_default_credentials.json") + }) + } + #[cfg(not(target_os = "windows"))] + { + std::env::var_os("HOME").map(|root| { + PathBuf::from(root) + .join(".config/gcloud/application_default_credentials.json") + }) + } + } +} + +/// `google-cloud-auth` credentials exposed as the `gcp_auth::TokenProvider` +/// `bigtable_rs` expects. +#[derive(Debug)] +struct GoogleCloudAuthTokenProvider { + credentials: AccessTokenCredentials, + project_id: Arc, +} + +impl GoogleCloudAuthTokenProvider { + fn from_application_default_credentials(project_id: &str) -> Result { + ApplicationDefaultCredentialSource::detect().log(); + Ok(Self { + credentials: ApplicationDefaultCredentialsBuilder::default() + .with_scopes([BIGTABLE_DATA_SCOPE]) + .build_access_token_credentials() + .context("failed to load Google Application Default Credentials")?, + project_id: Arc::from(project_id), + }) + } +} + +#[async_trait] +impl TokenProvider for GoogleCloudAuthTokenProvider { + async fn token( + &self, + _scopes: &[&str], + ) -> std::result::Result, gcp_auth::Error> { + // gcp_auth::Token has no public constructor; it only implements Deserialize. + serde_json::from_value(serde_json::json!({ + "access_token": self + .credentials + .access_token() + .await + .map_err(|err| { + gcp_auth::Error::Other( + "failed to get Google Cloud access token", + Box::new(err), + ) + })? + .token, + "expires_in": 3600, + })) + .map(Arc::new) + .map_err(|err| { + gcp_auth::Error::Json("failed to construct gcp_auth token", err) + }) + } + + async fn project_id(&self) -> std::result::Result, gcp_auth::Error> { + Ok(self.project_id.clone()) + } +} /// BigTable configuration information. struct BigTableConfig { @@ -139,14 +303,29 @@ impl KeyValueStoreNew for BigTable { "Time required for BigTable MutateRows requests" ); let config = BigTableConfig::from_url(&url)?; - let connection = BigTableConnection::new( - &config.project_id, - &config.instance_id, - /* read_only */ false, - CONCURRENCY, - Some(Duration::from_secs(60)), - ) - .await + let timeout = Some(Duration::from_secs(60)); + let connection = match std::env::var("BIGTABLE_EMULATOR_HOST") { + Ok(emulator_endpoint) => BigTableConnection::new_with_emulator( + emulator_endpoint.as_str(), + &config.project_id, + &config.instance_id, + /* read_only */ false, + CONCURRENCY, + timeout, + ), + Err(_) => BigTableConnection::new_with_token_provider( + &config.project_id, + &config.instance_id, + /* read_only */ false, + CONCURRENCY, + timeout, + Arc::new( + GoogleCloudAuthTokenProvider::from_application_default_credentials( + &config.project_id, + )?, + ), + ), + } .context("could not connect to BigTable")?; Ok(BigTable { @@ -369,3 +548,219 @@ fn bigtable_error_cause_for_metrics(err: &bigtable::Error) -> Cow<'static, str> bigtable::Error::InvalidArgument(_) => Cow::Borrowed("invalid argument"), } } + +#[cfg(test)] +mod application_default_credentials_tests { + use super::*; + use scoped_env::ScopedEnv; + use serial_test::serial; + use std::io::Write; + use tempfile::NamedTempFile; + + const SERVICE_ACCOUNT_JSON: &str = r#"{ + "type": "service_account", + "project_id": "test-project-id", + "private_key_id": "test-private-key-id", + "private_key": "-----BEGIN PRIVATE KEY-----\nBLAHBLAHBLAH\n-----END PRIVATE KEY-----\n", + "client_email": "test-client-email@test-project-id.iam.gserviceaccount.com", + "client_id": "1234567890", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "universe_domain": "googleapis.com" + }"#; + + const AUTHORIZED_USER_JSON: &str = r#"{ + "type": "authorized_user", + "client_id": "test-client-id.apps.googleusercontent.com", + "client_secret": "test-client-secret", + "refresh_token": "test-refresh-token" + }"#; + + const IMPERSONATED_SERVICE_ACCOUNT_JSON: &str = r#"{ + "type": "impersonated_service_account", + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/test-principal@test-project-id.iam.gserviceaccount.com:generateAccessToken", + "delegates": [], + "source_credentials": { + "type": "authorized_user", + "client_id": "test-client-id.apps.googleusercontent.com", + "client_secret": "test-client-secret", + "refresh_token": "test-refresh-token" + } + }"#; + + const EXTERNAL_ACCOUNT_JSON: &str = r#"{ + "type": "external_account", + "audience": "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/test-pool/providers/test-provider", + "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", + "token_url": "https://sts.googleapis.com/v1/token", + "credential_source": { + "file": "/tmp/geocode-csv-external-account-subject-token.jwt" + } + }"#; + + fn write_fixture(contents: &str) -> NamedTempFile { + let mut file = NamedTempFile::new().expect("tempfile"); + file.write_all(contents.as_bytes()).expect("write fixture"); + file + } + + fn token_provider_from_google_application_credentials( + contents: &str, + ) -> Result { + let file = write_fixture(contents); + let _google_application_credentials = ScopedEnv::set( + "GOOGLE_APPLICATION_CREDENTIALS", + file.path().to_str().expect("utf-8 path"), + ); + GoogleCloudAuthTokenProvider::from_application_default_credentials( + "test-project", + ) + } + + fn credentials_debug_name( + token_provider: &GoogleCloudAuthTokenProvider, + ) -> String { + format!("{:?}", token_provider.credentials) + } + + #[tokio::test] + #[serial] + async fn constructs_service_account_from_google_application_credentials() { + let token_provider = + token_provider_from_google_application_credentials(SERVICE_ACCOUNT_JSON) + .expect("service_account credentials should construct"); + let debug = credentials_debug_name(&token_provider); + assert!(debug.contains("ServiceAccountCredentials"), "{debug}"); + } + + #[tokio::test] + #[serial] + async fn constructs_authorized_user_from_google_application_credentials() { + let token_provider = + token_provider_from_google_application_credentials(AUTHORIZED_USER_JSON) + .expect("authorized_user credentials should construct"); + let debug = credentials_debug_name(&token_provider); + assert!(debug.contains("UserCredentials"), "{debug}"); + } + + #[tokio::test] + #[serial] + async fn constructs_impersonated_service_account_from_google_application_credentials( + ) { + let token_provider = token_provider_from_google_application_credentials( + IMPERSONATED_SERVICE_ACCOUNT_JSON, + ) + .expect("impersonated_service_account credentials should construct"); + let debug = credentials_debug_name(&token_provider); + assert!(debug.contains("ImpersonatedServiceAccount"), "{debug}"); + } + + #[tokio::test] + #[serial] + async fn constructs_external_account_from_google_application_credentials() { + let token_provider = + token_provider_from_google_application_credentials(EXTERNAL_ACCOUNT_JSON) + .expect("external_account credentials should construct"); + let debug = credentials_debug_name(&token_provider); + assert!( + debug.contains("FileSourcedCredentials") + || debug.contains("ExternalAccount"), + "{debug}" + ); + } + + #[test] + #[serial] + fn malformed_google_application_credentials_is_error() { + let err = token_provider_from_google_application_credentials("{ not json") + .expect_err("malformed credentials file should be an error"); + let message = format!("{err:#}"); + assert!( + message.contains("GOOGLE_APPLICATION_CREDENTIALS") + || message.contains("parse") + || message.contains("type") + || message.contains("expected"), + "{message}" + ); + } + + #[test] + #[serial] + fn missing_google_application_credentials_file_names_the_path() { + let missing_path = + "/tmp/geocode-csv-missing-adc-credentials-do-not-create.json"; + let _google_application_credentials = + ScopedEnv::set("GOOGLE_APPLICATION_CREDENTIALS", missing_path); + let err = GoogleCloudAuthTokenProvider::from_application_default_credentials( + "test-project", + ) + .expect_err("missing GOOGLE_APPLICATION_CREDENTIALS file should be an error"); + let message = format!("{err:#}"); + assert!( + message.contains("geocode-csv-missing-adc-credentials-do-not-create.json"), + "{message}" + ); + } + + #[test] + #[serial] + fn application_default_source_names_google_application_credentials_type() { + let file = write_fixture(IMPERSONATED_SERVICE_ACCOUNT_JSON); + let _google_application_credentials = ScopedEnv::set( + "GOOGLE_APPLICATION_CREDENTIALS", + file.path().to_str().expect("utf-8 path"), + ); + match ApplicationDefaultCredentialSource::detect() { + ApplicationDefaultCredentialSource::GoogleApplicationCredentials { + path, + credential_type, + } => { + assert_eq!(path, file.path()); + assert_eq!( + credential_type.as_deref(), + Some("impersonated_service_account") + ); + } + other => panic!("unexpected source: {other:?}"), + } + } + + #[test] + #[serial] + fn application_default_source_names_well_known_file_type() { + let home = tempfile::tempdir().expect("temp home"); + let well_known_path = home + .path() + .join(".config/gcloud/application_default_credentials.json"); + fs::create_dir_all(well_known_path.parent().expect("parent")) + .expect("gcloud config dir"); + fs::write(&well_known_path, EXTERNAL_ACCOUNT_JSON) + .expect("write well-known adc"); + let _home = ScopedEnv::set("HOME", home.path().to_str().expect("utf-8 path")); + let _google_application_credentials = + ScopedEnv::remove("GOOGLE_APPLICATION_CREDENTIALS"); + match ApplicationDefaultCredentialSource::detect() { + ApplicationDefaultCredentialSource::WellKnownApplicationDefault { + path, + credential_type, + } => { + assert_eq!(path, well_known_path); + assert_eq!(credential_type.as_deref(), Some("external_account")); + } + other => panic!("unexpected source: {other:?}"), + } + } + + #[test] + #[serial] + fn application_default_source_falls_back_to_metadata_server() { + let home = tempfile::tempdir().expect("temp home"); + let _home = ScopedEnv::set("HOME", home.path().to_str().expect("utf-8 path")); + let _google_application_credentials = + ScopedEnv::remove("GOOGLE_APPLICATION_CREDENTIALS"); + match ApplicationDefaultCredentialSource::detect() { + ApplicationDefaultCredentialSource::MetadataServer => {} + other => panic!("unexpected source: {other:?}"), + } + } +}