Crate kdb[−][src]
rust-kdb is an idiomatic Rust wrapper around the KDB+ C API. It supports manipulating K objects efficiently using zero cost abstractions, conversion to and from rust native types, and creation and editing of K lists/dictionaries using iterators.
The design goals of the library:
- Performance
- Provide an idiomatic rust API
- Safety
Why you might like it
- It's really fast. The abstractions around the KDB types have zero overhead so while it feels like you are using rust types with all the trimmings, it is as fast as calling the raw C API directly.
- It's safe! Using the C API is full of pitfalls that cause undefined behaviour. The abstractions in rust-kdb manage these for you, so that you don't need to worry about freeing your KDB objects or weird behaviour.
- It's just like using other rust data types. We've worked hard to make Lists work like Rust vectors, and to add similar convenience functions to dictionaries.
Why you might not like it
- Type conversions are common. It's not unusual to see rust-kdb code littered with
.try_into().unwrap()
Especially when working with mixed lists. This is a consequence of retrofitting the kdb type system into Rust. These type conversions are cheap (from/into are free, try_from/try_into are a single check of the KDB type code) But they do dirty the code somewhat. - It's incomplete. It currently lacks support for tables and not all functions have been included. The plan is to include these features in time.
Creating KDB types
KDB deals with atoms and lists.
rust-kdb maps this to the Atom And List generic types.
We create a kdb type using a KBox
. Just like a Rust Box
wraps
Rust heap managed pointers, KBox wraps KDB managed pointers.
To create a new 32-bit integer atom:
use kdb::KBox; let a = KBox::new_atom(42); assert_eq!(a.value(), 42);
To create a list of bytes:
let mut l = KBox::<List<u8>>::new_list(); for i in 1..=10 { l.push(i); } assert_eq!(l.len(), 10);
Working with unknown types
KDB is dynamically typed, in that each type is an instance of a k object
This is similar to variant types in C++. In rust-kdb, we manage this with
the Any
type.
The Any
type can be used in place of any valid KDB value (atom or list).
You can't do much with it, except try to convert it to a different type, using
the TryFrom
/TryInto
traits.
use kdb::*; use std::convert::{TryFrom, TryInto}; let a = KBox::new_atom(42); let b: KBox<Any> = a.into(); let c: KBox<Atom<i32>> = b.try_into().unwrap();
Writing embedded KDB plug-ins
Writing embedded plugins is straightforward using rust-kdb. Youll need to use the "embedded" feature for your plugin to use the correct library bindings.
Below is an example of a simple KDB plugin
use kdb::*; use std::convert::TryFrom; use std::f64::consts::PI; /// Calculates the circumference of a circle. Returns a null value if the radius is not a real number. #[no_mangle] pub extern "C" fn circumference(radius: &Any) -> Option<KBox<Atom<f64>>> { if let Ok(r) = <&Atom<f64>>::try_from(radius) { return Some(KBox::new_atom(r.value() * r.value() * PI)); } None }
Key points:
- Note that KDB parameters in extern "C" functions are references to KDB types, rather than a KBox. In KDB, the caller owns the parameters. Using a KBox here will likely cause a segfault.
- The return type is always either a KBox
or Option<KBox >. This is equivalent to returning a K pointer. Always return an owned type. - You can use typed atoms for parameters, not just Any. Bear in mind that this is unsafe as it is possible for q code to call the function with a type other than that one. Any is always safest.
Re-exports
pub use array_iterator; |
pub use uuid; |
Modules
kapi | Provides ffi definitions for the KDB C API. |
Macros
cast | Cast a KBox |
list | Create a list from a set of supplied values. |
Structs
Any | Any represents any KDB value regardless of type. Unlike atoms or lists you can't do anything with it, except for convert it into an atom or a list. It is ABI compatible with a K object, so it can be safely used as a parameter or return type for a function. See the chapter on embedded functions for more information. |
Atom | Atoms are the base primitive values in rust-kdb. You can create a new atom by calling
|
Connection | Represents a connection to a remote or embedded KDB instance, which can be used to send and query data on that instance. |
Date | Represents the number of days since 1 Jan 2000. |
DateTime | Represents a date and time in KDB. Conversions between the Unix Epoch and the KDB Epoch are done automatically. |
Dictionary | A key value based dictionary. |
KBox | Represents a memory managed K pointer. They are the
KDB equivalent of a Rust Box, a zero overhead wrapper
around a K pointer. It will call |
KError | Represents an error in KDB. |
List | Lists are the KDB equivalent of Rust's |
Minute | Represents the number of minutes since midnight (00:00). |
Month | The number of months since January 2000. |
Second | Represents the number of seconds since midnight (00:00) |
Symbol | Represents a KDB Symbol (interned string) Implements basic symbol operations for efficiency Can be converted to/from strings |
Table | Represents a table (a dictionary of columns) in KDB |
Time | The number of milliseconds since midnight. |
Timespan | Represents an elapsed span of time |
Timestamp | Represents a timestamp in KDB. Conversions between the Unix Epoch and the KDB Epoch are done automatically. |
Enums
ConnectionError | The error type for connecting to KDB. |
ConversionError | Error type for converting from/to kdb types. |
Error | The error type for Q query execution. |
SerializationMode | Describes how to perform serialization when using |
Functions
b9_serialize | Serialize a K object using KDB serialization. |
d9_deserialize | Decode a serialized K object. |
init | [not-embedded] Initialize the kdb memory subsystem. this is required when using generator functions
in a standalone kdb application. This is equivalent to calling |
symbol | Helper for succinctly creating a symbol. If the string passed in is not a valid symbol, i.e. it contains embedded nuls, then this function will panic. |