#![allow(
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::too_many_lines,
clippy::option_if_let_else,
clippy::manual_let_else
)]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(feature = "connectors")]
pub mod connector;
#[cfg(feature = "connectors")]
pub mod connectors;
mod error;
mod in_memory;
mod model;
#[cfg(feature = "persistent")]
mod persistent;
mod store;
#[cfg(feature = "connectors")]
pub use connector::{
Column, ColumnType, Connector, ConnectorAuth, ConnectorConfig, FileConnector, PullStream,
Schema, SslMode, SyncStrategy,
};
#[cfg(feature = "connectors")]
pub use connectors::{MysqlConnector, PostgresConnector};
pub use error::{ThingdError, ThingdResult};
pub use in_memory::MemoryEngine;
pub use model::{
AggregateFunction, AggregateGroupResult, AggregateOptions, AggregateResult, CollectionSchema,
DEFAULT_QUEUE_LEASE_MS, FieldSchema, Link, LinkDirection, LinkQueryOptions, ListEventsOptions,
ListObjectsOptions, MemoryEvent, MemoryObject, ObjectKey, PutObjectOptions, QueueClaimOptions,
QueueJob, QueueJobStatus, QueueNackOptions, SchemaOptions, SearchHit, SearchOptions, SortBy,
SortDirection, TimeBucket, TimeSeriesBucket, TimeSeriesOptions, TimeSeriesResult,
VectorSearchHit, VectorSearchOptions,
};
#[cfg(feature = "persistent")]
#[cfg_attr(docsrs, doc(cfg(feature = "persistent")))]
pub use persistent::PersistentEngine;
pub use store::{
AggregateStore, EventLog, LinkStore, ObjectStore, QueueStore, Searcher, ThingStore, VectorStore,
};
#[cfg(test)]
pub(crate) mod contract_tests;
pub(crate) fn unix_timestamp_millis() -> i64 {
let Ok(duration) = SystemTime::now().duration_since(UNIX_EPOCH) else {
#[cfg(debug_assertions)]
panic!("SystemTime::now is before UNIX epoch — clock is broken");
#[cfg(not(debug_assertions))]
{
return 0;
}
};
i64::try_from(duration.as_millis()).unwrap_or(i64::MAX)
}
pub(crate) fn u64_to_i64(value: u64) -> i64 {
i64::try_from(value).unwrap_or(i64::MAX)
}
pub(crate) fn now_iso_string() -> String {
chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Millis, true)
}
pub(crate) fn cosine_similarity(a: &[f32], b: &[f32]) -> f64 {
if a.len() != b.len() || a.is_empty() {
return 0.0;
}
let dot: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
let norm_a: f32 = a.iter().map(|x| x * x).sum::<f32>().sqrt();
let norm_b: f32 = b.iter().map(|x| x * x).sum::<f32>().sqrt();
if norm_a == 0.0 || norm_b == 0.0 {
return 0.0;
}
f64::from(dot / (norm_a * norm_b))
}