Skip to content

Commit

Permalink
REF: Separate out live protocol and msgs
Browse files Browse the repository at this point in the history
  • Loading branch information
threecgreen committed Sep 30, 2024
1 parent 13682cc commit 89d1c87
Show file tree
Hide file tree
Showing 6 changed files with 448 additions and 197 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 0.14.0 - TBD

#### Enhancements
- Made several previously internal functions public to allow advanced users more
customization and piecemeal usage of the live API:
- `ApiKey`
- `Symbols::to_chunked_api_string()`
- `live::protocol` module containing implementations of the raw API messages

## 0.13.0 - 2024-09-25

#### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion src/historical/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ impl ClientBuilder<Unset> {
/// This function returns an error when the API key is invalid.
pub fn key(self, key: impl ToString) -> crate::Result<ClientBuilder<ApiKey>> {
Ok(ClientBuilder {
key: crate::validate_key(key.to_string())?,
key: ApiKey::new(key.to_string())?,
base_url: self.base_url,
gateway: self.gateway,
})
Expand Down
72 changes: 46 additions & 26 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ impl Symbols {
}

#[cfg(feature = "live")]
pub(crate) fn to_chunked_api_string(&self) -> Vec<String> {
/// Splits the symbol into chunks to stay within the message length requirements of
/// the live gateway.
pub fn to_chunked_api_string(&self) -> Vec<String> {
const CHUNK_SIZE: usize = 128;
match self {
Symbols::All => vec![ALL_SYMBOLS.to_owned()],
Expand Down Expand Up @@ -160,31 +162,6 @@ impl From<Vec<&str>> for Symbols {
}
}

pub(crate) fn validate_key(key: String) -> crate::Result<ApiKey> {
if key == "$YOUR_API_KEY" {
Err(Error::bad_arg(
"key",
"got placeholder API key '$YOUR_API_KEY'. Please pass a real API key",
))
} else if key.len() != API_KEY_LENGTH {
Err(Error::bad_arg(
"key",
format!(
"expected to be 32-characters long, got {} characters",
key.len()
),
))
} else if !key.is_ascii() {
error!("API key '{key}' contains non-ASCII characters");
Err(Error::bad_arg(
"key",
"expected to be composed of only ASCII characters",
))
} else {
Ok(ApiKey(key))
}
}

pub(crate) fn key_from_env() -> crate::Result<String> {
std::env::var("DATABENTO_API_KEY").map_err(|e| {
Error::bad_arg(
Expand Down Expand Up @@ -241,6 +218,49 @@ impl fmt::Debug for ApiKey {
}
}

impl ApiKey {
/// Validates `key` meets requirements of an API key.
///
/// # Errors
/// This function returns an error if the key is invalid.
pub fn new(key: String) -> crate::Result<ApiKey> {
if key == "$YOUR_API_KEY" {
Err(Error::bad_arg(
"key",
"got placeholder API key '$YOUR_API_KEY'. Please pass a real API key",
))
} else if key.len() != API_KEY_LENGTH {
Err(Error::bad_arg(
"key",
format!(
"expected to be 32-characters long, got {} characters",
key.len()
),
))
} else if !key.is_ascii() {
error!("API key '{key}' contains non-ASCII characters");
Err(Error::bad_arg(
"key",
"expected to be composed of only ASCII characters",
))
} else {
Ok(ApiKey(key))
}
}

/// Returns a slice of the last 5 characters of the key.
#[cfg(feature = "live")]
pub fn bucket_id(&self) -> &str {
// Safe to splice because validated as only containing ASCII characters in [`Self::new()`]
&self.0[API_KEY_LENGTH - BUCKET_ID_LENGTH..]
}

/// Returns the entire key as a slice.
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}

#[cfg(test)]
const TEST_DATA_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data");
#[cfg(test)]
Expand Down
4 changes: 3 additions & 1 deletion src/live.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The Live client and related API types. Used for both real-time data and intraday historical.
mod client;
pub mod protocol;

use std::{net::SocketAddr, sync::Arc};

Expand All @@ -11,6 +12,7 @@ use tokio::net::{lookup_host, ToSocketAddrs};
use typed_builder::TypedBuilder;

use crate::{ApiKey, Symbols};

pub use client::Client;

/// A subscription for real-time or intraday historical data.
Expand Down Expand Up @@ -132,7 +134,7 @@ impl<D> ClientBuilder<Unset, D> {
pub fn key(self, key: impl ToString) -> crate::Result<ClientBuilder<ApiKey, D>> {
Ok(ClientBuilder {
addr: self.addr,
key: crate::validate_key(key.to_string())?,
key: ApiKey::new(key.to_string())?,
dataset: self.dataset,
send_ts_out: self.send_ts_out,
upgrade_policy: self.upgrade_policy,
Expand Down
Loading

0 comments on commit 89d1c87

Please sign in to comment.